diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9e021aaaf1..243a9b5402 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -485,7 +485,9 @@ class CuraApplication(QtApplication): preferences.addPreference("view/filter_current_build_plate", False) preferences.addPreference("cura/sidebar_collapsed", False) - preferences.addPreference("cura/favorite_materials", ";".join([])) + preferences.addPreference("cura/favorite_materials", "") + preferences.addPreference("cura/expanded_brands", "") + preferences.addPreference("cura/expanded_types", "") 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 0feecce41e..dd6376b5e3 100644 --- a/cura/Machines/MaterialManager.py +++ b/cura/Machines/MaterialManager.py @@ -204,12 +204,11 @@ class MaterialManager(QObject): for material_metadata in material_metadatas.values(): self.__addMaterialMetadataIntoLookupTree(material_metadata) - self.materialsUpdated.emit() - favorites = self._application.getPreferences().getValue("cura/favorite_materials") for item in favorites.split(";"): self._favorites.add(item) - self.favoritesUpdated.emit() + + self.materialsUpdated.emit() def __addMaterialMetadataIntoLookupTree(self, material_metadata: Dict[str, Any]) -> None: material_id = material_metadata["id"] @@ -635,7 +634,7 @@ class MaterialManager(QObject): @pyqtSlot(str) def addFavorite(self, root_material_id: str) -> None: self._favorites.add(root_material_id) - self.favoritesUpdated.emit() + self.materialsUpdated.emit() # Ensure all settings are saved. self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites))) @@ -644,7 +643,7 @@ class MaterialManager(QObject): @pyqtSlot(str) def removeFavorite(self, root_material_id: str) -> None: self._favorites.remove(root_material_id) - self.favoritesUpdated.emit() + self.materialsUpdated.emit() # Ensure all settings are saved. self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites))) diff --git a/cura/Machines/Models/BaseMaterialsModel.py b/cura/Machines/Models/BaseMaterialsModel.py index 9799a35ed1..be9f8be1ed 100644 --- a/cura/Machines/Models/BaseMaterialsModel.py +++ b/cura/Machines/Models/BaseMaterialsModel.py @@ -34,9 +34,6 @@ 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/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py index f8d92dc65f..458e4d9b47 100644 --- a/cura/Machines/Models/MaterialBrandsModel.py +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -12,7 +12,8 @@ class MaterialTypesModel(ListModel): super().__init__(parent) self.addRoleName(Qt.UserRole + 1, "name") - self.addRoleName(Qt.UserRole + 2, "colors") + self.addRoleName(Qt.UserRole + 2, "brand") + self.addRoleName(Qt.UserRole + 3, "colors") class MaterialBrandsModel(BaseMaterialsModel): @@ -84,6 +85,7 @@ class MaterialBrandsModel(BaseMaterialsModel): for material_type, material_list in material_dict.items(): material_type_item = { "name": material_type, + "brand": brand, "colors": BaseMaterialsModel(self) } material_type_item["colors"].clear() diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 4c1cd94b4f..4a1203c412 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -1,12 +1,11 @@ # Copyright (c) 2018 Ultimaker B.V. # Toolbox is released under the terms of the LGPLv3 or higher. -from typing import Dict, Optional, Union, Any, cast import json import os import tempfile import platform -from typing import cast, List, TYPE_CHECKING, Tuple, Optional +from typing import cast, Any, Dict, List, Set, TYPE_CHECKING, Tuple, Optional from PyQt5.QtCore import QUrl, QObject, pyqtProperty, pyqtSignal, pyqtSlot from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply @@ -64,7 +63,8 @@ class Toolbox(QObject, Extension): ] self._request_urls = {} # type: Dict[str, QUrl] self._to_update = [] # type: List[str] # Package_ids that are waiting to be updated - self._old_plugin_ids = [] # type: List[str] + self._old_plugin_ids = set() # type: Set[str] + self._old_plugin_metadata = dict() # type: Dict[str, Dict[str, Any]] # Data: self._metadata = { @@ -289,8 +289,8 @@ class Toolbox(QObject, Extension): installed_package_ids = self._package_manager.getAllInstalledPackageIDs() scheduled_to_remove_package_ids = self._package_manager.getToRemovePackageIDs() - self._old_plugin_ids = [] - self._old_plugin_metadata = [] # type: List[Dict[str, Any]] + self._old_plugin_ids = set() + self._old_plugin_metadata = dict() for plugin_id in old_plugin_ids: # Neither the installed packages nor the packages that are scheduled to remove are old plugins @@ -300,12 +300,20 @@ class Toolbox(QObject, Extension): old_metadata = self._plugin_registry.getMetaData(plugin_id) new_metadata = self._convertPluginMetadata(old_metadata) - self._old_plugin_ids.append(plugin_id) - self._old_plugin_metadata.append(new_metadata) + self._old_plugin_ids.add(plugin_id) + self._old_plugin_metadata[new_metadata["package_id"]] = new_metadata all_packages = self._package_manager.getAllInstalledPackagesInfo() if "plugin" in all_packages: - self._metadata["plugins_installed"] = all_packages["plugin"] + self._old_plugin_metadata + # For old plugins, we only want to include the old custom plugin that were installed via the old toolbox. + # The bundled plugins will be included in the "bundled_packages.json", so the bundled plugins should be + # excluded from the old plugins list/dict. + all_plugin_package_ids = set(package["package_id"] for package in all_packages["plugin"]) + self._old_plugin_ids = set(plugin_id for plugin_id in self._old_plugin_ids + if plugin_id not in all_plugin_package_ids) + self._old_plugin_metadata = {k: v for k, v in self._old_plugin_metadata.items() if k in self._old_plugin_ids} + + self._metadata["plugins_installed"] = all_packages["plugin"] + list(self._old_plugin_metadata.values()) self._models["plugins_installed"].setMetadata(self._metadata["plugins_installed"]) self.metadataChanged.emit() if "material" in all_packages: @@ -475,12 +483,14 @@ class Toolbox(QObject, Extension): # -------------------------------------------------------------------------- @pyqtSlot(str, result = bool) def canUpdate(self, package_id: str) -> bool: - if self.isOldPlugin(package_id): - return True - local_package = self._package_manager.getInstalledPackageInfo(package_id) if local_package is None: - return False + Logger.log("i", "Could not find package [%s] as installed in the package manager, fall back to check the old plugins", + package_id) + local_package = self.getOldPluginPackageMetadata(package_id) + if local_package is None: + Logger.log("i", "Could not find package [%s] in the old plugins", package_id) + return False remote_package = self.getRemotePackage(package_id) if remote_package is None: @@ -548,12 +558,14 @@ class Toolbox(QObject, Extension): return False # Check for plugins that were installed with the old plugin browser - @pyqtSlot(str, result = bool) def isOldPlugin(self, plugin_id: str) -> bool: if plugin_id in self._old_plugin_ids: return True return False + def getOldPluginPackageMetadata(self, plugin_id: str) -> Optional[Dict[str, Any]]: + return self._old_plugin_metadata.get(plugin_id) + def loadingComplete(self) -> bool: populated = 0 for list in self._metadata.items(): diff --git a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml index 1077cbff6f..c8f391dfb0 100644 --- a/resources/qml/Preferences/Materials/MaterialsBrandSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsBrandSection.qml @@ -13,14 +13,28 @@ import Cura 1.0 as Cura Rectangle { id: brand_section - property var expanded: base.collapsed_brands.indexOf(model.name) > -1 - property var types_model: model.material_types + + property var sectionName: "" + property var elementsModel // This can be a MaterialTypesModel or GenericMaterialsModel or FavoriteMaterialsModel + property var hasMaterialTypes: true // It indicates wheather it has material types or not + property var expanded: materialList.expandedBrands.indexOf(sectionName) > -1 + height: childrenRect.height width: parent.width Rectangle { id: brand_header_background - color: UM.Theme.getColor("favorites_header_bar") + color: + { + if(!expanded && sectionName == materialList.currentBrand) + { + return UM.Theme.getColor("favorites_row_selected") + } + else + { + return UM.Theme.getColor("favorites_header_bar") + } + } anchors.fill: brand_header } Row @@ -30,11 +44,11 @@ Rectangle Label { id: brand_name - text: model.name + text: sectionName height: UM.Theme.getSize("favorites_row").height width: parent.width - UM.Theme.getSize("favorites_button").width verticalAlignment: Text.AlignVCenter - leftPadding: 4 + leftPadding: (UM.Theme.getSize("default_margin").width / 2) | 0 } Button { @@ -69,32 +83,68 @@ Rectangle anchors.fill: brand_header onPressed: { - const i = base.collapsed_brands.indexOf(model.name) + const i = materialList.expandedBrands.indexOf(sectionName) if (i > -1) { // Remove it - base.collapsed_brands.splice(i, 1) + materialList.expandedBrands.splice(i, 1) brand_section.expanded = false } else { // Add it - base.collapsed_brands.push(model.name) + materialList.expandedBrands.push(sectionName) brand_section.expanded = true } + UM.Preferences.setValue("cura/expanded_brands", materialList.expandedBrands.join(";")); } } Column { + id: brandMaterialList 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: MaterialsTypeSection {} + model: elementsModel + delegate: Loader + { + id: loader + width: parent.width + property var element: model + sourceComponent: hasMaterialTypes ? materialsTypeSection : materialSlot + } + } + } + + Component + { + id: materialsTypeSection + MaterialsTypeSection + { + materialType: element + } + } + + Component + { + id: materialSlot + MaterialsSlot + { + material: element + } + } + + Connections + { + target: UM.Preferences + onPreferenceChanged: + { + expanded = materialList.expandedBrands.indexOf(sectionName) > -1 } } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml index ad9f0e3766..f72d93aff3 100644 --- a/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml +++ b/resources/qml/Preferences/Materials/MaterialsDetailsPanel.qml @@ -13,21 +13,29 @@ Item { id: detailsPanel - property var currentItem: base.currentItem + property var currentItem: null - onCurrentItemChanged: { updateMaterialPropertiesObject(currentItem) } + onCurrentItemChanged: + { + // When the current item changes, the detail view needs to be updated + if (currentItem != null) + { + updateMaterialPropertiesObject() + materialDetailsView.currentMaterialNode = currentItem.container_node + } + } - function updateMaterialPropertiesObject( currentItem ) + function updateMaterialPropertiesObject() { materialProperties.name = currentItem.name || "Unknown" - materialProperties.guid = currentItem.GUID; + 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.adhesion_info = currentItem.adhesion_info || "" materialProperties.density = currentItem.density || 0.0 materialProperties.diameter = currentItem.diameter || 0.0 materialProperties.approximate_diameter = currentItem.approximate_diameter || "0" @@ -62,13 +70,11 @@ Item bottom: parent.bottom } - editingEnabled: base.currentItem != null && !base.currentItem.is_read_only + editingEnabled: currentItem != null && !currentItem.is_read_only properties: materialProperties - containerId: base.currentItem != null ? base.currentItem.id : "" - currentMaterialNode: base.currentItem.container_node - - + containerId: currentItem != null ? currentItem.id : "" + currentMaterialNode: currentItem.container_node } QtObject diff --git a/resources/qml/Preferences/Materials/MaterialsList.qml b/resources/qml/Preferences/Materials/MaterialsList.qml index 4a1a330ed6..cb5de685e2 100644 --- a/resources/qml/Preferences/Materials/MaterialsList.qml +++ b/resources/qml/Preferences/Materials/MaterialsList.qml @@ -13,7 +13,6 @@ import Cura 1.0 as Cura Item { id: materialList - width: materialScrollView.width - 17 height: childrenRect.height // Children @@ -21,179 +20,135 @@ Item Cura.MaterialBrandsModel { id: materialsModel } Cura.FavoriteMaterialsModel { id: favoriteMaterialsModel } Cura.GenericMaterialsModel { id: genericMaterialsModel } + + property var currentType: null + property var currentBrand: null + property var expandedBrands: UM.Preferences.getValue("cura/expanded_brands").split(";") + property var expandedTypes: UM.Preferences.getValue("cura/expanded_types").split(";") + + // Store information about which parts of the tree are expanded + function persistExpandedCategories() + { + UM.Preferences.setValue("cura/expanded_brands", materialList.expandedBrands.join(";")) + UM.Preferences.setValue("cura/expanded_types", materialList.expandedTypes.join(";")) + } + + // Expand the list of materials in order to select the current material + function expandActiveMaterial(search_root_id) + { + if (search_root_id == "") + { + // When this happens it means that the information of one of the materials has changed, so the model + // was updated and the list has to highlight the current item. + var currentItemId = base.currentItem == null ? "" : base.currentItem.root_material_id + search_root_id = currentItemId + } + for (var material_idx = 0; material_idx < genericMaterialsModel.rowCount(); material_idx++) + { + var material = genericMaterialsModel.getItem(material_idx) + if (material.root_material_id == search_root_id) + { + if (materialList.expandedBrands.indexOf("Generic") == -1) + { + materialList.expandedBrands.push("Generic") + } + materialList.currentBrand = "Generic" + base.currentItem = material + persistExpandedCategories() + return true + } + } + for (var brand_idx = 0; brand_idx < materialsModel.rowCount(); brand_idx++) + { + var brand = materialsModel.getItem(brand_idx) + var types_model = brand.material_types + for (var type_idx = 0; type_idx < types_model.rowCount(); type_idx++) + { + var type = types_model.getItem(type_idx) + var colors_model = type.colors + for (var material_idx = 0; material_idx < colors_model.rowCount(); material_idx++) + { + var material = colors_model.getItem(material_idx) + if (material.root_material_id == search_root_id) + { + if (materialList.expandedBrands.indexOf(brand.name) == -1) + { + materialList.expandedBrands.push(brand.name) + } + materialList.currentBrand = brand.name + if (materialList.expandedTypes.indexOf(brand.name + "_" + type.name) == -1) + { + materialList.expandedTypes.push(brand.name + "_" + type.name) + } + materialList.currentType = brand.name + "_" + type.name + base.currentItem = material + persistExpandedCategories() + return true + } + } + } + } + return false + } + + function updateAfterModelChanges() + { + var correctlyExpanded = materialList.expandActiveMaterial(base.newRootMaterialIdToSwitchTo) + if (correctlyExpanded) + { + if (base.toActivateNewMaterial) + { + var position = Cura.ExtruderManager.activeExtruderIndex + Cura.MachineManager.setMaterial(position, base.currentItem.container_node) + } + base.newRootMaterialIdToSwitchTo = "" + base.toActivateNewMaterial = false + } + } + + Connections + { + target: materialsModel + onItemsChanged: updateAfterModelChanges() + } + + Connections + { + target: genericMaterialsModel + onItemsChanged: updateAfterModelChanges() + } + Column { - Rectangle - { - property var expanded: true + width: materialList.width + height: childrenRect.height - id: favorites_section - height: childrenRect.height - width: materialList.width - Rectangle - { - id: favorites_header_background - color: UM.Theme.getColor("favorites_header_bar") - anchors.fill: favorites_header - } - Row - { - id: favorites_header - Label - { - 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: MaterialsSlot { - material: model - } - } - } - } - Rectangle + MaterialsBrandSection { - property var expanded: base.collapsed_brands.indexOf("Generic") > -1 - - 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: - { - 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 - { - 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: MaterialsSlot { - material: model - } - } - } + id: favoriteSection + sectionName: "Favorites" + elementsModel: favoriteMaterialsModel + hasMaterialTypes: false } + + MaterialsBrandSection + { + id: genericSection + sectionName: "Generic" + elementsModel: genericMaterialsModel + hasMaterialTypes: false + } + Repeater { - id: brand_list model: materialsModel - delegate: MaterialsBrandSection {} + delegate: MaterialsBrandSection + { + id: brandSection + sectionName: model.name + elementsModel: model.material_types + hasMaterialTypes: true + } } } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsPage.qml b/resources/qml/Preferences/Materials/MaterialsPage.qml index 0b81df5fa1..2050f59739 100644 --- a/resources/qml/Preferences/Materials/MaterialsPage.qml +++ b/resources/qml/Preferences/Materials/MaterialsPage.qml @@ -17,97 +17,35 @@ Item // Keep PreferencesDialog happy property var resetEnabled: false property var currentItem: null + + property var hasCurrentItem: base.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; + if (!hasCurrentItem) + { + return false + } + 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 - // TODO: Save these to preferences - property var collapsed_brands: [] - property var collapsed_types: [] + property var extruder_position: Cura.ExtruderManager.activeExtruderIndex + property var active_root_material_id: Cura.MachineManager.currentRootMaterialId[extruder_position] UM.I18nCatalog { id: catalog name: "cura" } - Cura.MaterialBrandsModel { id: materialsModel } - function findModelByRootId( search_root_id ) - { - 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 - } - } - } - } - } - 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]; - console.log("goign to search for", active_root_material_id) - base.currentItem = findModelByRootId(active_root_material_id) - } + // When loaded, try to select the active material in the tree + Component.onCompleted: materialListView.expandActiveMaterial(active_root_material_id) - onCurrentItemChanged: { MaterialsDetailsPanel.currentItem = currentItem } - 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; - } - } + // Every time the selected item has changed, notify to the details panel + onCurrentItemChanged: materialDetailsPanel.currentItem = currentItem // Main layout Label @@ -146,8 +84,10 @@ Item { forceActiveFocus() - const extruder_position = Cura.ExtruderManager.activeExtruderIndex; - Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node); + // Set the current material as the one to be activated (needed to force the UI update) + base.newRootMaterialIdToSwitchTo = base.currentItem.root_material_id + const extruder_position = Cura.ExtruderManager.activeExtruderIndex + Cura.MachineManager.setMaterial(extruder_position, base.currentItem.container_node) } } @@ -214,7 +154,7 @@ Item forceActiveFocus(); exportMaterialDialog.open(); } - enabled: currentItem != null + enabled: base.hasCurrentItem } } @@ -285,15 +225,20 @@ Item color: palette.light } - width: true ? (parent.width * 0.4) | 0 : parent.width + width: (parent.width * 0.4) | 0 frameVisible: true - verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn + horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOff - MaterialsList {} + MaterialsList + { + id: materialListView + width: materialScrollView.viewport.width + } } MaterialsDetailsPanel { + id: materialDetailsPanel anchors { left: materialScrollView.right @@ -316,6 +261,8 @@ Item modality: Qt.ApplicationModal onYes: { + // Set the active material as the fallback. It will be selected when the current material is deleted + base.newRootMaterialIdToSwitchTo = base.active_root_material_id base.materialManager.removeMaterial(base.currentItem.container_node); } } diff --git a/resources/qml/Preferences/Materials/MaterialsSlot.qml b/resources/qml/Preferences/Materials/MaterialsSlot.qml index ab0dd23750..a474b52838 100644 --- a/resources/qml/Preferences/Materials/MaterialsSlot.qml +++ b/resources/qml/Preferences/Materials/MaterialsSlot.qml @@ -12,109 +12,109 @@ import Cura 1.0 as Cura Rectangle { - id: material_slot - property var material + id: materialSlot + property var material: null property var hovered: false - property var is_favorite: material.is_favorite + property var is_favorite: material != null ? material.is_favorite : false height: UM.Theme.getSize("favorites_row").height width: parent.width - color: base.currentItem == model ? UM.Theme.getColor("favorites_row_selected") : "transparent" - - Item + color: material != null ? (base.currentItem.root_material_id == material.root_material_id ? UM.Theme.getColor("favorites_row_selected") : "transparent") : "transparent" + + Rectangle { + id: swatch + color: material != null ? material.color_code : "transparent" + 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: materialSlot.verticalCenter + anchors.left: materialSlot.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + } + Label + { + text: material != null ? material.brand + " " + material.name : "" + verticalAlignment: Text.AlignVCenter height: parent.height - width: parent.width - Rectangle + anchors.left: swatch.right + anchors.verticalCenter: materialSlot.verticalCenter + anchors.leftMargin: UM.Theme.getSize("narrow_margin").width + } + MouseArea + { + anchors.fill: parent + onClicked: { - 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 + materialList.currentBrand = material.brand + materialList.currentType = material.brand + "_" + material.material + base.currentItem = material } - Label + hoverEnabled: true + onEntered: { materialSlot.hovered = true } + onExited: { materialSlot.hovered = false } + } + Button + { + id: favorite_button + text: "" + implicitWidth: UM.Theme.getSize("favorites_button").width + implicitHeight: UM.Theme.getSize("favorites_button").height + visible: materialSlot.hovered || materialSlot.is_favorite || favorite_button.hovered + anchors { - 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 + right: materialSlot.right + verticalCenter: materialSlot.verticalCenter } - MouseArea + onClicked: { - 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 + if (materialSlot.is_favorite) { + base.materialManager.removeFavorite(material.root_material_id) + materialSlot.is_favorite = false return } - style: ButtonStyle + base.materialManager.addFavorite(material.root_material_id) + materialSlot.is_favorite = true + return + } + style: ButtonStyle + { + background: Rectangle { - background: Rectangle - { - anchors.fill: parent - color: "transparent" - } + anchors.fill: parent + color: "transparent" } - UM.RecolorImage { - anchors + } + UM.RecolorImage { + anchors + { + verticalCenter: favorite_button.verticalCenter + horizontalCenter: favorite_button.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) { - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter + return UM.Theme.getColor("primary_hover") } - width: UM.Theme.getSize("favorites_button_icon").width - height: UM.Theme.getSize("favorites_button_icon").height - sourceSize.width: width - sourceSize.height: height - color: + else { - if (favorite_button.hovered) + if (materialSlot.is_favorite) { - return UM.Theme.getColor("primary_hover") + return UM.Theme.getColor("primary") } else { - if (material_slot.is_favorite) - { - return UM.Theme.getColor("primary") - } - else - { - UM.Theme.getColor("text_inactive") - } + UM.Theme.getColor("text_inactive") } } - source: material_slot.is_favorite ? UM.Theme.getIcon("favorites_star_full") : UM.Theme.getIcon("favorites_star_empty") } + source: materialSlot.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/Materials/MaterialsTypeSection.qml b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml index 11bf2385e1..f62fc4ee16 100644 --- a/resources/qml/Preferences/Materials/MaterialsTypeSection.qml +++ b/resources/qml/Preferences/Materials/MaterialsTypeSection.qml @@ -13,14 +13,32 @@ import Cura 1.0 as Cura Rectangle { id: material_type_section - property var expanded: base.collapsed_types.indexOf(model.brand + "_" + model.name) > -1 - property var colors_model: model.colors + property var materialType + property var expanded: materialList.expandedTypes.indexOf(materialType.brand + "_" + materialType.name) > -1 + property var colorsModel: materialType.colors height: childrenRect.height width: parent.width Rectangle { id: material_type_header_background - color: UM.Theme.getColor("lining") + color: + { + if(!expanded && materialType.brand + "_" + materialType.name == materialList.currentType) + { + return UM.Theme.getColor("favorites_row_selected") + } + else + { + return "transparent" + } + } + width: parent.width + height: material_type_header.height + } + Rectangle + { + id: material_type_header_border + color: UM.Theme.getColor("favorites_header_bar") anchors.bottom: material_type_header.bottom anchors.left: material_type_header.left height: UM.Theme.getSize("default_lining").height @@ -29,17 +47,17 @@ Rectangle Row { id: material_type_header - width: parent.width - 8 + width: parent.width + leftPadding: UM.Theme.getSize("default_margin").width anchors { left: parent.left - leftMargin: 8 } Label { - text: model.name + text: materialType.name height: UM.Theme.getSize("favorites_row").height - width: parent.width - UM.Theme.getSize("favorites_button").width + width: parent.width - parent.leftPadding - UM.Theme.getSize("favorites_button").width id: material_type_name verticalAlignment: Text.AlignVCenter } @@ -76,19 +94,21 @@ Rectangle anchors.fill: material_type_header onPressed: { - const i = base.collapsed_types.indexOf(model.brand + "_" + model.name) + const identifier = materialType.brand + "_" + materialType.name; + const i = materialList.expandedTypes.indexOf(identifier) if (i > -1) { // Remove it - base.collapsed_types.splice(i, 1) + materialList.expandedTypes.splice(i, 1) material_type_section.expanded = false } else { // Add it - base.collapsed_types.push(model.brand + "_" + model.name) + materialList.expandedTypes.push(identifier) material_type_section.expanded = true } + UM.Preferences.setValue("cura/expanded_types", materialList.expandedTypes.join(";")); } } Column @@ -97,13 +117,22 @@ Rectangle visible: material_type_section.expanded width: parent.width anchors.top: material_type_header.bottom - anchors.left: parent.left Repeater { - model: colors_model - delegate: MaterialsSlot { + model: colorsModel + delegate: MaterialsSlot + { material: model } } } + + Connections + { + target: UM.Preferences + onPreferenceChanged: + { + expanded = materialList.expandedTypes.indexOf(materialType.brand + "_" + materialType.name) > -1 + } + } } \ No newline at end of file diff --git a/resources/qml/Preferences/Materials/MaterialsView.qml b/resources/qml/Preferences/Materials/MaterialsView.qml index a03e5c48d7..56fa12877f 100644 --- a/resources/qml/Preferences/Materials/MaterialsView.qml +++ b/resources/qml/Preferences/Materials/MaterialsView.qml @@ -40,7 +40,7 @@ TabView { return "" } - var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentItem.container_node, true); + var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentMaterialNode, true); if (linkedMaterials.length == 0) { return "" @@ -191,6 +191,7 @@ TabView ReadOnlyTextField { id: colorLabel; + width: parent.width - colorSelector.width - parent.spacing text: properties.color_name; readOnly: !base.editingEnabled onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text) @@ -567,25 +568,25 @@ TabView // don't change when new name is the same if (old_name == new_name) { - return; + return } // update the values - base.materialManager.setMaterialName(base.currentMaterialNode, new_name); - materialProperties.name = new_name; + base.materialManager.setMaterialName(base.currentMaterialNode, new_name) + properties.name = new_name } // update the type of the material - function updateMaterialType (old_type, new_type) + function updateMaterialType(old_type, new_type) { - base.setMetaDataEntry("material", old_type, new_type); - materialProperties.material= new_type; + base.setMetaDataEntry("material", old_type, new_type) + properties.material = new_type } // update the brand of the material - function updateMaterialBrand (old_brand, new_brand) + function updateMaterialBrand(old_brand, new_brand) { - base.setMetaDataEntry("brand", old_brand, new_brand); - materialProperties.brand = new_brand; + base.setMetaDataEntry("brand", old_brand, new_brand) + properties.brand = new_brand } }