From 8493948ba13315c92db9f0e40c189dc7d99ce410 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 15 Aug 2018 14:06:07 +0200 Subject: [PATCH 01/30] Add a favorite materials model Contributes to CURA-5162 --- cura/CuraApplication.py | 11 +++ .../Machines/Models/FavoriteMaterialsModel.py | 70 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 cura/Machines/Models/FavoriteMaterialsModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 23a11a2bb3..9823c0fadf 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -69,6 +69,7 @@ from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfile from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel +from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel from cura.Machines.Models.BrandMaterialsModel import BrandMaterialsModel from cura.Machines.Models.QualityManagementModel import QualityManagementModel @@ -501,6 +502,15 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/sidebar_collapsed", False) self._need_to_show_user_agreement = not self.getPreferences().getValue("general/accepted_user_agreement") + favorites = [ + "ultimaker_cpe_green_ultimaker_s5_AA_0.4", + "ultimaker_pla_green_ultimaker_s5_AA_0.4", + "ultimaker_abs_grey_ultimaker_s5_AA_0.4", + "an_incorrect_id" + ] + preferences.addPreference("cura/favorite_materials", favorites) + print("FAVORITES ARE NOW SET") + for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin @@ -931,6 +941,7 @@ class CuraApplication(QtApplication): qmlRegisterType(InstanceContainer, "Cura", 1, 0, "InstanceContainer") qmlRegisterType(ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") + qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel") qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel") diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py new file mode 100644 index 0000000000..f6932a61b8 --- /dev/null +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -0,0 +1,70 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from UM.Logger import Logger +from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel + +class FavoriteMaterialsModel(BaseMaterialsModel): + + def __init__(self, parent = None): + super().__init__(parent) + + from cura.CuraApplication import CuraApplication + self._preferences = CuraApplication.getInstance().getPreferences() + self._machine_manager = CuraApplication.getInstance().getMachineManager() + self._extruder_manager = CuraApplication.getInstance().getExtruderManager() + self._material_manager = CuraApplication.getInstance().getMaterialManager() + + self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. + self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. + + self._update() + + def _update(self): + Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) + + global_stack = self._machine_manager.activeMachine + if global_stack is None: + self.setItems([]) + return + extruder_position = str(self._extruder_position) + if extruder_position not in global_stack.extruders: + self.setItems([]) + return + extruder_stack = global_stack.extruders[extruder_position] + + available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) + if available_material_dict is None: + self.setItems([]) + return + + favorite_ids = self._preferences.getValue("cura/favorite_materials") + + item_list = [] + for root_material_id, container_node in available_material_dict.items(): + metadata = container_node.metadata + + # Only add results for favorite materials + if metadata["id"] not in favorite_ids: + continue + + # Do not include the materials from a to-be-removed package + if bool(metadata.get("removed", False)): + continue + + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "container_node": container_node + } + item_list.append(item) + + # Sort the item list by material name alphabetically + item_list = sorted(item_list, key = lambda d: d["name"].upper()) + + print("FINAL FAVORITE LIST:", item_list) + self.setItems(item_list) From 57d41216e174fe97093d240f8f7bcac5a51c21d8 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 16 Aug 2018 13:04:17 +0200 Subject: [PATCH 02/30] Remove dummy favorites Contributes to CURA-5162 --- cura/CuraApplication.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9823c0fadf..3cd49e591f 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -501,16 +501,9 @@ class CuraApplication(QtApplication): preferences.addPreference("view/filter_current_build_plate", False) preferences.addPreference("cura/sidebar_collapsed", False) - self._need_to_show_user_agreement = not self.getPreferences().getValue("general/accepted_user_agreement") - favorites = [ - "ultimaker_cpe_green_ultimaker_s5_AA_0.4", - "ultimaker_pla_green_ultimaker_s5_AA_0.4", - "ultimaker_abs_grey_ultimaker_s5_AA_0.4", - "an_incorrect_id" - ] - preferences.addPreference("cura/favorite_materials", favorites) - print("FAVORITES ARE NOW SET") + preferences.addPreference("cura/favorite_materials", []) + self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement") for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin From e8cda9002186e03e2c6c74405633a7cdd82906a5 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 16 Aug 2018 13:04:58 +0200 Subject: [PATCH 03/30] Add favorites to materials menu Contributes to CURA-5162 --- .../Machines/Models/FavoriteMaterialsModel.py | 3 +- resources/qml/Menus/MaterialMenu.qml | 158 +++++++++++------- 2 files changed, 95 insertions(+), 66 deletions(-) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index f6932a61b8..cbe59a1a09 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -45,7 +45,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): metadata = container_node.metadata # Only add results for favorite materials - if metadata["id"] not in favorite_ids: + if root_material_id not in favorite_ids: continue # Do not include the materials from a to-be-removed package @@ -66,5 +66,4 @@ class FavoriteMaterialsModel(BaseMaterialsModel): # Sort the item list by material name alphabetically item_list = sorted(item_list, key = lambda d: d["name"].upper()) - print("FINAL FAVORITE LIST:", item_list) self.setItems(item_list) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 64b3130724..a53bc72a94 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -14,68 +14,10 @@ Menu property int extruderIndex: 0 - Instantiator + Cura.FavoriteMaterialsModel { - model: genericMaterialsModel - MenuItem - { - text: model.name - checkable: true - checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] - exclusiveGroup: group - onTriggered: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - } - } - onObjectAdded: menu.insertItem(index, object) - onObjectRemoved: menu.removeItem(object) - } - MenuSeparator { } - Instantiator - { - model: brandModel - Menu - { - id: brandMenu - title: brandName - property string brandName: model.name - property var brandMaterials: model.materials - - Instantiator - { - model: brandMaterials - Menu - { - id: brandMaterialsMenu - title: materialName - property string materialName: model.name - property var brandMaterialColors: model.colors - - Instantiator - { - model: brandMaterialColors - MenuItem - { - text: model.name - checkable: true - checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] - exclusiveGroup: group - onTriggered: - { - Cura.MachineManager.setMaterial(extruderIndex, model.container_node); - } - } - onObjectAdded: brandMaterialsMenu.insertItem(index, object) - onObjectRemoved: brandMaterialsMenu.removeItem(object) - } - } - onObjectAdded: brandMenu.insertItem(index, object) - onObjectRemoved: brandMenu.removeItem(object) - } - } - onObjectAdded: menu.insertItem(index, object) - onObjectRemoved: menu.removeItem(object) + id: favoriteMaterialsModel + extruderPosition: menu.extruderIndex } Cura.GenericMaterialsModel @@ -90,9 +32,97 @@ Menu extruderPosition: menu.extruderIndex } - ExclusiveGroup { id: group } + Instantiator + { + model: favoriteMaterialsModel + delegate: MenuItem + { + text: model.brand + " " + model.name + checkable: true + checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] + onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) + exclusiveGroup: group + } + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem(object) // TODO: This ain't gonna work, removeItem() takes an index, not object + } - MenuSeparator { } + MenuSeparator {} - MenuItem { action: Cura.Actions.manageMaterials } + Menu + { + id: genericMenu + title: "Generic" + + Instantiator + { + model: genericMaterialsModel + delegate: MenuItem + { + text: model.name + checkable: true + checked: model.root_material_id == Cura.MachineManager.currentRootMaterialId[extruderIndex] + exclusiveGroup: group + onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) + } + onObjectAdded: genericMenu.insertItem(index, object) + onObjectRemoved: genericMenu.removeItem(object) // TODO: This ain't gonna work, removeItem() takes an index, not object + } + } + + MenuSeparator {} + + Instantiator + { + model: brandModel + Menu + { + id: brandMenu + title: brandName + property string brandName: model.name + property var brandMaterials: model.materials + + Instantiator + { + model: brandMaterials + delegate: Menu + { + id: brandMaterialsMenu + title: materialName + property string materialName: model.name + property var brandMaterialColors: model.colors + + Instantiator + { + model: brandMaterialColors + delegate: MenuItem + { + text: model.name + checkable: true + checked: model.id == Cura.MachineManager.allActiveMaterialIds[Cura.ExtruderManager.extruderIds[extruderIndex]] + exclusiveGroup: group + onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node) + } + onObjectAdded: brandMaterialsMenu.insertItem(index, object) + onObjectRemoved: brandMaterialsMenu.removeItem(object) + } + } + onObjectAdded: brandMenu.insertItem(index, object) + onObjectRemoved: brandMenu.removeItem(object) + } + } + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem(object) + } + + ExclusiveGroup { + id: group + } + + MenuSeparator {} + + MenuItem + { + action: Cura.Actions.manageMaterials + } } From 2410c21839d0b0ebbb74f9c3ba7c0b9c6f602e05 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 20 Aug 2018 17:16:05 +0200 Subject: [PATCH 04/30] Move material list to separate QML file Contributes to CURA-5378 --- resources/qml/Preferences/MaterialsList.qml | 266 ++++++++++++++++++++ resources/qml/Preferences/MaterialsPage.qml | 116 +-------- 2 files changed, 279 insertions(+), 103 deletions(-) create mode 100644 resources/qml/Preferences/MaterialsList.qml diff --git a/resources/qml/Preferences/MaterialsList.qml b/resources/qml/Preferences/MaterialsList.qml new file mode 100644 index 0000000000..db0f5461ec --- /dev/null +++ b/resources/qml/Preferences/MaterialsList.qml @@ -0,0 +1,266 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: materialList + UM.I18nCatalog { id: catalog; name: "cura"; } + Cura.BrandMaterialsModel { id: materialsModel } + Cura.GenericMaterialsModel { id: genericMaterialsModel } + + width: materialScrollView.width - 20 + height: childrenRect.height + + + Column + { + Rectangle + { + height: 23 + width: materialList.width + Label + { + text: "Generic" + } + } + Repeater + { + model: genericMaterialsModel + delegate: Rectangle + { + height: 23 + width: materialList.width + color: "green" + Label + { + text: model.name + } + } + } + Repeater + { + id: brand_list + + model: materialsModel + delegate: Rectangle + { + id: brand_section + property var expanded: true + property var types_model: model.materials + height: childrenRect.height + width: parent.width + Rectangle + { + id: brand_header_background + color: "grey" + anchors.fill: brand_header + } + Row + { + id: brand_header + width: parent.width + Label + { + id: brand_name + text: model.name + height: 24 + width: parent.width - 24 + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: 24 + implicitHeight: 24 + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: brand_header + onPressed: + { + brand_section.expanded = !brand_section.expanded + } + } + Column + { + anchors.top: brand_header.bottom + width: parent.width - leftPadding + anchors.left: parent.left + leftPadding: 8 + height: brand_section.expanded ? childrenRect.height : 0 + visible: brand_section.expanded + Repeater + { + model: types_model + delegate: Rectangle + { + id: material_type_section + property var expanded: true + property var colors_model: model.colors + height: childrenRect.height + width: parent.width + Rectangle + { + id: material_type_header_background + color: "grey" + anchors.bottom: material_type_header.bottom + height: 1 + width: parent.width + } + Row + { + id: material_type_header + width: parent.width + + Label + { + text: model.name + height: 24 + width: parent.width - 24 + id: material_type_name + verticalAlignment: Text.AlignVCenter + } + Button + { + text: "" + implicitWidth: 24 + implicitHeight: 24 + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: material_type_header + onPressed: + { + material_type_section.expanded = !material_type_section.expanded + } + } + Column + { + height: material_type_section.expanded ? childrenRect.height : 0 + visible: material_type_section.expanded + width: parent.width - leftPadding + anchors.top: material_type_header.bottom + leftPadding: 8 + anchors.left: parent.left + Repeater + { + model: colors_model + delegate: Rectangle + { + height: 24 + width: parent.width +// color: "green" + Row + { + height: parent.height + width: parent.width + Rectangle + { + id: swatch + color: model.color_code + border.width: 1 + border.color: "black" + width: 14 + height: 14 + anchors.verticalCenter: parent.verticalCenter + } + Label + { + text: model.name + verticalAlignment: Text.AlignVCenter + height: 24 + anchors.left: swatch.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 4 + } + MouseArea + { + anchors.fill: parent + onClicked: + { + print(model.guid) + } + } + Button + { + text: "+" + implicitWidth: 24 + implicitHeight: 24 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + onClicked: + { + if (model.is_favorite) { + base.materialManager.removeFavorite(model.root_material_id) + model.is_favorite = false + return + } + base.materialManager.addFavorite(model.root_material_id) + model.is_favorite = true + return + } + } + } + } + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index e2e3edec2f..07b5da3f4e 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -17,12 +17,19 @@ Item property QtObject materialManager: CuraApplication.getMaterialManager() property var resetEnabled: false // Keep PreferencesDialog happy - UM.I18nCatalog { id: catalog; name: "cura"; } - - Cura.MaterialManagementModel + UM.I18nCatalog + { + id: catalog + name: "cura" + } + Cura.BrandMaterialsModel { id: materialsModel } + Cura.GenericMaterialsModel + { + id: genericMaterialsModel + } Label { @@ -366,104 +373,7 @@ Item width: true ? (parent.width * 0.4) | 0 : parent.width frameVisible: true - ListView - { - id: materialListView - - model: materialsModel - - section.property: "brand" - section.criteria: ViewSection.FullString - section.delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: palette.light - - Label - { - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_lining").width - text: section - font.bold: true - color: palette.text - } - } - - delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase - - Row - { - id: materialRow - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - - property bool isCurrentItem: parent.ListView.isCurrentItem - - property bool isItemActivated: - { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; - } - - Rectangle - { - width: Math.floor(parent.height * 0.8) - height: Math.floor(parent.height * 0.8) - color: model.color_code - border.color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.floor((parent.width * 0.3)) - text: model.material - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.material) ? model.name : "" - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - } - - MouseArea - { - anchors.fill: parent - onClicked: - { - parent.ListView.view.currentIndex = model.index; - } - } - } - - function activateDetailsWithIndex(index) - { - var model = materialsModel.getItem(index); - base.currentItem = model; - materialDetailsView.containerId = model.container_id; - materialDetailsView.currentMaterialNode = model.container_node; - - detailsPanel.updateMaterialPropertiesObject(); - } - - onCurrentIndexChanged: - { - forceActiveFocus(); // causes the changed fields to be saved - activateDetailsWithIndex(currentIndex); - } - } + MaterialsList {} } @@ -480,9 +390,9 @@ Item right: parent.right } - function updateMaterialPropertiesObject() + function updateMaterialPropertiesObject( currentItem ) { - var currentItem = materialsModel.getItem(materialListView.currentIndex); +// var currentItem = materialsModel.getItem(materialListView.currentIndex); materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; materialProperties.guid = currentItem.guid; From 68bccd8bf7cf9a6382d988fa538f7fc958ab776b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 20 Aug 2018 17:16:54 +0200 Subject: [PATCH 05/30] Improve the Favorites, Base, and Brand materials models (WIP) Contribuetes to CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 4 ++ cura/Machines/Models/BrandMaterialsModel.py | 40 +++++++++++++------ .../Machines/Models/FavoriteMaterialsModel.py | 6 ++- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 4759c8b5b0..ceba1f6eeb 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -21,6 +21,8 @@ class BaseMaterialsModel(ListModel): MaterialRole = Qt.UserRole + 5 ColorRole = Qt.UserRole + 6 ContainerNodeRole = Qt.UserRole + 7 + ColorCodeRole = Qt.UserRole + 8 + GUIDRole = Qt.UserRole + 9 extruderPositionChanged = pyqtSignal() @@ -31,10 +33,12 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.RootMaterialIdRole, "root_material_id") self.addRoleName(self.IdRole, "id") + self.addRoleName(self.GUIDRole, "guid") self.addRoleName(self.NameRole, "name") self.addRoleName(self.BrandRole, "brand") self.addRoleName(self.MaterialRole, "material") self.addRoleName(self.ColorRole, "color_name") + self.addRoleName(self.ColorCodeRole, "color_code") self.addRoleName(self.ContainerNodeRole, "container_node") self._extruder_position = 0 diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index ad48b3ea21..c5edd6e57c 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -50,6 +50,7 @@ class BrandMaterialsModel(ListModel): self._extruder_stack = None from cura.CuraApplication import CuraApplication + self._container_registry = CuraApplication.getInstance().getContainerRegistry() self._machine_manager = CuraApplication.getInstance().getMachineManager() self._extruder_manager = CuraApplication.getInstance().getExtruderManager() self._material_manager = CuraApplication.getInstance().getMaterialManager() @@ -104,30 +105,45 @@ class BrandMaterialsModel(ListModel): brand_group_dict = {} for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata - brand = metadata["brand"] - # Only add results for generic materials - if brand.lower() == "generic": - continue + # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): continue + # Skip generic materials, and add brands we haven't seen yet to the dict + brand = metadata["brand"] + if brand.lower() == "generic": + continue if brand not in brand_group_dict: brand_group_dict[brand] = {} + # Add material types we haven't seen yet to the dict material_type = metadata["material"] if material_type not in brand_group_dict[brand]: brand_group_dict[brand][material_type] = [] - item = {"root_material_id": root_material_id, - "id": metadata["id"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "container_node": container_node - } + # Now handle the individual materials + item = { + "root_material_id": root_material_id, + # "root_material_id": container_node.metadata["base_file"] <- as written in material management model + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "guid": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), + "approximate_diameter": metadata["approximate_diameter"], + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": False + } brand_group_dict[brand][material_type].append(item) for brand, material_dict in brand_group_dict.items(): diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index cbe59a1a09..9d05f8cb4a 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -17,7 +17,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. - + self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _update(self): @@ -38,7 +38,9 @@ class FavoriteMaterialsModel(BaseMaterialsModel): self.setItems([]) return - favorite_ids = self._preferences.getValue("cura/favorite_materials") + favorite_ids = self._material_manager.getFavorites() + + print("favorite_ids:", favorite_ids) item_list = [] for root_material_id, container_node in available_material_dict.items(): From 6d1fd8281ca0d5bd267b68c1fdc13922da98bab1 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 20 Aug 2018 17:17:14 +0200 Subject: [PATCH 06/30] Add favorites funcitonality to MaterialManager.py Contributes to CURA-5378 --- cura/Machines/MaterialManager.py | 40 +++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index d5a7d5d089..d59aa07590 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -4,6 +4,7 @@ from collections import defaultdict, OrderedDict import copy import uuid +import json from typing import Dict, Optional, TYPE_CHECKING from PyQt5.Qt import QTimer, QObject, pyqtSignal, pyqtSlot @@ -38,7 +39,8 @@ if TYPE_CHECKING: # class MaterialManager(QObject): - materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated. + materialsUpdated = pyqtSignal() # Emitted whenever the material lookup tables are updated. + favoritesUpdated = pyqtSignal() # Emitted whenever the favorites are changed def __init__(self, container_registry, parent = None): super().__init__(parent) @@ -75,6 +77,8 @@ class MaterialManager(QObject): self._container_registry.containerAdded.connect(self._onContainerMetadataChanged) self._container_registry.containerRemoved.connect(self._onContainerMetadataChanged) + self._favorites = set() + def initialize(self): # Find all materials and put them in a matrix for quick search. material_metadatas = {metadata["id"]: metadata for metadata in @@ -194,6 +198,14 @@ class MaterialManager(QObject): self.materialsUpdated.emit() + favorites = self._application.getPreferences().getValue("cura/favorite_materials") + print(favorites) + for item in favorites: + print(item) + self._favorites.add(item) + print("LOADED FAVES", self._favorites) + self.favoritesUpdated.emit() + def __addMaterialMetadataIntoLookupTree(self, material_metadata: dict) -> None: material_id = material_metadata["id"] @@ -608,3 +620,29 @@ class MaterialManager(QObject): new_base_id = new_id, new_metadata = new_metadata) return new_id + + @pyqtSlot(str) + def addFavorite(self, root_material_id: str): + print(root_material_id) + self._favorites.add(root_material_id) + self.favoritesUpdated.emit() + print(self._favorites) + print(list(self._favorites)) + + # Ensure all settings are saved. + self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.saveSettings() + + @pyqtSlot(str) + def removeFavorite(self, root_material_id: str): + self._favorites.remove(root_material_id) + self.favoritesUpdated.emit() + print(self._favorites) + + # Ensure all settings are saved. + self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.saveSettings() + + @pyqtSlot() + def getFavorites(self): + return self._favorites \ No newline at end of file From 08b325ee0484da12b1afb632de7c681bae6f482b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:31:48 +0200 Subject: [PATCH 07/30] Correctly load material favorites from preferences Contributes to CURA-5378, CURA-5162 --- cura/CuraApplication.py | 2 +- cura/Machines/MaterialManager.py | 13 +++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 3cd49e591f..27f558bc41 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -501,7 +501,7 @@ class CuraApplication(QtApplication): preferences.addPreference("view/filter_current_build_plate", False) preferences.addPreference("cura/sidebar_collapsed", False) - preferences.addPreference("cura/favorite_materials", []) + preferences.addPreference("cura/favorite_materials", ";".join([])) self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement") diff --git a/cura/Machines/MaterialManager.py b/cura/Machines/MaterialManager.py index d59aa07590..1463f2e40e 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -199,11 +199,8 @@ class MaterialManager(QObject): self.materialsUpdated.emit() favorites = self._application.getPreferences().getValue("cura/favorite_materials") - print(favorites) - for item in favorites: - print(item) + for item in favorites.split(";"): self._favorites.add(item) - print("LOADED FAVES", self._favorites) self.favoritesUpdated.emit() def __addMaterialMetadataIntoLookupTree(self, material_metadata: dict) -> None: @@ -623,24 +620,20 @@ class MaterialManager(QObject): @pyqtSlot(str) def addFavorite(self, root_material_id: str): - print(root_material_id) self._favorites.add(root_material_id) self.favoritesUpdated.emit() - print(self._favorites) - print(list(self._favorites)) # Ensure all settings are saved. - self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites))) self._application.saveSettings() @pyqtSlot(str) def removeFavorite(self, root_material_id: str): self._favorites.remove(root_material_id) self.favoritesUpdated.emit() - print(self._favorites) # Ensure all settings are saved. - self._application.getPreferences().setValue("cura/favorite_materials", list(self._favorites)) + self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites))) self._application.saveSettings() @pyqtSlot() From cb713eea6ae7b9bf9146e079da3cf4dd21400038 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:33:29 +0200 Subject: [PATCH 08/30] Improve models Contributes to CURA-5162, CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 2 ++ cura/Machines/Models/BrandMaterialsModel.py | 4 +++- .../Machines/Models/FavoriteMaterialsModel.py | 9 ++++---- cura/Machines/Models/GenericMaterialsModel.py | 21 ++++++++++++------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ceba1f6eeb..ebf87e26b3 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -23,6 +23,7 @@ class BaseMaterialsModel(ListModel): ContainerNodeRole = Qt.UserRole + 7 ColorCodeRole = Qt.UserRole + 8 GUIDRole = Qt.UserRole + 9 + IsFavoriteRole = Qt.UserRole + 10 extruderPositionChanged = pyqtSignal() @@ -40,6 +41,7 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.ColorRole, "color_name") self.addRoleName(self.ColorCodeRole, "color_code") self.addRoleName(self.ContainerNodeRole, "container_node") + self.addRoleName(self.IsFavoriteRole, "is_favorite") self._extruder_position = 0 self._extruder_stack = None diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index c5edd6e57c..1eb76ca33c 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -58,6 +58,7 @@ class BrandMaterialsModel(ListModel): self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. + # self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _updateExtruderStack(self): @@ -106,6 +107,7 @@ class BrandMaterialsModel(ListModel): for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata + favorites = self._material_manager.getFavorites() # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): @@ -142,7 +144,7 @@ class BrandMaterialsModel(ListModel): "adhesion_info": metadata["adhesion_info"], "is_read_only": self._container_registry.isReadOnly(metadata["id"]), "container_node": container_node, - "is_favorite": False + "is_favorite": root_material_id in favorites } brand_group_dict[brand][material_type].append(item) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 9d05f8cb4a..d9ca69f4e1 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -27,6 +27,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): if global_stack is None: self.setItems([]) return + extruder_position = str(self._extruder_position) if extruder_position not in global_stack.extruders: self.setItems([]) @@ -40,8 +41,6 @@ class FavoriteMaterialsModel(BaseMaterialsModel): favorite_ids = self._material_manager.getFavorites() - print("favorite_ids:", favorite_ids) - item_list = [] for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata @@ -61,11 +60,13 @@ class FavoriteMaterialsModel(BaseMaterialsModel): "brand": metadata["brand"], "material": metadata["material"], "color_name": metadata["color_name"], - "container_node": container_node + "color_code": metadata["color_code"], + "container_node": container_node, + "is_favorite": True } item_list.append(item) # Sort the item list by material name alphabetically - item_list = sorted(item_list, key = lambda d: d["name"].upper()) + item_list = sorted(item_list, key = lambda d: d["brand"].upper()) self.setItems(item_list) diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index f14b039c91..90c8d43026 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -38,6 +38,8 @@ class GenericMaterialsModel(BaseMaterialsModel): self.setItems([]) return + favorites = self._material_manager.getFavorites() + item_list = [] for root_material_id, container_node in available_material_dict.items(): metadata = container_node.metadata @@ -50,14 +52,17 @@ class GenericMaterialsModel(BaseMaterialsModel): if bool(metadata.get("removed", False)): continue - item = {"root_material_id": root_material_id, - "id": metadata["id"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "container_node": container_node - } + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "container_node": container_node, + "is_favorite": root_material_id in favorites + } item_list.append(item) # Sort the item list by material name alphabetically From 272e892179c7cdfe868cd0703e3e725da51fc552 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:33:55 +0200 Subject: [PATCH 09/30] Extend Cura Light theme for material favorites Contributes to CURA-5162, CURA-5378 --- .../themes/cura-light/icons/favorites_star_empty.svg | 8 ++++++++ .../themes/cura-light/icons/favorites_star_full.svg | 6 ++++++ resources/themes/cura-light/theme.json | 12 +++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 resources/themes/cura-light/icons/favorites_star_empty.svg create mode 100644 resources/themes/cura-light/icons/favorites_star_full.svg diff --git a/resources/themes/cura-light/icons/favorites_star_empty.svg b/resources/themes/cura-light/icons/favorites_star_empty.svg new file mode 100644 index 0000000000..bb1205e7a7 --- /dev/null +++ b/resources/themes/cura-light/icons/favorites_star_empty.svg @@ -0,0 +1,8 @@ + + + + + diff --git a/resources/themes/cura-light/icons/favorites_star_full.svg b/resources/themes/cura-light/icons/favorites_star_full.svg new file mode 100644 index 0000000000..aad45c5d02 --- /dev/null +++ b/resources/themes/cura-light/icons/favorites_star_full.svg @@ -0,0 +1,6 @@ + + + + + diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 7bcdafce98..c408146669 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -315,7 +315,13 @@ "tab_status_disconnected": [200, 200, 200, 255], "printer_config_matched": [12, 169, 227, 255], - "printer_config_mismatch": [127, 127, 127, 255] + "printer_config_mismatch": [127, 127, 127, 255], + + "favorites_header_bar": [245, 245, 245, 255], + "favorites_header_hover": [245, 245, 245, 255], + "favorites_header_text": [31, 36, 39, 255], + "favorites_header_text_hover": [31, 36, 39, 255], + "favorites_row_selected": [196, 239, 255, 255] }, "sizes": { @@ -372,6 +378,10 @@ "small_button": [2, 2], "small_button_icon": [1.5, 1.5], + "favorites_row": [2, 2], + "favorites_button": [2, 2], + "favorites_button_icon": [1.2, 1.2], + "printer_status_icon": [1.8, 1.8], "printer_sync_icon": [1.2, 1.2], From 00eb8e6788eb11bbe6d6f55f4c2c4d6839d36006 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 12:34:38 +0200 Subject: [PATCH 10/30] Organize material preferences Contributes to CURA-5378 --- resources/qml/Cura.qml | 2 +- .../Preferences/Materials/MaterialSlot.qml | 120 +++++ .../{ => Materials}/MaterialView.qml | 2 + .../Materials/MaterialsDetailsPanel.qml | 103 +++++ .../{ => Materials}/MaterialsList.qml | 265 +++++++---- .../{ => Materials}/MaterialsPage.qml | 422 +++++++----------- .../Preferences/Materials/OldMaterialList.qml | 98 ++++ 7 files changed, 656 insertions(+), 356 deletions(-) create mode 100644 resources/qml/Preferences/Materials/MaterialSlot.qml rename resources/qml/Preferences/{ => Materials}/MaterialView.qml (99%) create mode 100644 resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml rename resources/qml/Preferences/{ => Materials}/MaterialsList.qml (50%) rename resources/qml/Preferences/{ => Materials}/MaterialsPage.qml (67%) create mode 100644 resources/qml/Preferences/Materials/OldMaterialList.qml diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 60f6e77ea9..f1bb3188b3 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -541,7 +541,7 @@ UM.MainWindow insertPage(2, catalog.i18nc("@title:tab", "Printers"), Qt.resolvedUrl("Preferences/MachinesPage.qml")); - insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/MaterialsPage.qml")); + insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/Materials/MaterialsPage.qml")); insertPage(4, catalog.i18nc("@title:tab", "Profiles"), Qt.resolvedUrl("Preferences/ProfilesPage.qml")); diff --git a/resources/qml/Preferences/Materials/MaterialSlot.qml b/resources/qml/Preferences/Materials/MaterialSlot.qml new file mode 100644 index 0000000000..678a69bd54 --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialSlot.qml @@ -0,0 +1,120 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + id: material_slot + property var material + property var hovered: false + property var is_favorite: material.is_favorite + + height: UM.Theme.getSize("favorites_row").height + width: parent.width + color: base.currentItem == model ? UM.Theme.getColor("favorites_row_selected") : "transparent" + + Row + { + height: parent.height + width: parent.width + Rectangle + { + id: swatch + color: material.color_code + border.width: UM.Theme.getSize("default_lining").width + border.color: "black" + width: UM.Theme.getSize("favorites_button_icon").width + height: UM.Theme.getSize("favorites_button_icon").height + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + } + Label + { + text: material.brand + " " + material.name + verticalAlignment: Text.AlignVCenter + height: parent.height + anchors.left: swatch.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: UM.Theme.getSize("narrow_margin").width + } + MouseArea + { + anchors.fill: parent + onClicked: { base.currentItem = material } + hoverEnabled: true + onEntered: { material_slot.hovered = true } + onExited: { material_slot.hovered = false } + } + Button + { + id: favorite_button + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + visible: material_slot.hovered || material_slot.is_favorite || favorite_button.hovered + anchors + { + right: parent.right + verticalCenter: parent.verticalCenter + } + onClicked: + { + if (material_slot.is_favorite) { + base.materialManager.removeFavorite(material.root_material_id) + material_slot.is_favorite = false + return + } + base.materialManager.addFavorite(material.root_material_id) + material_slot.is_favorite = true + return + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("favorites_button_icon").width + height: UM.Theme.getSize("favorites_button_icon").height + sourceSize.width: width + sourceSize.height: height + color: + { + if (favorite_button.hovered) + { + return UM.Theme.getColor("primary_hover") + } + else + { + if (material_slot.is_favorite) + { + return UM.Theme.getColor("primary") + } + else + { + UM.Theme.getColor("text_inactive") + } + } + } + source: material_slot.is_favorite ? UM.Theme.getIcon("favorites_star_full") : UM.Theme.getIcon("favorites_star_empty") + } + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/Materials/MaterialView.qml similarity index 99% rename from resources/qml/Preferences/MaterialView.qml rename to resources/qml/Preferences/Materials/MaterialView.qml index 0929f1790a..c3503ae646 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/Materials/MaterialView.qml @@ -8,6 +8,8 @@ import QtQuick.Dialogs 1.2 import UM 1.2 as UM import Cura 1.0 as Cura +import ".." // Access to ReadOnlyTextArea.qml + TabView { id: base diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml new file mode 100644 index 0000000000..e18ae15201 --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -0,0 +1,103 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Item +{ + id: detailsPanel + + function updateMaterialPropertiesObject( currentItem ) + { +// var currentItem = materialsModel.getItem(materialListView.currentIndex); + + materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; + materialProperties.guid = currentItem.guid; + materialProperties.container_id = currentItem.container_id; + + materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; + materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; + materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; + materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; + + materialProperties.description = currentItem.description ? currentItem.description : ""; + materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; + + materialProperties.density = currentItem.density ? currentItem.density : 0.0; + materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; + materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; + } + + Item + { + anchors.fill: parent + + Item // Material title Label + { + id: profileName + + width: parent.width + height: childrenRect.height + + Label { + text: materialProperties.name + font: UM.Theme.getFont("large") + } + } + + MaterialView // Material detailed information view below the title Label + { + id: materialDetailsView + anchors + { + left: parent.left + right: parent.right + top: profileName.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + } + + editingEnabled: base.currentItem != null && !base.currentItem.is_read_only + + properties: materialProperties + containerId: base.currentItem != null ? base.currentItem.container_id : "" + currentMaterialNode: base.currentItem.container_node + + + } + + QtObject + { + id: materialProperties + + property string guid: "00000000-0000-0000-0000-000000000000" + property string container_id: "Unknown"; + property string name: "Unknown"; + property string profile_type: "Unknown"; + property string brand: "Unknown"; + property string material: "Unknown"; // This needs to be named as "material" to be consistent with + // the material container's metadata entry + + property string color_name: "Yellow"; + property color color_code: "yellow"; + + property real density: 0.0; + property real diameter: 0.0; + property string approximate_diameter: "0"; + + property real spool_cost: 0.0; + property real spool_weight: 0.0; + property real spool_length: 0.0; + property real cost_per_meter: 0.0; + + property string description: ""; + property string adhesion_info: ""; + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml similarity index 50% rename from resources/qml/Preferences/MaterialsList.qml rename to resources/qml/Preferences/Materials/MaterialsList.qml index db0f5461ec..a051f55cac 100644 --- a/resources/qml/Preferences/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -6,42 +6,174 @@ import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.2 + import UM 1.2 as UM import Cura 1.0 as Cura Item { id: materialList - UM.I18nCatalog { id: catalog; name: "cura"; } - Cura.BrandMaterialsModel { id: materialsModel } - Cura.GenericMaterialsModel { id: genericMaterialsModel } - - width: materialScrollView.width - 20 + width: materialScrollView.width - 17 height: childrenRect.height - + // Children + UM.I18nCatalog { id: catalog; name: "cura"; } + Cura.BrandMaterialsModel { id: materialsModel } + Cura.FavoriteMaterialsModel { id: favoriteMaterialsModel } + Cura.GenericMaterialsModel { id: genericMaterialsModel } Column { Rectangle { - height: 23 + property var expanded: true + + id: favorites_section + height: childrenRect.height width: materialList.width - Label + Rectangle { - text: "Generic" + id: favorites_header_background + color: UM.Theme.getColor("favorites_header_bar") + anchors.fill: favorites_header } - } - Repeater - { - model: genericMaterialsModel - delegate: Rectangle + Row { - height: 23 - width: materialList.width - color: "green" + id: favorites_header Label { - text: model.name + id: favorites_name + text: "Favorites" + height: UM.Theme.getSize("favorites_row").height + width: materialList.width - UM.Theme.getSize("favorites_button").width + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: favorites_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: favorites_header + onPressed: + { + favorites_section.expanded = !favorites_section.expanded + } + } + Column + { + anchors.top: favorites_header.bottom + anchors.left: parent.left + width: materialList.width + height: favorites_section.expanded ? childrenRect.height : 0 + visible: favorites_section.expanded + Repeater + { + model: favoriteMaterialsModel + delegate: MaterialSlot { + material: model + } + } + } + } + Rectangle + { + property var expanded: true + + id: generic_section + height: childrenRect.height + width: materialList.width + Rectangle + { + id: generic_header_background + color: UM.Theme.getColor("favorites_header_bar") + anchors.fill: generic_header + } + Row + { + id: generic_header + Label + { + id: generic_name + text: "Generic" + height: UM.Theme.getSize("favorites_row").height + width: materialList.width - UM.Theme.getSize("favorites_button").width + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: generic_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: generic_header + onPressed: + { + generic_section.expanded = !generic_section.expanded + } + } + Column + { + anchors.top: generic_header.bottom + width: materialList.width + anchors.left: parent.left + height: generic_section.expanded ? childrenRect.height : 0 + visible: generic_section.expanded + Repeater + { + model: genericMaterialsModel + delegate: MaterialSlot { + material: model + } } } } @@ -60,7 +192,7 @@ Item Rectangle { id: brand_header_background - color: "grey" + color: UM.Theme.getColor("favorites_header_bar") anchors.fill: brand_header } Row @@ -71,16 +203,16 @@ Item { id: brand_name text: model.name - height: 24 - width: parent.width - 24 + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width verticalAlignment: Text.AlignVCenter leftPadding: 4 } Button { text: "" - implicitWidth: 24 - implicitHeight: 24 + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height UM.RecolorImage { anchors { @@ -115,9 +247,8 @@ Item Column { anchors.top: brand_header.bottom - width: parent.width - leftPadding + width: parent.width anchors.left: parent.left - leftPadding: 8 height: brand_section.expanded ? childrenRect.height : 0 visible: brand_section.expanded Repeater @@ -133,29 +264,34 @@ Item Rectangle { id: material_type_header_background - color: "grey" + color: UM.Theme.getColor("lining") anchors.bottom: material_type_header.bottom - height: 1 - width: parent.width + anchors.left: material_type_header.left + height: UM.Theme.getSize("default_lining").height + width: material_type_header.width } Row { id: material_type_header - width: parent.width - + width: parent.width - 8 + anchors + { + left: parent.left + leftMargin: 8 + } Label { text: model.name - height: 24 - width: parent.width - 24 + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width id: material_type_name verticalAlignment: Text.AlignVCenter } Button { text: "" - implicitWidth: 24 - implicitHeight: 24 + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height UM.RecolorImage { anchors { @@ -191,69 +327,14 @@ Item { height: material_type_section.expanded ? childrenRect.height : 0 visible: material_type_section.expanded - width: parent.width - leftPadding + width: parent.width anchors.top: material_type_header.bottom - leftPadding: 8 anchors.left: parent.left Repeater { model: colors_model - delegate: Rectangle - { - height: 24 - width: parent.width -// color: "green" - Row - { - height: parent.height - width: parent.width - Rectangle - { - id: swatch - color: model.color_code - border.width: 1 - border.color: "black" - width: 14 - height: 14 - anchors.verticalCenter: parent.verticalCenter - } - Label - { - text: model.name - verticalAlignment: Text.AlignVCenter - height: 24 - anchors.left: swatch.right - anchors.verticalCenter: parent.verticalCenter - anchors.leftMargin: 4 - } - MouseArea - { - anchors.fill: parent - onClicked: - { - print(model.guid) - } - } - Button - { - text: "+" - implicitWidth: 24 - implicitHeight: 24 - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - onClicked: - { - if (model.is_favorite) { - base.materialManager.removeFavorite(model.root_material_id) - model.is_favorite = false - return - } - base.materialManager.addFavorite(model.root_material_id) - model.is_favorite = true - return - } - } - } + delegate: MaterialSlot { + material: model } } } diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml similarity index 67% rename from resources/qml/Preferences/MaterialsPage.qml rename to resources/qml/Preferences/Materials/MaterialsPage.qml index 07b5da3f4e..0e615a8d1b 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -9,13 +9,22 @@ import QtQuick.Dialogs 1.2 import UM 1.2 as UM import Cura 1.0 as Cura - Item { id: base property QtObject materialManager: CuraApplication.getMaterialManager() - property var resetEnabled: false // Keep PreferencesDialog happy + // Keep PreferencesDialog happy + property var resetEnabled: false + property var currentItem: null + property var isCurrentItemActivated: + { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return base.currentItem.root_material_id == root_material_id; + } + property string newRootMaterialIdToSwitchTo: "" + property bool toActivateNewMaterial: false UM.I18nCatalog { @@ -30,11 +39,72 @@ Item { id: genericMaterialsModel } + // Component.onCompleted: + // { + // // Select the activated material when this page shows up + // const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + // const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + // var itemIndex = -1; + // for (var i = 0; i < materialsModel.rowCount(); ++i) + // { + // var item = materialsModel.getItem(i); + // if (item.root_material_id == active_root_material_id) + // { + // itemIndex = i; + // break; + // } + // } + // materialListView.currentIndex = itemIndex; + // } + + // This connection makes sure that we will switch to the new + Connections + { + target: materialsModel + onItemsChanged: + { + var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id; + var position = Cura.ExtruderManager.activeExtruderIndex; + // try to pick the currently selected item; it may have been moved + if (base.newRootMaterialIdToSwitchTo == "") + { + base.newRootMaterialIdToSwitchTo = currentItemId; + } + + for (var idx = 0; idx < materialsModel.rowCount(); ++idx) + { + var item = materialsModel.getItem(idx); + if (item.root_material_id == base.newRootMaterialIdToSwitchTo) + { + // Switch to the newly created profile if needed + materialListView.currentIndex = idx; + materialListView.activateDetailsWithIndex(materialListView.currentIndex); + if (base.toActivateNewMaterial) + { + Cura.MachineManager.setMaterial(position, item.container_node); + } + base.newRootMaterialIdToSwitchTo = ""; + base.toActivateNewMaterial = false; + return + } + } + + materialListView.currentIndex = 0; + materialListView.activateDetailsWithIndex(materialListView.currentIndex); + if (base.toActivateNewMaterial) + { + Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node); + } + base.newRootMaterialIdToSwitchTo = ""; + base.toActivateNewMaterial = false; + } + } + + // Main layout Label { id: titleLabel - anchors { top: parent.top @@ -42,45 +112,12 @@ Item right: parent.right margins: 5 * screenScaleFactor } - font.pointSize: 18 text: catalog.i18nc("@title:tab", "Materials") } - property var hasCurrentItem: materialListView.currentItem != null - - property var currentItem: - { // is soon to be overwritten - var current_index = materialListView.currentIndex; - return materialsModel.getItem(current_index); - } - - property var isCurrentItemActivated: - { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return base.currentItem.root_material_id == root_material_id; - } - - Component.onCompleted: - { - // Select the activated material when this page shows up - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - var itemIndex = -1; - for (var i = 0; i < materialsModel.rowCount(); ++i) - { - var item = materialsModel.getItem(i); - if (item.root_material_id == active_root_material_id) - { - itemIndex = i; - break; - } - } - materialListView.currentIndex = itemIndex; - } - - Row // Button Row + // Button Row + Row { id: buttonRow anchors @@ -173,63 +210,102 @@ Item } } - property string newRootMaterialIdToSwitchTo: "" - property bool toActivateNewMaterial: false - - // This connection makes sure that we will switch to the new - Connections - { - target: materialsModel - onItemsChanged: + Item { + id: contentsItem + anchors { - var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id; - var position = Cura.ExtruderManager.activeExtruderIndex; - - // try to pick the currently selected item; it may have been moved - if (base.newRootMaterialIdToSwitchTo == "") - { - base.newRootMaterialIdToSwitchTo = currentItemId; - } - - for (var idx = 0; idx < materialsModel.rowCount(); ++idx) - { - var item = materialsModel.getItem(idx); - if (item.root_material_id == base.newRootMaterialIdToSwitchTo) - { - // Switch to the newly created profile if needed - materialListView.currentIndex = idx; - materialListView.activateDetailsWithIndex(materialListView.currentIndex); - if (base.toActivateNewMaterial) - { - Cura.MachineManager.setMaterial(position, item.container_node); - } - base.newRootMaterialIdToSwitchTo = ""; - base.toActivateNewMaterial = false; - return - } - } - - materialListView.currentIndex = 0; - materialListView.activateDetailsWithIndex(materialListView.currentIndex); - if (base.toActivateNewMaterial) - { - Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node); - } - base.newRootMaterialIdToSwitchTo = ""; - base.toActivateNewMaterial = false; + top: titleLabel.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + margins: 5 * screenScaleFactor + bottomMargin: 0 } + clip: true } + Item + { + anchors + { + top: buttonRow.bottom + topMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + bottom: parent.bottom + } + + SystemPalette { id: palette } + + Label + { + id: captionLabel + anchors + { + top: parent.top + left: parent.left + } + visible: text != "" + text: + { + var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; + if (Cura.MachineManager.hasVariants) + { + caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; + } + return caption; + } + width: materialScrollView.width + elide: Text.ElideRight + } + + ScrollView + { + id: materialScrollView + anchors + { + top: captionLabel.visible ? captionLabel.bottom : parent.top + topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 + bottom: parent.bottom + left: parent.left + } + + Rectangle + { + parent: viewport + anchors.fill: parent + color: palette.light + } + + width: true ? (parent.width * 0.4) | 0 : parent.width + frameVisible: true + verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn + + MaterialsList {} + } + + // MaterialsDetailsPanel + // { + // anchors + // { + // left: materialScrollView.right + // leftMargin: UM.Theme.getSize("default_margin").width + // top: parent.top + // bottom: parent.bottom + // right: parent.right + // } + // } + } + + // Dialogs MessageDialog { id: confirmRemoveMaterialDialog - icon: StandardIcon.Question; title: catalog.i18nc("@title:window", "Confirm Remove") text: catalog.i18nc("@label (%1 is object name)", "Are you sure you wish to remove %1? This cannot be undone!").arg(base.currentItem.name) standardButtons: StandardButton.Yes | StandardButton.No modality: Qt.ApplicationModal - onYes: { base.materialManager.removeMaterial(base.currentItem.container_node); @@ -299,184 +375,4 @@ Item { id: messageDialog } - - - Item { - id: contentsItem - - anchors - { - top: titleLabel.bottom - left: parent.left - right: parent.right - bottom: parent.bottom - margins: 5 * screenScaleFactor - bottomMargin: 0 - } - - clip: true - } - - Item - { - anchors - { - top: buttonRow.bottom - topMargin: UM.Theme.getSize("default_margin").height - left: parent.left - right: parent.right - bottom: parent.bottom - } - - SystemPalette { id: palette } - - Label - { - id: captionLabel - anchors - { - top: parent.top - left: parent.left - } - visible: text != "" - text: - { - var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName; - if (Cura.MachineManager.hasVariants) - { - caption += ", " + Cura.MachineManager.activeDefinitionVariantsName + ": " + Cura.MachineManager.activeVariantName; - } - return caption; - } - width: materialScrollView.width - elide: Text.ElideRight - } - - ScrollView - { - id: materialScrollView - anchors - { - top: captionLabel.visible ? captionLabel.bottom : parent.top - topMargin: captionLabel.visible ? UM.Theme.getSize("default_margin").height : 0 - bottom: parent.bottom - left: parent.left - } - - Rectangle - { - parent: viewport - anchors.fill: parent - color: palette.light - } - - width: true ? (parent.width * 0.4) | 0 : parent.width - frameVisible: true - - MaterialsList {} - } - - - Item - { - id: detailsPanel - - anchors - { - left: materialScrollView.right - leftMargin: UM.Theme.getSize("default_margin").width - top: parent.top - bottom: parent.bottom - right: parent.right - } - - function updateMaterialPropertiesObject( currentItem ) - { -// var currentItem = materialsModel.getItem(materialListView.currentIndex); - - materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; - materialProperties.guid = currentItem.guid; - materialProperties.container_id = currentItem.container_id; - - materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; - materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; - materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; - materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; - - materialProperties.description = currentItem.description ? currentItem.description : ""; - materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; - - materialProperties.density = currentItem.density ? currentItem.density : 0.0; - materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; - } - - Item - { - anchors.fill: parent - - Item // Material title Label - { - id: profileName - - width: parent.width - height: childrenRect.height - - Label { - text: materialProperties.name - font: UM.Theme.getFont("large") - } - } - - MaterialView // Material detailed information view below the title Label - { - id: materialDetailsView - anchors - { - left: parent.left - right: parent.right - top: profileName.bottom - topMargin: UM.Theme.getSize("default_margin").height - bottom: parent.bottom - } - - editingEnabled: base.currentItem != null && !base.currentItem.is_read_only - - properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.container_id : "" - currentMaterialNode: base.currentItem.container_node - - property alias pane: base - } - - QtObject - { - id: materialProperties - - property string guid: "00000000-0000-0000-0000-000000000000" - property string container_id: "Unknown"; - property string name: "Unknown"; - property string profile_type: "Unknown"; - property string brand: "Unknown"; - property string material: "Unknown"; // This needs to be named as "material" to be consistent with - // the material container's metadata entry - - property string color_name: "Yellow"; - property color color_code: "yellow"; - - property real density: 0.0; - property real diameter: 0.0; - property string approximate_diameter: "0"; - - property real spool_cost: 0.0; - property real spool_weight: 0.0; - property real spool_length: 0.0; - property real cost_per_meter: 0.0; - - property string description: ""; - property string adhesion_info: ""; - } - } - } - } } diff --git a/resources/qml/Preferences/Materials/OldMaterialList.qml b/resources/qml/Preferences/Materials/OldMaterialList.qml new file mode 100644 index 0000000000..6c15ddf7cc --- /dev/null +++ b/resources/qml/Preferences/Materials/OldMaterialList.qml @@ -0,0 +1,98 @@ +ListView +{ + id: materialListView + + model: materialsModel + + section.property: "brand" + section.criteria: ViewSection.FullString + section.delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: palette.light + + Label + { + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_lining").width + text: section + font.bold: true + color: palette.text + } + } + + delegate: Rectangle + { + width: materialScrollView.width + height: childrenRect.height + color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase + + Row + { + id: materialRow + spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + + property bool isCurrentItem: parent.ListView.isCurrentItem + + property bool isItemActivated: + { + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + return model.root_material_id == root_material_id; + } + + Rectangle + { + width: Math.floor(parent.height * 0.8) + height: Math.floor(parent.height * 0.8) + color: model.color_code + border.color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; + anchors.verticalCenter: parent.verticalCenter + } + Label + { + width: Math.floor((parent.width * 0.3)) + text: model.material + elide: Text.ElideRight + font.italic: materialRow.isItemActivated + color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; + } + Label + { + text: (model.name != model.material) ? model.name : "" + elide: Text.ElideRight + font.italic: materialRow.isItemActivated + color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; + } + } + + MouseArea + { + anchors.fill: parent + onClicked: + { + parent.ListView.view.currentIndex = model.index; + } + } + } + + function activateDetailsWithIndex(index) + { + var model = materialsModel.getItem(index); + base.currentItem = model; + materialDetailsView.containerId = model.container_id; + materialDetailsView.currentMaterialNode = model.container_node; + + detailsPanel.updateMaterialPropertiesObject(); + } + + onCurrentIndexChanged: + { + forceActiveFocus(); // causes the changed fields to be saved + activateDetailsWithIndex(currentIndex); + } +} From 6225fff1f852e57bc47282cfd81cc7f11dfc6e2d Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Wed, 22 Aug 2018 15:58:58 +0200 Subject: [PATCH 11/30] Re-added material detail view Contributes to CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 2 +- cura/Machines/Models/BrandMaterialsModel.py | 33 +++++++++-------- .../Machines/Models/FavoriteMaterialsModel.py | 1 + cura/Machines/Models/GenericMaterialsModel.py | 1 + .../Preferences/Materials/MaterialSlot.qml | 2 +- .../Preferences/Materials/MaterialView.qml | 2 +- .../Materials/MaterialsDetailsPanel.qml | 35 +++++++++---------- .../Preferences/Materials/MaterialsPage.qml | 26 +++++++------- 8 files changed, 51 insertions(+), 51 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ebf87e26b3..80ecf72c0a 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -34,7 +34,7 @@ class BaseMaterialsModel(ListModel): self.addRoleName(self.RootMaterialIdRole, "root_material_id") self.addRoleName(self.IdRole, "id") - self.addRoleName(self.GUIDRole, "guid") + self.addRoleName(self.GUIDRole, "GUID") self.addRoleName(self.NameRole, "name") self.addRoleName(self.BrandRole, "brand") self.addRoleName(self.MaterialRole, "material") diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py index 1eb76ca33c..154019d028 100644 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ b/cura/Machines/Models/BrandMaterialsModel.py @@ -127,24 +127,23 @@ class BrandMaterialsModel(ListModel): # Now handle the individual materials item = { - "root_material_id": root_material_id, - # "root_material_id": container_node.metadata["base_file"] <- as written in material management model - "id": metadata["id"], - "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml - "guid": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "description": metadata["description"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "density": metadata.get("properties", {}).get("density", ""), - "diameter": metadata.get("properties", {}).get("diameter", ""), + "root_material_id": root_material_id, + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), "approximate_diameter": metadata["approximate_diameter"], - "adhesion_info": metadata["adhesion_info"], - "is_read_only": self._container_registry.isReadOnly(metadata["id"]), - "container_node": container_node, - "is_favorite": root_material_id in favorites + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": root_material_id in favorites } brand_group_dict[brand][material_type].append(item) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index d9ca69f4e1..35a5229da1 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -56,6 +56,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): item = { "root_material_id": root_material_id, "id": metadata["id"], + "GUID": metadata["GUID"], "name": metadata["name"], "brand": metadata["brand"], "material": metadata["material"], diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index 90c8d43026..a8f5bfbd35 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -55,6 +55,7 @@ class GenericMaterialsModel(BaseMaterialsModel): item = { "root_material_id": root_material_id, "id": metadata["id"], + "GUID": metadata["GUID"], "name": metadata["name"], "brand": metadata["brand"], "material": metadata["material"], diff --git a/resources/qml/Preferences/Materials/MaterialSlot.qml b/resources/qml/Preferences/Materials/MaterialSlot.qml index 678a69bd54..ab0dd23750 100644 --- a/resources/qml/Preferences/Materials/MaterialSlot.qml +++ b/resources/qml/Preferences/Materials/MaterialSlot.qml @@ -21,7 +21,7 @@ Rectangle width: parent.width color: base.currentItem == model ? UM.Theme.getColor("favorites_row_selected") : "transparent" - Row + Item { height: parent.height width: parent.width diff --git a/resources/qml/Preferences/Materials/MaterialView.qml b/resources/qml/Preferences/Materials/MaterialView.qml index c3503ae646..1e5362567a 100644 --- a/resources/qml/Preferences/Materials/MaterialView.qml +++ b/resources/qml/Preferences/Materials/MaterialView.qml @@ -38,7 +38,7 @@ TabView if (!base.containerId || !base.editingEnabled) { return "" } - var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentMaterialNode, true); + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentItem.container_node, true); if (linkedMaterials.length == 0) { return "" } diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml index e18ae15201..fc8c6d728c 100644 --- a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -13,25 +13,24 @@ Item { id: detailsPanel + property var currentItem: base.currentItem + + onCurrentItemChanged: { updateMaterialPropertiesObject(currentItem) } + function updateMaterialPropertiesObject( currentItem ) { -// var currentItem = materialsModel.getItem(materialListView.currentIndex); - - materialProperties.name = currentItem.name ? currentItem.name : "Unknown"; - materialProperties.guid = currentItem.guid; - materialProperties.container_id = currentItem.container_id; - - materialProperties.brand = currentItem.brand ? currentItem.brand : "Unknown"; - materialProperties.material = currentItem.material ? currentItem.material : "Unknown"; - materialProperties.color_name = currentItem.color_name ? currentItem.color_name : "Yellow"; - materialProperties.color_code = currentItem.color_code ? currentItem.color_code : "yellow"; - - materialProperties.description = currentItem.description ? currentItem.description : ""; - materialProperties.adhesion_info = currentItem.adhesion_info ? currentItem.adhesion_info : ""; - - materialProperties.density = currentItem.density ? currentItem.density : 0.0; - materialProperties.diameter = currentItem.diameter ? currentItem.diameter : 0.0; - materialProperties.approximate_diameter = currentItem.approximate_diameter ? currentItem.approximate_diameter : "0"; + materialProperties.name = currentItem.name || "Unknown" + materialProperties.guid = currentItem.GUID; + materialProperties.container_id = currentItem.id + materialProperties.brand = currentItem.brand || "Unknown" + materialProperties.material = currentItem.material || "Unknown" + materialProperties.color_name = currentItem.color_name || "Yellow" + materialProperties.color_code = currentItem.color_code || "yellow" + materialProperties.description = currentItem.description || "" + materialProperties.adhesion_info = currentItem.adhesion_info || ""; + materialProperties.density = currentItem.density || 0.0 + materialProperties.diameter = currentItem.diameter || 0.0 + materialProperties.approximate_diameter = currentItem.approximate_diameter || "0" } Item @@ -66,7 +65,7 @@ Item editingEnabled: base.currentItem != null && !base.currentItem.is_read_only properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.container_id : "" + containerId: base.currentItem != null ? base.currentItem.id : "" currentMaterialNode: base.currentItem.container_node diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 0e615a8d1b..ce7203f34b 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -56,8 +56,8 @@ Item // } // materialListView.currentIndex = itemIndex; // } - - // This connection makes sure that we will switch to the new + + onCurrentItemChanged: { MaterialsDetailsPanel.currentItem = currentItem } Connections { target: materialsModel @@ -284,17 +284,17 @@ Item MaterialsList {} } - // MaterialsDetailsPanel - // { - // anchors - // { - // left: materialScrollView.right - // leftMargin: UM.Theme.getSize("default_margin").width - // top: parent.top - // bottom: parent.bottom - // right: parent.right - // } - // } + MaterialsDetailsPanel + { + anchors + { + left: materialScrollView.right + leftMargin: UM.Theme.getSize("default_margin").width + top: parent.top + bottom: parent.bottom + right: parent.right + } + } } // Dialogs From 8da77736006429d5e719402e2bdc52bdb0250181 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 23 Aug 2018 16:04:51 +0200 Subject: [PATCH 12/30] Remove unused code Contributes to CURA-5162, CURA-5378 --- cura/CuraApplication.py | 6 +- .../Models/MaterialManagementModel.py | 104 ------------------ .../Preferences/Materials/OldMaterialList.qml | 98 ----------------- 3 files changed, 2 insertions(+), 206 deletions(-) delete mode 100644 cura/Machines/Models/MaterialManagementModel.py delete mode 100644 resources/qml/Preferences/Materials/OldMaterialList.qml diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 27f558bc41..27c0350eea 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -68,10 +68,9 @@ from cura.Machines.Models.NozzleModel import NozzleModel from cura.Machines.Models.QualityProfilesDropDownMenuModel import QualityProfilesDropDownMenuModel from cura.Machines.Models.CustomQualityProfilesDropDownMenuModel import CustomQualityProfilesDropDownMenuModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel -from cura.Machines.Models.MaterialManagementModel import MaterialManagementModel from cura.Machines.Models.FavoriteMaterialsModel import FavoriteMaterialsModel from cura.Machines.Models.GenericMaterialsModel import GenericMaterialsModel -from cura.Machines.Models.BrandMaterialsModel import BrandMaterialsModel +from cura.Machines.Models.MaterialBrandsModel import MaterialBrandsModel from cura.Machines.Models.QualityManagementModel import QualityManagementModel from cura.Machines.Models.QualitySettingsModel import QualitySettingsModel from cura.Machines.Models.MachineManagementModel import MachineManagementModel @@ -936,8 +935,7 @@ class CuraApplication(QtApplication): qmlRegisterType(FavoriteMaterialsModel, "Cura", 1, 0, "FavoriteMaterialsModel") qmlRegisterType(GenericMaterialsModel, "Cura", 1, 0, "GenericMaterialsModel") - qmlRegisterType(BrandMaterialsModel, "Cura", 1, 0, "BrandMaterialsModel") - qmlRegisterType(MaterialManagementModel, "Cura", 1, 0, "MaterialManagementModel") + qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel") qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel") qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel") diff --git a/cura/Machines/Models/MaterialManagementModel.py b/cura/Machines/Models/MaterialManagementModel.py deleted file mode 100644 index 46e9cb887a..0000000000 --- a/cura/Machines/Models/MaterialManagementModel.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtCore import Qt - -from UM.Logger import Logger -from UM.Qt.ListModel import ListModel - - -# -# This model is for the Material management page. -# -class MaterialManagementModel(ListModel): - RootMaterialIdRole = Qt.UserRole + 1 - DisplayNameRole = Qt.UserRole + 2 - BrandRole = Qt.UserRole + 3 - MaterialTypeRole = Qt.UserRole + 4 - ColorNameRole = Qt.UserRole + 5 - ColorCodeRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 7 - ContainerIdRole = Qt.UserRole + 8 - - DescriptionRole = Qt.UserRole + 9 - AdhesionInfoRole = Qt.UserRole + 10 - ApproximateDiameterRole = Qt.UserRole + 11 - GuidRole = Qt.UserRole + 12 - DensityRole = Qt.UserRole + 13 - DiameterRole = Qt.UserRole + 14 - IsReadOnlyRole = Qt.UserRole + 15 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.RootMaterialIdRole, "root_material_id") - self.addRoleName(self.DisplayNameRole, "name") - self.addRoleName(self.BrandRole, "brand") - self.addRoleName(self.MaterialTypeRole, "material") - self.addRoleName(self.ColorNameRole, "color_name") - self.addRoleName(self.ColorCodeRole, "color_code") - self.addRoleName(self.ContainerNodeRole, "container_node") - self.addRoleName(self.ContainerIdRole, "container_id") - - self.addRoleName(self.DescriptionRole, "description") - self.addRoleName(self.AdhesionInfoRole, "adhesion_info") - self.addRoleName(self.ApproximateDiameterRole, "approximate_diameter") - self.addRoleName(self.GuidRole, "guid") - self.addRoleName(self.DensityRole, "density") - self.addRoleName(self.DiameterRole, "diameter") - self.addRoleName(self.IsReadOnlyRole, "is_read_only") - - from cura.CuraApplication import CuraApplication - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.globalContainerChanged.connect(self._update) - self._extruder_manager.activeExtruderChanged.connect(self._update) - self._material_manager.materialsUpdated.connect(self._update) - - self._update() - - def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - active_extruder_stack = self._machine_manager.activeStack - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - active_extruder_stack) - if available_material_dict is None: - self.setItems([]) - return - - material_list = [] - for root_material_id, container_node in available_material_dict.items(): - keys_to_fetch = ("name", - "brand", - "material", - "color_name", - "color_code", - "description", - "adhesion_info", - "approximate_diameter",) - - item = {"root_material_id": container_node.metadata["base_file"], - "container_node": container_node, - "guid": container_node.metadata["GUID"], - "container_id": container_node.metadata["id"], - "density": container_node.metadata.get("properties", {}).get("density", ""), - "diameter": container_node.metadata.get("properties", {}).get("diameter", ""), - "is_read_only": self._container_registry.isReadOnly(container_node.metadata["id"]), - } - - for key in keys_to_fetch: - item[key] = container_node.metadata.get(key, "") - - material_list.append(item) - - material_list = sorted(material_list, key = lambda k: (k["brand"].upper(), k["name"].upper())) - self.setItems(material_list) diff --git a/resources/qml/Preferences/Materials/OldMaterialList.qml b/resources/qml/Preferences/Materials/OldMaterialList.qml deleted file mode 100644 index 6c15ddf7cc..0000000000 --- a/resources/qml/Preferences/Materials/OldMaterialList.qml +++ /dev/null @@ -1,98 +0,0 @@ -ListView -{ - id: materialListView - - model: materialsModel - - section.property: "brand" - section.criteria: ViewSection.FullString - section.delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: palette.light - - Label - { - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_lining").width - text: section - font.bold: true - color: palette.text - } - } - - delegate: Rectangle - { - width: materialScrollView.width - height: childrenRect.height - color: ListView.isCurrentItem ? palette.highlight : (model.index % 2) ? palette.base : palette.alternateBase - - Row - { - id: materialRow - spacing: (UM.Theme.getSize("default_margin").width / 2) | 0 - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.right: parent.right - - property bool isCurrentItem: parent.ListView.isCurrentItem - - property bool isItemActivated: - { - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - const root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - return model.root_material_id == root_material_id; - } - - Rectangle - { - width: Math.floor(parent.height * 0.8) - height: Math.floor(parent.height * 0.8) - color: model.color_code - border.color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - anchors.verticalCenter: parent.verticalCenter - } - Label - { - width: Math.floor((parent.width * 0.3)) - text: model.material - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - Label - { - text: (model.name != model.material) ? model.name : "" - elide: Text.ElideRight - font.italic: materialRow.isItemActivated - color: materialRow.isCurrentItem ? palette.highlightedText : palette.text; - } - } - - MouseArea - { - anchors.fill: parent - onClicked: - { - parent.ListView.view.currentIndex = model.index; - } - } - } - - function activateDetailsWithIndex(index) - { - var model = materialsModel.getItem(index); - base.currentItem = model; - materialDetailsView.containerId = model.container_id; - materialDetailsView.currentMaterialNode = model.container_node; - - detailsPanel.updateMaterialPropertiesObject(); - } - - onCurrentIndexChanged: - { - forceActiveFocus(); // causes the changed fields to be saved - activateDetailsWithIndex(currentIndex); - } -} From 56a5f59964d25066c713dec6d5b04558b9a2bcab Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 23 Aug 2018 16:39:40 +0200 Subject: [PATCH 13/30] Cleaner code I was hoping to completely nix the generic materials model (since it's basically just a brand "Generic", but then in the QML it has to be have the same in terms of sub-menus or fold-outs and that looked stupid (Generic -> ABS -> ABS)). So we keep that one for now. It is cleaner though. Contributes to CURA-5162, CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 95 ++++++---- cura/Machines/Models/BrandMaterialsModel.py | 174 ------------------ .../Machines/Models/FavoriteMaterialsModel.py | 43 ++--- cura/Machines/Models/GenericMaterialsModel.py | 51 ++--- cura/Machines/Models/MaterialBrandsModel.py | 129 +++++++++++++ resources/qml/Menus/MaterialMenu.qml | 4 +- .../Preferences/Materials/MaterialsList.qml | 4 +- .../Preferences/Materials/MaterialsPage.qml | 2 +- 8 files changed, 222 insertions(+), 280 deletions(-) delete mode 100644 cura/Machines/Models/BrandMaterialsModel.py create mode 100644 cura/Machines/Models/MaterialBrandsModel.py diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 80ecf72c0a..122c38804c 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -2,51 +2,54 @@ # Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty - -from UM.Application import Application from UM.Qt.ListModel import ListModel -# -# This is the base model class for GenericMaterialsModel and BrandMaterialsModel -# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately. -# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top -# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu -# +## This is the base model class for GenericMaterialsModel and MaterialBrandsModel. +# Those 2 models are used by the material drop down menu to show generic materials and branded materials separately. +# The extruder position defined here is being used to bound a menu to the correct extruder. This is used in the top +# bar menu "Settings" -> "Extruder nr" -> "Material" -> this menu class BaseMaterialsModel(ListModel): - RootMaterialIdRole = Qt.UserRole + 1 - IdRole = Qt.UserRole + 2 - NameRole = Qt.UserRole + 3 - BrandRole = Qt.UserRole + 4 - MaterialRole = Qt.UserRole + 5 - ColorRole = Qt.UserRole + 6 - ContainerNodeRole = Qt.UserRole + 7 - ColorCodeRole = Qt.UserRole + 8 - GUIDRole = Qt.UserRole + 9 - IsFavoriteRole = Qt.UserRole + 10 extruderPositionChanged = pyqtSignal() def __init__(self, parent = None): super().__init__(parent) - self._application = Application.getInstance() - self._machine_manager = self._application.getMachineManager() - self.addRoleName(self.RootMaterialIdRole, "root_material_id") - self.addRoleName(self.IdRole, "id") - self.addRoleName(self.GUIDRole, "GUID") - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.BrandRole, "brand") - self.addRoleName(self.MaterialRole, "material") - self.addRoleName(self.ColorRole, "color_name") - self.addRoleName(self.ColorCodeRole, "color_code") - self.addRoleName(self.ContainerNodeRole, "container_node") - self.addRoleName(self.IsFavoriteRole, "is_favorite") + from cura.CuraApplication import CuraApplication + + self._application = CuraApplication.getInstance() + + # Make these managers available to all material models + self._extruder_manager = self._application.getExtruderManager() + self._machine_manager = self._application.getMachineManager() + self._material_manager = self._application.getMaterialManager() + + # Update the stack and the model data when the machine changes + self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) + + # Update this model when switching machines + self._machine_manager.activeStackChanged.connect(self._update) + + # Update this model when list of materials changes + self._material_manager.materialsUpdated.connect(self._update) + + self.addRoleName(Qt.UserRole + 1, "root_material_id") + self.addRoleName(Qt.UserRole + 2, "id") + self.addRoleName(Qt.UserRole + 3, "GUID") + self.addRoleName(Qt.UserRole + 4, "name") + self.addRoleName(Qt.UserRole + 5, "brand") + self.addRoleName(Qt.UserRole + 6, "material") + self.addRoleName(Qt.UserRole + 7, "color_name") + self.addRoleName(Qt.UserRole + 8, "color_code") + self.addRoleName(Qt.UserRole + 9, "container_node") + self.addRoleName(Qt.UserRole + 10, "is_favorite") self._extruder_position = 0 self._extruder_stack = None - # Update the stack and the model data when the machine changes - self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) + + self._available_materials = None + self._favorite_ids = None def _updateExtruderStack(self): global_stack = self._machine_manager.activeMachine @@ -71,8 +74,30 @@ class BaseMaterialsModel(ListModel): def extruderPosition(self) -> int: return self._extruder_position - # - # This is an abstract method that needs to be implemented by - # + ## This is an abstract method that needs to be implemented by the specific + # models themselves. def _update(self): pass + + ## This method is used by all material models in the beginning of the + # _update() method in order to prevent errors. It's the same in all models + # so it's placed here for easy access. + def _canUpdate(self): + global_stack = self._machine_manager.activeMachine + + if global_stack is None: + return False + + extruder_position = str(self._extruder_position) + + if extruder_position not in global_stack.extruders: + return False + + extruder_stack = global_stack.extruders[extruder_position] + + self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) + if self._available_materials is None: + return False + + return True + diff --git a/cura/Machines/Models/BrandMaterialsModel.py b/cura/Machines/Models/BrandMaterialsModel.py deleted file mode 100644 index 154019d028..0000000000 --- a/cura/Machines/Models/BrandMaterialsModel.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty - -from UM.Qt.ListModel import ListModel -from UM.Logger import Logger -from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel - - -# -# This is an intermediate model to group materials with different colours for a same brand and type. -# -class MaterialsModelGroupedByType(ListModel): - NameRole = Qt.UserRole + 1 - ColorsRole = Qt.UserRole + 2 - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.ColorsRole, "colors") - - -# -# This model is used to show branded materials in the material drop down menu. -# The structure of the menu looks like this: -# Brand -> Material Type -> list of materials -# -# To illustrate, a branded material menu may look like this: -# Ultimaker -> PLA -> Yellow PLA -# -> Black PLA -# -> ... -# -> ABS -> White ABS -# ... -# -class BrandMaterialsModel(ListModel): - NameRole = Qt.UserRole + 1 - MaterialsRole = Qt.UserRole + 2 - - extruderPositionChanged = pyqtSignal() - - def __init__(self, parent = None): - super().__init__(parent) - - self.addRoleName(self.NameRole, "name") - self.addRoleName(self.MaterialsRole, "materials") - - self._extruder_position = 0 - self._extruder_stack = None - - from cura.CuraApplication import CuraApplication - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack) - self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. - self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. - # self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed - self._update() - - def _updateExtruderStack(self): - global_stack = self._machine_manager.activeMachine - if global_stack is None: - return - - if self._extruder_stack is not None: - self._extruder_stack.pyqtContainersChanged.disconnect(self._update) - self._extruder_stack = global_stack.extruders.get(str(self._extruder_position)) - if self._extruder_stack is not None: - self._extruder_stack.pyqtContainersChanged.connect(self._update) - # Force update the model when the extruder stack changes - self._update() - - def setExtruderPosition(self, position: int): - if self._extruder_stack is None or self._extruder_position != position: - self._extruder_position = position - self._updateExtruderStack() - self.extruderPositionChanged.emit() - - @pyqtProperty(int, fset=setExtruderPosition, notify=extruderPositionChanged) - def extruderPosition(self) -> int: - return self._extruder_position - - def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - extruder_position = str(self._extruder_position) - if extruder_position not in global_stack.extruders: - self.setItems([]) - return - extruder_stack = global_stack.extruders[str(self._extruder_position)] - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - extruder_stack) - if available_material_dict is None: - self.setItems([]) - return - - brand_item_list = [] - brand_group_dict = {} - for root_material_id, container_node in available_material_dict.items(): - metadata = container_node.metadata - - favorites = self._material_manager.getFavorites() - - # Do not include the materials from a to-be-removed package - if bool(metadata.get("removed", False)): - continue - - # Skip generic materials, and add brands we haven't seen yet to the dict - brand = metadata["brand"] - if brand.lower() == "generic": - continue - if brand not in brand_group_dict: - brand_group_dict[brand] = {} - - # Add material types we haven't seen yet to the dict - material_type = metadata["material"] - if material_type not in brand_group_dict[brand]: - brand_group_dict[brand][material_type] = [] - - # Now handle the individual materials - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "description": metadata["description"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "density": metadata.get("properties", {}).get("density", ""), - "diameter": metadata.get("properties", {}).get("diameter", ""), - "approximate_diameter": metadata["approximate_diameter"], - "adhesion_info": metadata["adhesion_info"], - "is_read_only": self._container_registry.isReadOnly(metadata["id"]), - "container_node": container_node, - "is_favorite": root_material_id in favorites - } - brand_group_dict[brand][material_type].append(item) - - for brand, material_dict in brand_group_dict.items(): - brand_item = {"name": brand, - "materials": MaterialsModelGroupedByType(self)} - - material_type_item_list = [] - for material_type, material_list in material_dict.items(): - material_type_item = {"name": material_type, - "colors": BaseMaterialsModel(self)} - material_type_item["colors"].clear() - - # Sort materials by name - material_list = sorted(material_list, key = lambda x: x["name"].upper()) - material_type_item["colors"].setItems(material_list) - - material_type_item_list.append(material_type_item) - - # Sort material type by name - material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper()) - brand_item["materials"].setItems(material_type_item_list) - - brand_item_list.append(brand_item) - - # Sort brand by name - brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper()) - self.setItems(brand_item_list) diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 35a5229da1..34e148e2fd 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -8,51 +8,32 @@ class FavoriteMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - - from cura.CuraApplication import CuraApplication - self._preferences = CuraApplication.getInstance().getPreferences() - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. - self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - global_stack = self._machine_manager.activeMachine - if global_stack is None: + # Perform standard check and reset if the check fails + if not self._canUpdate(): self.setItems([]) return - extruder_position = str(self._extruder_position) - if extruder_position not in global_stack.extruders: - self.setItems([]) - return - extruder_stack = global_stack.extruders[extruder_position] - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack) - if available_material_dict is None: - self.setItems([]) - return - - favorite_ids = self._material_manager.getFavorites() + # Get updated list of favorites + self._favorite_ids = self._material_manager.getFavorites() item_list = [] - for root_material_id, container_node in available_material_dict.items(): - metadata = container_node.metadata - # Only add results for favorite materials - if root_material_id not in favorite_ids: - continue + for root_material_id, container_node in self._available_materials.items(): + metadata = container_node.metadata # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): continue + # Only add results for favorite materials + if root_material_id not in self._favorite_ids: + continue + item = { "root_material_id": root_material_id, "id": metadata["id"], @@ -63,11 +44,11 @@ class FavoriteMaterialsModel(BaseMaterialsModel): "color_name": metadata["color_name"], "color_code": metadata["color_code"], "container_node": container_node, - "is_favorite": True + "is_favorite": True # Don't need to set since we only include favorites anyway } item_list.append(item) - # Sort the item list by material name alphabetically + # Sort the item list alphabetically by name item_list = sorted(item_list, key = lambda d: d["brand"].upper()) self.setItems(item_list) diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index a8f5bfbd35..3432f3e35c 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -4,44 +4,25 @@ from UM.Logger import Logger from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel - class GenericMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - - from cura.CuraApplication import CuraApplication - self._machine_manager = CuraApplication.getInstance().getMachineManager() - self._extruder_manager = CuraApplication.getInstance().getExtruderManager() - self._material_manager = CuraApplication.getInstance().getMaterialManager() - - self._machine_manager.activeStackChanged.connect(self._update) #Update when switching machines. - self._material_manager.materialsUpdated.connect(self._update) #Update when the list of materials changes. self._update() def _update(self): - Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) - global_stack = self._machine_manager.activeMachine - if global_stack is None: - self.setItems([]) - return - extruder_position = str(self._extruder_position) - if extruder_position not in global_stack.extruders: - self.setItems([]) - return - extruder_stack = global_stack.extruders[extruder_position] - - available_material_dict = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, - extruder_stack) - if available_material_dict is None: + # Perform standard check and reset if the check fails + if not self._canUpdate(): self.setItems([]) return - favorites = self._material_manager.getFavorites() + # Get updated list of favorites + self._favorite_ids = self._material_manager.getFavorites() item_list = [] - for root_material_id, container_node in available_material_dict.items(): + + for root_material_id, container_node in self._available_materials.items(): metadata = container_node.metadata # Only add results for generic materials @@ -54,19 +35,19 @@ class GenericMaterialsModel(BaseMaterialsModel): item = { "root_material_id": root_material_id, - "id": metadata["id"], - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "container_node": container_node, - "is_favorite": root_material_id in favorites + "id": metadata["id"], + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "container_node": container_node, + "is_favorite": root_material_id in self._favorite_ids } item_list.append(item) - # Sort the item list by material name alphabetically + # Sort the item list alphabetically by name item_list = sorted(item_list, key = lambda d: d["name"].upper()) self.setItems(item_list) diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py new file mode 100644 index 0000000000..89d9fc7bfd --- /dev/null +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -0,0 +1,129 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty +from UM.Qt.ListModel import ListModel +from UM.Logger import Logger +from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel + +class MaterialTypesModel(ListModel): + + def __init__(self, parent = None): + super().__init__(parent) + + self.addRoleName(Qt.UserRole + 1, "name") + self.addRoleName(Qt.UserRole + 2, "colors") + +class MaterialBrandsModel(BaseMaterialsModel): + + extruderPositionChanged = pyqtSignal() + + def __init__(self, parent = None): + super().__init__(parent) + + from cura.CuraApplication import CuraApplication + + self.addRoleName(Qt.UserRole + 1, "name") + self.addRoleName(Qt.UserRole + 2, "material_types") + + self._container_registry = CuraApplication.getInstance().getContainerRegistry() + + self._update() + + def _update(self): + + # Perform standard check and reset if the check fails + if not self._canUpdate(): + self.setItems([]) + return + + # Get updated list of favorites + self._favorite_ids = self._material_manager.getFavorites() + + brand_item_list = [] + brand_group_dict = {} + + # Part 1: Generate the entire tree of brands -> material types -> spcific materials + for root_material_id, container_node in self._available_materials.items(): + metadata = container_node.metadata + + # Do not include the materials from a to-be-removed package + if bool(metadata.get("removed", False)): + continue + + # Add brands we haven't seen yet to the dict, skipping generics + brand = metadata["brand"] + if brand.lower() == "generic": + continue + if brand not in brand_group_dict: + brand_group_dict[brand] = {} + + # Add material types we haven't seen yet to the dict + material_type = metadata["material"] + if material_type not in brand_group_dict[brand]: + brand_group_dict[brand][material_type] = [] + + # Now handle the individual materials + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), + "approximate_diameter": metadata["approximate_diameter"], + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": root_material_id in self._favorite_ids + } + brand_group_dict[brand][material_type].append(item) + + # Part 2: Organize the tree into models + # + # Normally, the structure of the menu looks like this: + # Brand -> Material Type -> Specific Material + # + # To illustrate, a branded material menu may look like this: + # Ultimaker ┳ PLA ┳ Yellow PLA + # ┃ ┣ Black PLA + # ┃ ┗ ... + # ┃ + # ┗ ABS ┳ White ABS + # ┗ ... + for brand, material_dict in brand_group_dict.items(): + + material_type_item_list = [] + brand_item = { + "name": brand, + "material_types": MaterialTypesModel(self) + } + + for material_type, material_list in material_dict.items(): + material_type_item = { + "name": material_type, + "colors": BaseMaterialsModel(self) + } + material_type_item["colors"].clear() + + # Sort materials by name + material_list = sorted(material_list, key = lambda x: x["name"].upper()) + material_type_item["colors"].setItems(material_list) + + material_type_item_list.append(material_type_item) + + # Sort material type by name + material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper()) + brand_item["material_types"].setItems(material_type_item_list) + + brand_item_list.append(brand_item) + + # Sort brand by name + brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper()) + self.setItems(brand_item_list) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index a53bc72a94..186c5d1d2a 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -26,7 +26,7 @@ Menu extruderPosition: menu.extruderIndex } - Cura.BrandMaterialsModel + Cura.MaterialBrandsModel { id: brandModel extruderPosition: menu.extruderIndex @@ -80,7 +80,7 @@ Menu id: brandMenu title: brandName property string brandName: model.name - property var brandMaterials: model.materials + property var brandMaterials: model.material_types Instantiator { diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index a051f55cac..220ce0134d 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -18,7 +18,7 @@ Item // Children UM.I18nCatalog { id: catalog; name: "cura"; } - Cura.BrandMaterialsModel { id: materialsModel } + Cura.MaterialBrandsModel { id: materialsModel } Cura.FavoriteMaterialsModel { id: favoriteMaterialsModel } Cura.GenericMaterialsModel { id: genericMaterialsModel } Column @@ -186,7 +186,7 @@ Item { id: brand_section property var expanded: true - property var types_model: model.materials + property var types_model: model.material_types height: childrenRect.height width: parent.width Rectangle diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index ce7203f34b..4df6049b3f 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -31,7 +31,7 @@ Item id: catalog name: "cura" } - Cura.BrandMaterialsModel + Cura.MaterialBrandsModel { id: materialsModel } From 6be9b5e27fb8cc2e0d3a9941b3824b40bc94d20a Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Thu, 23 Aug 2018 16:58:23 +0200 Subject: [PATCH 14/30] Consolidate models some more Contributes to CURA-5162, CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 42 ++++++++++++++++--- .../Machines/Models/FavoriteMaterialsModel.py | 13 +----- cura/Machines/Models/GenericMaterialsModel.py | 21 +++------- cura/Machines/Models/MaterialBrandsModel.py | 24 +---------- 4 files changed, 44 insertions(+), 56 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 122c38804c..ff006d00ae 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -21,6 +21,7 @@ class BaseMaterialsModel(ListModel): self._application = CuraApplication.getInstance() # Make these managers available to all material models + self._container_registry = self._application.getInstance().getContainerRegistry() self._extruder_manager = self._application.getExtruderManager() self._machine_manager = self._application.getMachineManager() self._material_manager = self._application.getMaterialManager() @@ -39,11 +40,17 @@ class BaseMaterialsModel(ListModel): self.addRoleName(Qt.UserRole + 3, "GUID") self.addRoleName(Qt.UserRole + 4, "name") self.addRoleName(Qt.UserRole + 5, "brand") - self.addRoleName(Qt.UserRole + 6, "material") - self.addRoleName(Qt.UserRole + 7, "color_name") - self.addRoleName(Qt.UserRole + 8, "color_code") - self.addRoleName(Qt.UserRole + 9, "container_node") - self.addRoleName(Qt.UserRole + 10, "is_favorite") + self.addRoleName(Qt.UserRole + 6, "description") + self.addRoleName(Qt.UserRole + 7, "material") + self.addRoleName(Qt.UserRole + 8, "color_name") + self.addRoleName(Qt.UserRole + 9, "color_code") + self.addRoleName(Qt.UserRole + 10, "density") + self.addRoleName(Qt.UserRole + 11, "diameter") + self.addRoleName(Qt.UserRole + 12, "approximate_diameter") + self.addRoleName(Qt.UserRole + 13, "adhesion_info") + self.addRoleName(Qt.UserRole + 14, "is_read_only") + self.addRoleName(Qt.UserRole + 15, "container_node") + self.addRoleName(Qt.UserRole + 16, "is_favorite") self._extruder_position = 0 self._extruder_stack = None @@ -101,3 +108,28 @@ class BaseMaterialsModel(ListModel): return True + ## This is another convenience function which is shared by all material + # models so it's put here to avoid having so much duplicated code. + def _createMaterialItem(self, root_material_id, container_node): + metadata = container_node.metadata + item = { + "root_material_id": root_material_id, + "id": metadata["id"], + "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml + "GUID": metadata["GUID"], + "name": metadata["name"], + "brand": metadata["brand"], + "description": metadata["description"], + "material": metadata["material"], + "color_name": metadata["color_name"], + "color_code": metadata["color_code"], + "density": metadata.get("properties", {}).get("density", ""), + "diameter": metadata.get("properties", {}).get("diameter", ""), + "approximate_diameter": metadata["approximate_diameter"], + "adhesion_info": metadata["adhesion_info"], + "is_read_only": self._container_registry.isReadOnly(metadata["id"]), + "container_node": container_node, + "is_favorite": root_material_id in self._favorite_ids + } + return item + diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 34e148e2fd..3c5ca226fe 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -34,18 +34,7 @@ class FavoriteMaterialsModel(BaseMaterialsModel): if root_material_id not in self._favorite_ids: continue - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "container_node": container_node, - "is_favorite": True # Don't need to set since we only include favorites anyway - } + item = self._createMaterialItem(root_material_id, container_node) item_list.append(item) # Sort the item list alphabetically by name diff --git a/cura/Machines/Models/GenericMaterialsModel.py b/cura/Machines/Models/GenericMaterialsModel.py index 3432f3e35c..27e6fdfd7c 100644 --- a/cura/Machines/Models/GenericMaterialsModel.py +++ b/cura/Machines/Models/GenericMaterialsModel.py @@ -25,26 +25,15 @@ class GenericMaterialsModel(BaseMaterialsModel): for root_material_id, container_node in self._available_materials.items(): metadata = container_node.metadata - # Only add results for generic materials - if metadata["brand"].lower() != "generic": - continue - # Do not include the materials from a to-be-removed package if bool(metadata.get("removed", False)): continue - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "container_node": container_node, - "is_favorite": root_material_id in self._favorite_ids - } + # Only add results for generic materials + if metadata["brand"].lower() != "generic": + continue + + item = self._createMaterialItem(root_material_id, container_node) item_list.append(item) # Sort the item list alphabetically by name diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py index 89d9fc7bfd..3f917abb16 100644 --- a/cura/Machines/Models/MaterialBrandsModel.py +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -21,13 +21,9 @@ class MaterialBrandsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - from cura.CuraApplication import CuraApplication - self.addRoleName(Qt.UserRole + 1, "name") self.addRoleName(Qt.UserRole + 2, "material_types") - self._container_registry = CuraApplication.getInstance().getContainerRegistry() - self._update() def _update(self): @@ -64,25 +60,7 @@ class MaterialBrandsModel(BaseMaterialsModel): brand_group_dict[brand][material_type] = [] # Now handle the individual materials - item = { - "root_material_id": root_material_id, - "id": metadata["id"], - "container_id": metadata["id"], # TODO: Remove duplicate in material manager qml - "GUID": metadata["GUID"], - "name": metadata["name"], - "brand": metadata["brand"], - "description": metadata["description"], - "material": metadata["material"], - "color_name": metadata["color_name"], - "color_code": metadata["color_code"], - "density": metadata.get("properties", {}).get("density", ""), - "diameter": metadata.get("properties", {}).get("diameter", ""), - "approximate_diameter": metadata["approximate_diameter"], - "adhesion_info": metadata["adhesion_info"], - "is_read_only": self._container_registry.isReadOnly(metadata["id"]), - "container_node": container_node, - "is_favorite": root_material_id in self._favorite_ids - } + item = self._createMaterialItem(root_material_id, container_node) brand_group_dict[brand][material_type].append(item) # Part 2: Organize the tree into models From 93645e6bfe1d2b1c330beade5db2906c46184396 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 24 Aug 2018 10:46:23 +0200 Subject: [PATCH 15/30] Reduce component sizes Contributes to CURA-5378 --- .../Materials/MaterialBrandSection.qml | 88 ++++++++++ .../Materials/MaterialTypeSection.qml | 97 +++++++++++ .../Preferences/Materials/MaterialsList.qml | 162 +----------------- 3 files changed, 186 insertions(+), 161 deletions(-) create mode 100644 resources/qml/Preferences/Materials/MaterialBrandSection.qml create mode 100644 resources/qml/Preferences/Materials/MaterialTypeSection.qml diff --git a/resources/qml/Preferences/Materials/MaterialBrandSection.qml b/resources/qml/Preferences/Materials/MaterialBrandSection.qml new file mode 100644 index 0000000000..0acd2aa1d5 --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialBrandSection.qml @@ -0,0 +1,88 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + id: brand_section + property var expanded: true + property var types_model: model.material_types + height: childrenRect.height + width: parent.width + Rectangle + { + id: brand_header_background + color: UM.Theme.getColor("favorites_header_bar") + anchors.fill: brand_header + } + Row + { + id: brand_header + width: parent.width + Label + { + id: brand_name + text: model.name + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width + verticalAlignment: Text.AlignVCenter + leftPadding: 4 + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: brand_header + onPressed: + { + brand_section.expanded = !brand_section.expanded + } + } + Column + { + anchors.top: brand_header.bottom + width: parent.width + anchors.left: parent.left + height: brand_section.expanded ? childrenRect.height : 0 + visible: brand_section.expanded + Repeater + { + model: types_model + delegate: MaterialTypeSection {} + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialTypeSection.qml b/resources/qml/Preferences/Materials/MaterialTypeSection.qml new file mode 100644 index 0000000000..ba4621f15e --- /dev/null +++ b/resources/qml/Preferences/Materials/MaterialTypeSection.qml @@ -0,0 +1,97 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Uranium is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.3 +import QtQuick.Dialogs 1.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +Rectangle +{ + id: material_type_section + property var expanded: true + property var colors_model: model.colors + height: childrenRect.height + width: parent.width + Rectangle + { + id: material_type_header_background + color: UM.Theme.getColor("lining") + anchors.bottom: material_type_header.bottom + anchors.left: material_type_header.left + height: UM.Theme.getSize("default_lining").height + width: material_type_header.width + } + Row + { + id: material_type_header + width: parent.width - 8 + anchors + { + left: parent.left + leftMargin: 8 + } + Label + { + text: model.name + height: UM.Theme.getSize("favorites_row").height + width: parent.width - UM.Theme.getSize("favorites_button").width + id: material_type_name + verticalAlignment: Text.AlignVCenter + } + Button + { + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + UM.RecolorImage { + anchors + { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: height + color: "black" + source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") + } + style: ButtonStyle + { + background: Rectangle + { + anchors.fill: parent + color: "transparent" + } + } + } + } + MouseArea + { + anchors.fill: material_type_header + onPressed: + { + material_type_section.expanded = !material_type_section.expanded + } + } + Column + { + height: material_type_section.expanded ? childrenRect.height : 0 + visible: material_type_section.expanded + width: parent.width + anchors.top: material_type_header.bottom + anchors.left: parent.left + Repeater + { + model: colors_model + delegate: MaterialSlot { + material: model + } + } + } +} \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 220ce0134d..c16b37170f 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -180,168 +180,8 @@ Item Repeater { id: brand_list - model: materialsModel - delegate: Rectangle - { - id: brand_section - property var expanded: true - property var types_model: model.material_types - height: childrenRect.height - width: parent.width - Rectangle - { - id: brand_header_background - color: UM.Theme.getColor("favorites_header_bar") - anchors.fill: brand_header - } - Row - { - id: brand_header - width: parent.width - Label - { - id: brand_name - text: model.name - height: UM.Theme.getSize("favorites_row").height - width: parent.width - UM.Theme.getSize("favorites_button").width - verticalAlignment: Text.AlignVCenter - leftPadding: 4 - } - Button - { - text: "" - implicitWidth: UM.Theme.getSize("favorites_button").width - implicitHeight: UM.Theme.getSize("favorites_button").height - UM.RecolorImage { - anchors - { - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter - } - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height - color: "black" - source: brand_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") - } - style: ButtonStyle - { - background: Rectangle - { - anchors.fill: parent - color: "transparent" - } - } - } - } - MouseArea - { - anchors.fill: brand_header - onPressed: - { - brand_section.expanded = !brand_section.expanded - } - } - Column - { - anchors.top: brand_header.bottom - width: parent.width - anchors.left: parent.left - height: brand_section.expanded ? childrenRect.height : 0 - visible: brand_section.expanded - Repeater - { - model: types_model - delegate: Rectangle - { - id: material_type_section - property var expanded: true - property var colors_model: model.colors - height: childrenRect.height - width: parent.width - Rectangle - { - id: material_type_header_background - color: UM.Theme.getColor("lining") - anchors.bottom: material_type_header.bottom - anchors.left: material_type_header.left - height: UM.Theme.getSize("default_lining").height - width: material_type_header.width - } - Row - { - id: material_type_header - width: parent.width - 8 - anchors - { - left: parent.left - leftMargin: 8 - } - Label - { - text: model.name - height: UM.Theme.getSize("favorites_row").height - width: parent.width - UM.Theme.getSize("favorites_button").width - id: material_type_name - verticalAlignment: Text.AlignVCenter - } - Button - { - text: "" - implicitWidth: UM.Theme.getSize("favorites_button").width - implicitHeight: UM.Theme.getSize("favorites_button").height - UM.RecolorImage { - anchors - { - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter - } - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: height - color: "black" - source: material_type_section.expanded ? UM.Theme.getIcon("arrow_bottom") : UM.Theme.getIcon("arrow_left") - } - style: ButtonStyle - { - background: Rectangle - { - anchors.fill: parent - color: "transparent" - } - } - } - } - MouseArea - { - anchors.fill: material_type_header - onPressed: - { - material_type_section.expanded = !material_type_section.expanded - } - } - Column - { - height: material_type_section.expanded ? childrenRect.height : 0 - visible: material_type_section.expanded - width: parent.width - anchors.top: material_type_header.bottom - anchors.left: parent.left - Repeater - { - model: colors_model - delegate: MaterialSlot { - material: model - } - } - } - } - } - } - } + delegate: MaterialBrandSection {} } } } \ No newline at end of file From 61c635fbaf9545fb460950042622d4045f710ffa Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 23 Aug 2018 16:59:09 +0200 Subject: [PATCH 16/30] Mock application in unit tests --- tests/conftest.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f2c709d8d8..77d215815a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,19 +3,21 @@ # The purpose of this class is to create fixtures or methods that can be shared among all tests. +import unittest.mock import pytest + from UM.Qt.QtApplication import QtApplication #QtApplication import is required, even though it isn't used. from cura.CuraApplication import CuraApplication from cura.MachineActionManager import MachineActionManager + + # Create a CuraApplication object that will be shared among all tests. It needs to be initialized. # Since we need to use it more that once, we create the application the first time and use its instance afterwards. @pytest.fixture() def application() -> CuraApplication: - application = CuraApplication.getInstance() - if application is None: - application = CuraApplication() - return application + app = unittest.mock.MagicMock() + return app # Returns a MachineActionManager instance. @pytest.fixture() From 13069a2f99f5d530c0f06e564daa99ceb358ad0b Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 24 Aug 2018 11:06:44 +0200 Subject: [PATCH 17/30] Some file renaming Contributes to CURA-5378 --- .../{MaterialBrandSection.qml => MaterialsBrandSection.qml} | 2 +- .../qml/Preferences/Materials/MaterialsDetailsPanel.qml | 2 +- resources/qml/Preferences/Materials/MaterialsList.qml | 6 +++--- .../Materials/{MaterialSlot.qml => MaterialsSlot.qml} | 0 .../{MaterialTypeSection.qml => MaterialsTypeSection.qml} | 2 +- .../Materials/{MaterialView.qml => MaterialsView.qml} | 0 6 files changed, 6 insertions(+), 6 deletions(-) rename resources/qml/Preferences/Materials/{MaterialBrandSection.qml => MaterialsBrandSection.qml} (98%) rename resources/qml/Preferences/Materials/{MaterialSlot.qml => MaterialsSlot.qml} (100%) rename resources/qml/Preferences/Materials/{MaterialTypeSection.qml => MaterialsTypeSection.qml} (98%) rename resources/qml/Preferences/Materials/{MaterialView.qml => MaterialsView.qml} (100%) diff --git a/resources/qml/Preferences/Materials/MaterialBrandSection.qml b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml similarity index 98% rename from resources/qml/Preferences/Materials/MaterialBrandSection.qml rename to resources/qml/Preferences/Materials/MaterialsBrandSection.qml index 0acd2aa1d5..7e1db1353c 100644 --- a/resources/qml/Preferences/Materials/MaterialBrandSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml @@ -82,7 +82,7 @@ Rectangle Repeater { model: types_model - delegate: MaterialTypeSection {} + delegate: MaterialsTypeSection {} } } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml index fc8c6d728c..ad9f0e3766 100644 --- a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -50,7 +50,7 @@ Item } } - MaterialView // Material detailed information view below the title Label + MaterialsView // Material detailed information view below the title Label { id: materialDetailsView anchors diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index c16b37170f..2aea433843 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -94,7 +94,7 @@ Item Repeater { model: favoriteMaterialsModel - delegate: MaterialSlot { + delegate: MaterialsSlot { material: model } } @@ -171,7 +171,7 @@ Item Repeater { model: genericMaterialsModel - delegate: MaterialSlot { + delegate: MaterialsSlot { material: model } } @@ -181,7 +181,7 @@ Item { id: brand_list model: materialsModel - delegate: MaterialBrandSection {} + delegate: MaterialsBrandSection {} } } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialSlot.qml b/resources/qml/Preferences/Materials/MaterialsSlot.qml similarity index 100% rename from resources/qml/Preferences/Materials/MaterialSlot.qml rename to resources/qml/Preferences/Materials/MaterialsSlot.qml diff --git a/resources/qml/Preferences/Materials/MaterialTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml similarity index 98% rename from resources/qml/Preferences/Materials/MaterialTypeSection.qml rename to resources/qml/Preferences/Materials/MaterialsTypeSection.qml index ba4621f15e..2395714d15 100644 --- a/resources/qml/Preferences/Materials/MaterialTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -89,7 +89,7 @@ Rectangle Repeater { model: colors_model - delegate: MaterialSlot { + delegate: MaterialsSlot { material: model } } diff --git a/resources/qml/Preferences/Materials/MaterialView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml similarity index 100% rename from resources/qml/Preferences/Materials/MaterialView.qml rename to resources/qml/Preferences/Materials/MaterialsView.qml From 2304aeaceb2a29b6210a5e3513488ba04a7b01cf Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Fri, 24 Aug 2018 12:10:32 +0200 Subject: [PATCH 18/30] Expanded states preserved when updating models Did this so that models can be updated more often fixing bugs where when a material is set as "not favorite" in the favorites section, its updated accordingly in its "normal" section. It's also the ground work for saving material section expansion to preferences. Contributes to CURA-5378 --- cura/Machines/Models/BaseMaterialsModel.py | 3 ++ .../Machines/Models/FavoriteMaterialsModel.py | 1 - .../Materials/MaterialsBrandSection.qml | 16 +++++- .../Preferences/Materials/MaterialsList.qml | 16 +++++- .../Preferences/Materials/MaterialsPage.qml | 50 +++++++++++-------- .../Materials/MaterialsTypeSection.qml | 16 +++++- 6 files changed, 74 insertions(+), 28 deletions(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index ff006d00ae..a90d762236 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -35,6 +35,9 @@ class BaseMaterialsModel(ListModel): # Update this model when list of materials changes self._material_manager.materialsUpdated.connect(self._update) + # Update this model when list of favorites changes + self._material_manager.favoritesUpdated.connect(self._update) + self.addRoleName(Qt.UserRole + 1, "root_material_id") self.addRoleName(Qt.UserRole + 2, "id") self.addRoleName(Qt.UserRole + 3, "GUID") diff --git a/cura/Machines/Models/FavoriteMaterialsModel.py b/cura/Machines/Models/FavoriteMaterialsModel.py index 3c5ca226fe..be3f0f605f 100644 --- a/cura/Machines/Models/FavoriteMaterialsModel.py +++ b/cura/Machines/Models/FavoriteMaterialsModel.py @@ -8,7 +8,6 @@ class FavoriteMaterialsModel(BaseMaterialsModel): def __init__(self, parent = None): super().__init__(parent) - self._material_manager.favoritesUpdated.connect(self._update) # Update when favorites are changed self._update() def _update(self): diff --git a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml index 7e1db1353c..1077cbff6f 100644 --- a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml @@ -13,7 +13,7 @@ import Cura 1.0 as Cura Rectangle { id: brand_section - property var expanded: true + property var expanded: base.collapsed_brands.indexOf(model.name) > -1 property var types_model: model.material_types height: childrenRect.height width: parent.width @@ -69,7 +69,19 @@ Rectangle anchors.fill: brand_header onPressed: { - brand_section.expanded = !brand_section.expanded + const i = base.collapsed_brands.indexOf(model.name) + if (i > -1) + { + // Remove it + base.collapsed_brands.splice(i, 1) + brand_section.expanded = false + } + else + { + // Add it + base.collapsed_brands.push(model.name) + brand_section.expanded = true + } } } Column diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 2aea433843..4a1a330ed6 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -102,7 +102,7 @@ Item } Rectangle { - property var expanded: true + property var expanded: base.collapsed_brands.indexOf("Generic") > -1 id: generic_section height: childrenRect.height @@ -158,7 +158,19 @@ Item anchors.fill: generic_header onPressed: { - generic_section.expanded = !generic_section.expanded + const i = base.collapsed_brands.indexOf("Generic") + if (i > -1) + { + // Remove it + base.collapsed_brands.splice(i, 1) + generic_section.expanded = false + } + else + { + // Add it + base.collapsed_brands.push("Generic") + generic_section.expanded = true + } } } Column diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 4df6049b3f..0b81df5fa1 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -26,36 +26,44 @@ Item property string newRootMaterialIdToSwitchTo: "" property bool toActivateNewMaterial: false + // TODO: Save these to preferences + property var collapsed_brands: [] + property var collapsed_types: [] + UM.I18nCatalog { id: catalog name: "cura" } - Cura.MaterialBrandsModel + Cura.MaterialBrandsModel { id: materialsModel } + + function findModelByRootId( search_root_id ) { - id: materialsModel + for (var i = 0; i < materialsModel.rowCount(); i++) + { + var types_model = materialsModel.getItem(i).material_types; + for (var j = 0; j < types_model.rowCount(); j++) + { + var colors_model = types_model.getItem(j).colors; + for (var k = 0; k < colors_model.rowCount(); k++) + { + var material = colors_model.getItem(k); + if (material.root_material_id == search_root_id) + { + return material + } + } + } + } } - Cura.GenericMaterialsModel + Component.onCompleted: { - id: genericMaterialsModel + // Select the activated material when this page shows up + const extruder_position = Cura.ExtruderManager.activeExtruderIndex; + const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; + console.log("goign to search for", active_root_material_id) + base.currentItem = findModelByRootId(active_root_material_id) } - // Component.onCompleted: - // { - // // Select the activated material when this page shows up - // const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - // const active_root_material_id = Cura.MachineManager.currentRootMaterialId[extruder_position]; - // var itemIndex = -1; - // for (var i = 0; i < materialsModel.rowCount(); ++i) - // { - // var item = materialsModel.getItem(i); - // if (item.root_material_id == active_root_material_id) - // { - // itemIndex = i; - // break; - // } - // } - // materialListView.currentIndex = itemIndex; - // } onCurrentItemChanged: { MaterialsDetailsPanel.currentItem = currentItem } Connections diff --git a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml index 2395714d15..11bf2385e1 100644 --- a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -13,7 +13,7 @@ import Cura 1.0 as Cura Rectangle { id: material_type_section - property var expanded: true + property var expanded: base.collapsed_types.indexOf(model.brand + "_" + model.name) > -1 property var colors_model: model.colors height: childrenRect.height width: parent.width @@ -76,7 +76,19 @@ Rectangle anchors.fill: material_type_header onPressed: { - material_type_section.expanded = !material_type_section.expanded + const i = base.collapsed_types.indexOf(model.brand + "_" + model.name) + if (i > -1) + { + // Remove it + base.collapsed_types.splice(i, 1) + material_type_section.expanded = false + } + else + { + // Add it + base.collapsed_types.push(model.brand + "_" + model.name) + material_type_section.expanded = true + } } } Column From 8daf02063da0f66ff12f49e0d8f8d8ac324c174b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 24 Aug 2018 15:35:01 +0200 Subject: [PATCH 19/30] Fix quality lookup fallback mechanism CURA-5668 The last fallback is the global qualities, either machine-specific or generic, but not using both. Because if a machine defines its own global qualities, it is intended to override the existing ones, so do not fallback again in this case. --- cura/Machines/QualityManager.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index df3bec0827..cb2776429f 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -259,8 +259,12 @@ class QualityManager(QObject): # 2. machine-nozzle-and-material-specific qualities if exist # 3. machine-nozzle-specific qualities if exist # 4. machine-material-specific qualities if exist - # 5. machine-specific qualities if exist - # 6. generic qualities if exist + # 5. machine-specific global qualities if exist, otherwise generic global qualities + # NOTE: We DO NOT fail back to generic global qualities if machine-specific global qualities exist. + # This is because when a machine defines its own global qualities such as Normal, Fine, etc., + # it is intended to maintain those specific qualities ONLY. If we still fail back to the generic + # global qualities, there can be unimplemented quality types e.g. "coarse", and this is not + # correct. # Each points above can be represented as a node in the lookup tree, so here we simply put those nodes into # the list with priorities as the order. Later, we just need to loop over each node in this list and fetch # qualities from there. @@ -289,7 +293,13 @@ class QualityManager(QObject): addNodesToCheck(machine_node, nodes_to_check, node_info_list_0, 0) - nodes_to_check += [machine_node, default_machine_node] + # The last fall back will be the global qualities (either from the machine-specific node or the generic + # node), but we only use one. For details see the overview comments above. + if machine_node.quality_type_map: + nodes_to_check += [machine_node] + else: + nodes_to_check += [default_machine_node] + for node in nodes_to_check: if node and node.quality_type_map: if has_variant_materials: From eac70dc06dd5e062fc54a36482b9ab025a147b65 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Aug 2018 09:41:19 +0200 Subject: [PATCH 20/30] Change default print job name to 'Untitled' This is more common for documents that don't yet have a title in many applications. --- cura/PrintInformation.py | 2 +- resources/qml/JobSpecs.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 21e2040dc1..8527da1b8a 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -300,7 +300,7 @@ class PrintInformation(QObject): def _updateJobName(self): if self._base_name == "": - self._job_name = "unnamed" + self._job_name = "Untitled" self._is_user_specified_job_name = False self.jobNameChanged.emit() return diff --git a/resources/qml/JobSpecs.qml b/resources/qml/JobSpecs.qml index 20ec8ce289..31ca84d66e 100644 --- a/resources/qml/JobSpecs.qml +++ b/resources/qml/JobSpecs.qml @@ -81,7 +81,7 @@ Item { text: PrintInformation.jobName horizontalAlignment: TextInput.AlignRight onEditingFinished: { - var new_name = text == "" ? catalog.i18nc("@text Print job name", "unnamed") : text; + var new_name = text == "" ? catalog.i18nc("@text Print job name", "Untitled") : text; PrintInformation.setJobName(new_name, true); printJobTextfield.focus = false; } From 33f495442a84eecbb0a0aee4970d17258b52dd75 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Aug 2018 10:44:13 +0200 Subject: [PATCH 21/30] Remove unneeded code CURA-5162 --- cura/Machines/Models/BaseMaterialsModel.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index a90d762236..43b42c55ff 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -22,7 +22,6 @@ class BaseMaterialsModel(ListModel): # Make these managers available to all material models self._container_registry = self._application.getInstance().getContainerRegistry() - self._extruder_manager = self._application.getExtruderManager() self._machine_manager = self._application.getMachineManager() self._material_manager = self._application.getMaterialManager() From 336ea150d931e7e91582997648bf02af4a023832 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Aug 2018 10:45:18 +0200 Subject: [PATCH 22/30] Change tabs into spaces As per our code style. --- resources/extruders/builder_premium_large_front.def.json | 6 +++--- resources/extruders/builder_premium_large_rear.def.json | 4 ++-- resources/extruders/builder_premium_medium_front.def.json | 6 +++--- resources/extruders/builder_premium_medium_rear.def.json | 4 ++-- resources/extruders/builder_premium_small_front.def.json | 6 +++--- resources/extruders/builder_premium_small_rear.def.json | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/resources/extruders/builder_premium_large_front.def.json b/resources/extruders/builder_premium_large_front.def.json index 059f7ef8a7..4834bc8fd9 100644 --- a/resources/extruders/builder_premium_large_front.def.json +++ b/resources/extruders/builder_premium_large_front.def.json @@ -16,13 +16,13 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "material_diameter": { "default_value": 1.75 }, - - "machine_extruder_start_pos_abs": { "default_value": true }, + + "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_large_rear.def.json b/resources/extruders/builder_premium_large_rear.def.json index 769178a8b4..f257749ea4 100644 --- a/resources/extruders/builder_premium_large_rear.def.json +++ b/resources/extruders/builder_premium_large_rear.def.json @@ -20,9 +20,9 @@ "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, - "machine_extruder_end_pos_abs": { "default_value": true }, + "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_medium_front.def.json b/resources/extruders/builder_premium_medium_front.def.json index bd735fbe25..05dcb3d49f 100644 --- a/resources/extruders/builder_premium_medium_front.def.json +++ b/resources/extruders/builder_premium_medium_front.def.json @@ -16,13 +16,13 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "material_diameter": { "default_value": 1.75 }, - - "machine_extruder_start_pos_abs": { "default_value": true }, + + "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_medium_rear.def.json b/resources/extruders/builder_premium_medium_rear.def.json index 59e688ff71..3461e07f09 100644 --- a/resources/extruders/builder_premium_medium_rear.def.json +++ b/resources/extruders/builder_premium_medium_rear.def.json @@ -20,9 +20,9 @@ "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, - "machine_extruder_end_pos_abs": { "default_value": true }, + "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_small_front.def.json b/resources/extruders/builder_premium_small_front.def.json index 17fb914a42..7a1c352c73 100644 --- a/resources/extruders/builder_premium_small_front.def.json +++ b/resources/extruders/builder_premium_small_front.def.json @@ -16,13 +16,13 @@ "machine_nozzle_offset_x": { "default_value": 0.0 }, "machine_nozzle_offset_y": { "default_value": 0.0 }, "material_diameter": { "default_value": 1.75 }, - - "machine_extruder_start_pos_abs": { "default_value": true }, + + "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } diff --git a/resources/extruders/builder_premium_small_rear.def.json b/resources/extruders/builder_premium_small_rear.def.json index 70a2dbf1aa..7085236a5c 100644 --- a/resources/extruders/builder_premium_small_rear.def.json +++ b/resources/extruders/builder_premium_small_rear.def.json @@ -20,9 +20,9 @@ "machine_extruder_start_pos_abs": { "default_value": true }, "machine_extruder_start_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_start_pos_y": { "value": "prime_tower_position_y" }, - "machine_extruder_end_pos_abs": { "default_value": true }, + "machine_extruder_end_pos_abs": { "default_value": true }, "machine_extruder_end_pos_x": { "value": "prime_tower_position_x" }, "machine_extruder_end_pos_y": { "value": "prime_tower_position_y" }, - "extruder_prime_pos_abs": { "default_value": true } + "extruder_prime_pos_abs": { "default_value": true } } } From 45e335531884902becc2c948e592fa6aa0a12b10 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 27 Aug 2018 10:57:58 +0200 Subject: [PATCH 23/30] Catch failure to parse QML component Don't crash the application then. --- plugins/PostProcessingPlugin/PostProcessingPlugin.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py index da971a8e61..b28a028325 100644 --- a/plugins/PostProcessingPlugin/PostProcessingPlugin.py +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py @@ -1,5 +1,6 @@ -# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. +# Copyright (c) 2018 Jaime van Kessel, Ultimaker B.V. # The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. + from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot from UM.PluginRegistry import PluginRegistry @@ -260,6 +261,9 @@ class PostProcessingPlugin(QObject, Extension): # Create the plugin dialog component path = os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "PostProcessingPlugin.qml") self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) + if self._view is None: + Logger.log("e", "Not creating PostProcessing button near save button because the QML component failed to be created.") + return Logger.log("d", "Post processing view created.") # Create the save button component @@ -269,6 +273,9 @@ class PostProcessingPlugin(QObject, Extension): def showPopup(self): if self._view is None: self._createView() + if self._view is None: + Logger.log("e", "Not creating PostProcessing window since the QML component failed to be created.") + return self._view.show() ## Property changed: trigger re-slice From 22ccf074f3b8529bbb541d1da20ca39ff7d9d572 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 27 Aug 2018 13:20:18 +0200 Subject: [PATCH 24/30] Only check if printing extruder is enabled for printing meshes CURA-5669 --- plugins/CuraEngineBackend/StartSliceJob.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 0ebcafdbb2..1295390c22 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -220,8 +220,10 @@ class StartSliceJob(Job): stack = global_stack skip_group = False for node in group: + # Only check if the printing extruder is enabled for printing meshes + is_non_printing_mesh = node.callDecoration("evaluateIsNonPrintingMesh") extruder_position = node.callDecoration("getActiveExtruderPosition") - if not extruders_enabled[extruder_position]: + if not is_non_printing_mesh and not extruders_enabled[extruder_position]: skip_group = True has_model_with_disabled_extruders = True associated_disabled_extruders.add(extruder_position) From fe9cada45903c71b64c033fd3603eb6866917a2e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Mon, 27 Aug 2018 13:59:00 +0200 Subject: [PATCH 25/30] Increase plugin API version to 5 CURA-5627 --- plugins/3MFReader/plugin.json | 2 +- plugins/3MFWriter/plugin.json | 2 +- plugins/ChangeLogPlugin/plugin.json | 2 +- plugins/CuraEngineBackend/plugin.json | 2 +- plugins/CuraProfileReader/plugin.json | 2 +- plugins/CuraProfileWriter/plugin.json | 2 +- plugins/FirmwareUpdateChecker/plugin.json | 2 +- plugins/GCodeGzReader/plugin.json | 2 +- plugins/GCodeGzWriter/plugin.json | 2 +- plugins/GCodeProfileReader/plugin.json | 2 +- plugins/GCodeReader/plugin.json | 2 +- plugins/GCodeWriter/plugin.json | 2 +- plugins/ImageReader/plugin.json | 2 +- plugins/LegacyProfileReader/plugin.json | 2 +- plugins/MachineSettingsAction/plugin.json | 2 +- plugins/ModelChecker/plugin.json | 2 +- plugins/MonitorStage/plugin.json | 2 +- plugins/PerObjectSettingsTool/plugin.json | 2 +- plugins/PostProcessingPlugin/plugin.json | 2 +- plugins/PrepareStage/plugin.json | 2 +- plugins/RemovableDriveOutputDevice/plugin.json | 2 +- plugins/SimulationView/plugin.json | 2 +- plugins/SliceInfoPlugin/plugin.json | 2 +- plugins/SolidView/plugin.json | 2 +- plugins/SupportEraser/plugin.json | 2 +- plugins/Toolbox/plugin.json | 2 +- plugins/UFPWriter/plugin.json | 2 +- plugins/UM3NetworkPrinting/plugin.json | 2 +- plugins/USBPrinting/plugin.json | 2 +- plugins/UltimakerMachineActions/plugin.json | 2 +- plugins/UserAgreement/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json | 2 +- plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json | 2 +- plugins/X3DReader/plugin.json | 2 +- plugins/XRayView/plugin.json | 2 +- plugins/XmlMaterialProfile/plugin.json | 2 +- 43 files changed, 43 insertions(+), 43 deletions(-) diff --git a/plugins/3MFReader/plugin.json b/plugins/3MFReader/plugin.json index 5d15123017..5e41975752 100644 --- a/plugins/3MFReader/plugin.json +++ b/plugins/3MFReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for reading 3MF files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/3MFWriter/plugin.json b/plugins/3MFWriter/plugin.json index 22d18b2cf1..9ec4fb0c20 100644 --- a/plugins/3MFWriter/plugin.json +++ b/plugins/3MFWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for writing 3MF files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/ChangeLogPlugin/plugin.json b/plugins/ChangeLogPlugin/plugin.json index e9414b9b71..e09a08564a 100644 --- a/plugins/ChangeLogPlugin/plugin.json +++ b/plugins/ChangeLogPlugin/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Shows changes since latest checked version.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/CuraEngineBackend/plugin.json b/plugins/CuraEngineBackend/plugin.json index e5df06f228..111698d8d1 100644 --- a/plugins/CuraEngineBackend/plugin.json +++ b/plugins/CuraEngineBackend/plugin.json @@ -2,7 +2,7 @@ "name": "CuraEngine Backend", "author": "Ultimaker B.V.", "description": "Provides the link to the CuraEngine slicing backend.", - "api": 4, + "api": 5, "version": "1.0.0", "i18n-catalog": "cura" } diff --git a/plugins/CuraProfileReader/plugin.json b/plugins/CuraProfileReader/plugin.json index 004a1ade4d..66a2a6a56b 100644 --- a/plugins/CuraProfileReader/plugin.json +++ b/plugins/CuraProfileReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for importing Cura profiles.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/CuraProfileWriter/plugin.json b/plugins/CuraProfileWriter/plugin.json index d9accce770..16c8c34152 100644 --- a/plugins/CuraProfileWriter/plugin.json +++ b/plugins/CuraProfileWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for exporting Cura profiles.", - "api": 4, + "api": 5, "i18n-catalog":"cura" } diff --git a/plugins/FirmwareUpdateChecker/plugin.json b/plugins/FirmwareUpdateChecker/plugin.json index d6a9f9fbd7..cbbd41e420 100644 --- a/plugins/FirmwareUpdateChecker/plugin.json +++ b/plugins/FirmwareUpdateChecker/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Checks for firmware updates.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeGzReader/plugin.json b/plugins/GCodeGzReader/plugin.json index e9f14724e0..3bd6a4097d 100644 --- a/plugins/GCodeGzReader/plugin.json +++ b/plugins/GCodeGzReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Reads g-code from a compressed archive.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeGzWriter/plugin.json b/plugins/GCodeGzWriter/plugin.json index 9774e9a25c..4c6497317b 100644 --- a/plugins/GCodeGzWriter/plugin.json +++ b/plugins/GCodeGzWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Writes g-code to a compressed archive.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeProfileReader/plugin.json b/plugins/GCodeProfileReader/plugin.json index f8f7d4c291..9677628c85 100644 --- a/plugins/GCodeProfileReader/plugin.json +++ b/plugins/GCodeProfileReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for importing profiles from g-code files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeReader/plugin.json b/plugins/GCodeReader/plugin.json index f72a8cc12c..75b4d0cd4f 100644 --- a/plugins/GCodeReader/plugin.json +++ b/plugins/GCodeReader/plugin.json @@ -3,6 +3,6 @@ "author": "Victor Larchenko", "version": "1.0.0", "description": "Allows loading and displaying G-code files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/GCodeWriter/plugin.json b/plugins/GCodeWriter/plugin.json index 5fcb1a3bd7..3bbbab8b95 100644 --- a/plugins/GCodeWriter/plugin.json +++ b/plugins/GCodeWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Writes g-code to a file.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/ImageReader/plugin.json b/plugins/ImageReader/plugin.json index 2752c6e8f4..08195863e8 100644 --- a/plugins/ImageReader/plugin.json +++ b/plugins/ImageReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Enables ability to generate printable geometry from 2D image files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/LegacyProfileReader/plugin.json b/plugins/LegacyProfileReader/plugin.json index 2dc71511a9..179f5444e0 100644 --- a/plugins/LegacyProfileReader/plugin.json +++ b/plugins/LegacyProfileReader/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for importing profiles from legacy Cura versions.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/MachineSettingsAction/plugin.json b/plugins/MachineSettingsAction/plugin.json index 703a145deb..571658e40a 100644 --- a/plugins/MachineSettingsAction/plugin.json +++ b/plugins/MachineSettingsAction/plugin.json @@ -3,6 +3,6 @@ "author": "fieldOfView", "version": "1.0.0", "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/ModelChecker/plugin.json b/plugins/ModelChecker/plugin.json index a9190adcaa..3753c0cc88 100644 --- a/plugins/ModelChecker/plugin.json +++ b/plugins/ModelChecker/plugin.json @@ -2,7 +2,7 @@ "name": "Model Checker", "author": "Ultimaker B.V.", "version": "0.1", - "api": 4, + "api": 5, "description": "Checks models and print configuration for possible printing issues and give suggestions.", "i18n-catalog": "cura" } diff --git a/plugins/MonitorStage/plugin.json b/plugins/MonitorStage/plugin.json index cb3f55a80d..88b53840e0 100644 --- a/plugins/MonitorStage/plugin.json +++ b/plugins/MonitorStage/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides a monitor stage in Cura.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/PerObjectSettingsTool/plugin.json b/plugins/PerObjectSettingsTool/plugin.json index 3254662d33..15fde63387 100644 --- a/plugins/PerObjectSettingsTool/plugin.json +++ b/plugins/PerObjectSettingsTool/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides the Per Model Settings.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/PostProcessingPlugin/plugin.json b/plugins/PostProcessingPlugin/plugin.json index ebfef8145a..fea061e93b 100644 --- a/plugins/PostProcessingPlugin/plugin.json +++ b/plugins/PostProcessingPlugin/plugin.json @@ -2,7 +2,7 @@ "name": "Post Processing", "author": "Ultimaker", "version": "2.2", - "api": 4, + "api": 5, "description": "Extension that allows for user created scripts for post processing", "catalog": "cura" } \ No newline at end of file diff --git a/plugins/PrepareStage/plugin.json b/plugins/PrepareStage/plugin.json index 4fd55e955e..f0464313c7 100644 --- a/plugins/PrepareStage/plugin.json +++ b/plugins/PrepareStage/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides a prepare stage in Cura.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/RemovableDriveOutputDevice/plugin.json b/plugins/RemovableDriveOutputDevice/plugin.json index df11644256..36bb9ae186 100644 --- a/plugins/RemovableDriveOutputDevice/plugin.json +++ b/plugins/RemovableDriveOutputDevice/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "description": "Provides removable drive hotplugging and writing support.", "version": "1.0.0", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/SimulationView/plugin.json b/plugins/SimulationView/plugin.json index 0e7bec0626..93df98068f 100644 --- a/plugins/SimulationView/plugin.json +++ b/plugins/SimulationView/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides the Simulation view.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/SliceInfoPlugin/plugin.json b/plugins/SliceInfoPlugin/plugin.json index d1c643266b..939e5ff235 100644 --- a/plugins/SliceInfoPlugin/plugin.json +++ b/plugins/SliceInfoPlugin/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Submits anonymous slice info. Can be disabled through preferences.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/SolidView/plugin.json b/plugins/SolidView/plugin.json index 6d6bda96f0..e70ec224dd 100644 --- a/plugins/SolidView/plugin.json +++ b/plugins/SolidView/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides a normal solid mesh view.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/SupportEraser/plugin.json b/plugins/SupportEraser/plugin.json index 5ccb639913..7af35e0fb5 100644 --- a/plugins/SupportEraser/plugin.json +++ b/plugins/SupportEraser/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Creates an eraser mesh to block the printing of support in certain places", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/Toolbox/plugin.json b/plugins/Toolbox/plugin.json index 12d4042b6b..2557185524 100644 --- a/plugins/Toolbox/plugin.json +++ b/plugins/Toolbox/plugin.json @@ -2,6 +2,6 @@ "name": "Toolbox", "author": "Ultimaker B.V.", "version": "1.0.0", - "api": 4, + "api": 5, "description": "Find, manage and install new Cura packages." } diff --git a/plugins/UFPWriter/plugin.json b/plugins/UFPWriter/plugin.json index 7d10b89ad4..ab590353e0 100644 --- a/plugins/UFPWriter/plugin.json +++ b/plugins/UFPWriter/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides support for writing Ultimaker Format Packages.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } \ No newline at end of file diff --git a/plugins/UM3NetworkPrinting/plugin.json b/plugins/UM3NetworkPrinting/plugin.json index e7b59fadd6..d415338374 100644 --- a/plugins/UM3NetworkPrinting/plugin.json +++ b/plugins/UM3NetworkPrinting/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "description": "Manages network connections to Ultimaker 3 printers.", "version": "1.0.0", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/USBPrinting/plugin.json b/plugins/USBPrinting/plugin.json index 27e07c45b2..3484c8a48a 100644 --- a/plugins/USBPrinting/plugin.json +++ b/plugins/USBPrinting/plugin.json @@ -2,7 +2,7 @@ "name": "USB printing", "author": "Ultimaker B.V.", "version": "1.0.0", - "api": 4, + "api": 5, "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "i18n-catalog": "cura" } diff --git a/plugins/UltimakerMachineActions/plugin.json b/plugins/UltimakerMachineActions/plugin.json index 57b3e6bc8f..b60c7df88e 100644 --- a/plugins/UltimakerMachineActions/plugin.json +++ b/plugins/UltimakerMachineActions/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/UserAgreement/plugin.json b/plugins/UserAgreement/plugin.json index b10abc5640..50a2aa0441 100644 --- a/plugins/UserAgreement/plugin.json +++ b/plugins/UserAgreement/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Ask the user once if he/she agrees with our license.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json index 79115f931e..463fcdc941 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.1 to Cura 2.2.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json index d213042ad2..e7a0b1c559 100644 --- a/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade22to24/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.2 to Cura 2.4.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json index 759b6368fd..3029539887 100644 --- a/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade25to26/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.5 to Cura 2.6.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json index 3c3d7fff8c..225da67235 100644 --- a/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade26to27/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.6 to Cura 2.7.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json index 3df84ff7e6..9a139851ec 100644 --- a/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade27to30/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 2.7 to Cura 3.0.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json index d80b820976..cf42b3f6cd 100644 --- a/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade30to31/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.0 to Cura 3.1.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json index fbce09c807..f9cc968dae 100644 --- a/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade32to33/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.2 to Cura 3.3.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json index 164b79d504..f5ba7235d1 100644 --- a/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade33to34/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.3 to Cura 3.4.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json b/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json index 1059ca3e57..c07ae31c0a 100644 --- a/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json +++ b/plugins/VersionUpgrade/VersionUpgrade34to40/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Upgrades configurations from Cura 3.4 to Cura 4.0.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/X3DReader/plugin.json b/plugins/X3DReader/plugin.json index f18c7f033d..9ee09e43df 100644 --- a/plugins/X3DReader/plugin.json +++ b/plugins/X3DReader/plugin.json @@ -3,6 +3,6 @@ "author": "Seva Alekseyev", "version": "0.5.0", "description": "Provides support for reading X3D files.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/XRayView/plugin.json b/plugins/XRayView/plugin.json index 4e89690c13..576dec4656 100644 --- a/plugins/XRayView/plugin.json +++ b/plugins/XRayView/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides the X-Ray view.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } diff --git a/plugins/XmlMaterialProfile/plugin.json b/plugins/XmlMaterialProfile/plugin.json index 17056dcb3e..4b2901c375 100644 --- a/plugins/XmlMaterialProfile/plugin.json +++ b/plugins/XmlMaterialProfile/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "version": "1.0.0", "description": "Provides capabilities to read and write XML-based material profiles.", - "api": 4, + "api": 5, "i18n-catalog": "cura" } From 3e3f1cb03d27eabdaa682bea1cbb38e59dd14de9 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 28 Aug 2018 09:31:05 +0200 Subject: [PATCH 26/30] Remove double shortcut buttons CURA-5642 --- resources/qml/Actions.qml | 18 +++++++++--------- resources/qml/Cura.qml | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 21e6eebf58..d5572298f7 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -110,35 +110,35 @@ Item Action { id: view3DCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&3D View"); + text: catalog.i18nc("@action:inmenu menubar:view","3D View"); onTriggered: UM.Controller.rotateView("3d", 0); } Action { id: viewFrontCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Front View"); + text: catalog.i18nc("@action:inmenu menubar:view","Front View"); onTriggered: UM.Controller.rotateView("home", 0); } Action { id: viewTopCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Top View"); + text: catalog.i18nc("@action:inmenu menubar:view","Top View"); onTriggered: UM.Controller.rotateView("y", 90); } Action { id: viewLeftSideCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Left Side View"); + text: catalog.i18nc("@action:inmenu menubar:view","Left Side View"); onTriggered: UM.Controller.rotateView("x", 90); } Action { id: viewRightSideCameraAction; - text: catalog.i18nc("@action:inmenu menubar:view","&Right Side View"); + text: catalog.i18nc("@action:inmenu menubar:view","Right Side View"); onTriggered: UM.Controller.rotateView("x", -90); } @@ -229,7 +229,7 @@ Item Action { id: deleteSelectionAction; - text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount); + text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete Selected Model", "Delete Selected Models", UM.Selection.selectionCount); enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection; iconName: "edit-delete"; shortcut: StandardKey.Delete; @@ -239,7 +239,7 @@ Item Action //Also add backspace as the same function as delete because on Macintosh keyboards the button called "delete" is actually a backspace, and the user expects it to function as a delete. { id: backspaceSelectionAction - text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount) + text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete Selected Model", "Delete Selected Models", UM.Selection.selectionCount) enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection iconName: "edit-delete" shortcut: StandardKey.Backspace @@ -328,7 +328,7 @@ Item Action { id: selectAllAction; - text: catalog.i18nc("@action:inmenu menubar:edit","&Select All Models"); + text: catalog.i18nc("@action:inmenu menubar:edit","Select All Models"); enabled: UM.Controller.toolsEnabled; iconName: "edit-select-all"; shortcut: "Ctrl+A"; @@ -386,7 +386,7 @@ Item Action { id: resetAllAction; - text: catalog.i18nc("@action:inmenu menubar:edit","Reset All Model &Transformations"); + text: catalog.i18nc("@action:inmenu menubar:edit","Reset All Model Transformations"); onTriggered: CuraApplication.resetAll(); } diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index cd8a122bd2..33e456c758 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -117,7 +117,7 @@ UM.MainWindow MenuItem { id: saveWorkspaceMenu - text: catalog.i18nc("@title:menu menubar:file","&Save...") + text: catalog.i18nc("@title:menu menubar:file","Save...") onTriggered: { var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/x-curaproject+xml" }; From 40c4e9c5dfe5361a8f7c38ec3ef2462b0ec2aacb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 28 Aug 2018 09:56:00 +0200 Subject: [PATCH 27/30] Fix KeyError color_code in BaseMaterialsModel --- cura/Machines/Models/BaseMaterialsModel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 43b42c55ff..1b20e1188c 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -124,7 +124,7 @@ class BaseMaterialsModel(ListModel): "description": metadata["description"], "material": metadata["material"], "color_name": metadata["color_name"], - "color_code": metadata["color_code"], + "color_code": metadata.get("color_code", ""), "density": metadata.get("properties", {}).get("density", ""), "diameter": metadata.get("properties", {}).get("diameter", ""), "approximate_diameter": metadata["approximate_diameter"], From 694cc91ae9d174f8b420f63188754e3db232457d Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Tue, 28 Aug 2018 11:21:47 +0200 Subject: [PATCH 28/30] Add a "Favorites" heading to materials menu Contributes to CURA-5162 Also fixed some non i18n strings --- resources/qml/Menus/MaterialMenu.qml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/qml/Menus/MaterialMenu.qml b/resources/qml/Menus/MaterialMenu.qml index 186c5d1d2a..f9e343d2dd 100644 --- a/resources/qml/Menus/MaterialMenu.qml +++ b/resources/qml/Menus/MaterialMenu.qml @@ -10,7 +10,7 @@ import Cura 1.0 as Cura Menu { id: menu - title: "Material" + title: catalog.i18nc("@label:category menu label", "Material") property int extruderIndex: 0 @@ -32,6 +32,12 @@ Menu extruderPosition: menu.extruderIndex } + MenuItem + { + text: catalog.i18nc("@label:category menu label", "Favorites") + enabled: false + visible: favoriteMaterialsModel.items.length > 0 + } Instantiator { model: favoriteMaterialsModel @@ -52,7 +58,7 @@ Menu Menu { id: genericMenu - title: "Generic" + title: catalog.i18nc("@label:category menu label", "Generic") Instantiator { From dda356fbc4fb122b36fd71e096434c414319c9f4 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 29 Aug 2018 11:50:43 +0200 Subject: [PATCH 29/30] Remove the 40 char maximum on printer address textfield --- plugins/UM3NetworkPrinting/DiscoverUM3Action.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml index 127b3c35bd..b5b80a3010 100644 --- a/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/DiscoverUM3Action.qml @@ -364,7 +364,6 @@ Cura.MachineAction { id: addressField width: parent.width - maximumLength: 40 validator: RegExpValidator { regExp: /[a-zA-Z0-9\.\-\_]*/ From 1d8f19f1d1c501f5d7525ca695967a7813f30c16 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 29 Aug 2018 11:55:37 +0200 Subject: [PATCH 30/30] Don't give error value for infill layer thickness if no infill It won't crash the engine because the entire infill filling routine is skipped. --- 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 3eb7cb1c32..610ee1473e 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1819,9 +1819,9 @@ "unit": "mm", "type": "float", "default_value": 0.1, - "minimum_value": "resolveOrValue('layer_height')", + "minimum_value": "resolveOrValue('layer_height') if infill_line_distance > 0 else -999999", "maximum_value_warning": "0.75 * machine_nozzle_size", - "maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8)", + "maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8) if infill_line_distance > 0 else 999999", "value": "resolveOrValue('layer_height')", "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled", "limit_to_extruder": "infill_extruder_nr",