MaterialBrandsModel.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
  4. from UM.Qt.ListModel import ListModel
  5. from UM.Logger import Logger
  6. from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
  7. class MaterialTypesModel(ListModel):
  8. def __init__(self, parent = None):
  9. super().__init__(parent)
  10. self.addRoleName(Qt.UserRole + 1, "name")
  11. self.addRoleName(Qt.UserRole + 2, "brand")
  12. self.addRoleName(Qt.UserRole + 3, "colors")
  13. class MaterialBrandsModel(BaseMaterialsModel):
  14. extruderPositionChanged = pyqtSignal()
  15. def __init__(self, parent = None):
  16. super().__init__(parent)
  17. self.addRoleName(Qt.UserRole + 1, "name")
  18. self.addRoleName(Qt.UserRole + 2, "material_types")
  19. self._update()
  20. def _update(self):
  21. if not self._canUpdate():
  22. return
  23. # Get updated list of favorites
  24. self._favorite_ids = self._material_manager.getFavorites()
  25. brand_item_list = []
  26. brand_group_dict = {}
  27. # Part 1: Generate the entire tree of brands -> material types -> spcific materials
  28. for root_material_id, container_node in self._available_materials.items():
  29. # Do not include the materials from a to-be-removed package
  30. if bool(container_node.getMetaDataEntry("removed", False)):
  31. continue
  32. # Add brands we haven't seen yet to the dict, skipping generics
  33. brand = container_node.getMetaDataEntry("brand", "")
  34. if brand.lower() == "generic":
  35. continue
  36. if brand not in brand_group_dict:
  37. brand_group_dict[brand] = {}
  38. # Add material types we haven't seen yet to the dict
  39. material_type = container_node.getMetaDataEntry("material", "")
  40. if material_type not in brand_group_dict[brand]:
  41. brand_group_dict[brand][material_type] = []
  42. # Now handle the individual materials
  43. item = self._createMaterialItem(root_material_id, container_node)
  44. brand_group_dict[brand][material_type].append(item)
  45. # Part 2: Organize the tree into models
  46. #
  47. # Normally, the structure of the menu looks like this:
  48. # Brand -> Material Type -> Specific Material
  49. #
  50. # To illustrate, a branded material menu may look like this:
  51. # Ultimaker ┳ PLA ┳ Yellow PLA
  52. # ┃ ┣ Black PLA
  53. # ┃ ┗ ...
  54. # ┃
  55. # ┗ ABS ┳ White ABS
  56. # ┗ ...
  57. for brand, material_dict in brand_group_dict.items():
  58. material_type_item_list = []
  59. brand_item = {
  60. "name": brand,
  61. "material_types": MaterialTypesModel(self)
  62. }
  63. for material_type, material_list in material_dict.items():
  64. material_type_item = {
  65. "name": material_type,
  66. "brand": brand,
  67. "colors": BaseMaterialsModel(self)
  68. }
  69. material_type_item["colors"].clear()
  70. # Sort materials by name
  71. material_list = sorted(material_list, key = lambda x: x["name"].upper())
  72. material_type_item["colors"].setItems(material_list)
  73. material_type_item_list.append(material_type_item)
  74. # Sort material type by name
  75. material_type_item_list = sorted(material_type_item_list, key = lambda x: x["name"].upper())
  76. brand_item["material_types"].setItems(material_type_item_list)
  77. brand_item_list.append(brand_item)
  78. # Sort brand by name
  79. brand_item_list = sorted(brand_item_list, key = lambda x: x["name"].upper())
  80. self.setItems(brand_item_list)