Merge branch 'master' into patch-2

This commit is contained in:
Mark 2018-08-29 13:55:42 +02:00 committed by GitHub
commit 17f51ca704
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 1284 additions and 798 deletions

View File

@ -67,9 +67,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
@ -480,7 +480,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")
preferences.addPreference("cura/favorite_materials", ";".join([]))
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
@ -911,9 +913,9 @@ 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")
qmlRegisterType(MaterialBrandsModel, "Cura", 1, 0, "MaterialBrandsModel")
qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")

View File

@ -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,11 @@ class MaterialManager(QObject):
self.materialsUpdated.emit()
favorites = self._application.getPreferences().getValue("cura/favorite_materials")
for item in favorites.split(";"):
self._favorites.add(item)
self.favoritesUpdated.emit()
def __addMaterialMetadataIntoLookupTree(self, material_metadata: dict) -> None:
material_id = material_metadata["id"]
@ -608,3 +617,25 @@ class MaterialManager(QObject):
new_base_id = new_id,
new_metadata = new_metadata)
return new_id
@pyqtSlot(str)
def addFavorite(self, root_material_id: str):
self._favorites.add(root_material_id)
self.favoritesUpdated.emit()
# Ensure all settings are saved.
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()
# Ensure all settings are saved.
self._application.getPreferences().setValue("cura/favorite_materials", ";".join(list(self._favorites)))
self._application.saveSettings()
@pyqtSlot()
def getFavorites(self):
return self._favorites

View File

@ -2,45 +2,63 @@
# 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
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.NameRole, "name")
self.addRoleName(self.BrandRole, "brand")
self.addRoleName(self.MaterialRole, "material")
self.addRoleName(self.ColorRole, "color_name")
self.addRoleName(self.ContainerNodeRole, "container_node")
from cura.CuraApplication import CuraApplication
self._application = CuraApplication.getInstance()
# Make these managers available to all material models
self._container_registry = self._application.getInstance().getContainerRegistry()
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)
# 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")
self.addRoleName(Qt.UserRole + 4, "name")
self.addRoleName(Qt.UserRole + 5, "brand")
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
# 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
@ -65,8 +83,55 @@ 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
## 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.get("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

View File

@ -1,157 +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._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._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
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
if brand not in brand_group_dict:
brand_group_dict[brand] = {}
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
}
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)

View File

@ -0,0 +1,42 @@
# 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)
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()
item_list = []
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 = self._createMaterialItem(root_material_id, container_node)
item_list.append(item)
# Sort the item list alphabetically by name
item_list = sorted(item_list, key = lambda d: d["brand"].upper())
self.setItems(item_list)

View File

@ -4,63 +4,39 @@
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:
# 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
# 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 generic materials
if metadata["brand"].lower() != "generic":
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
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
}
# 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 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)

View File

@ -0,0 +1,107 @@
# 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)
self.addRoleName(Qt.UserRole + 1, "name")
self.addRoleName(Qt.UserRole + 2, "material_types")
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 = self._createMaterialItem(root_material_id, container_node)
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)

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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)

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Checks for firmware updates.",
"api": 4,
"api": 5,
"i18n-catalog": "cura"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.",
"version": "1.0.0",
"description": "Provides the Simulation view.",
"api": 4,
"api": 5,
"i18n-catalog": "cura"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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."
}

View File

@ -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"
}

View File

@ -364,7 +364,6 @@ Cura.MachineAction
{
id: addressField
width: parent.width
maximumLength: 40
validator: RegExpValidator
{
regExp: /[a-zA-Z0-9\.\-\_]*/

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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",

View File

@ -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 }
}
}

View File

@ -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 }
}
}

View File

@ -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 }
}
}

View File

@ -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 }
}
}

View File

@ -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 }
}
}

View File

@ -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 }
}
}

View File

@ -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();
}

View File

@ -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" };
@ -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"));

View File

@ -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;
}

View File

@ -10,28 +10,74 @@ import Cura 1.0 as Cura
Menu
{
id: menu
title: "Material"
title: catalog.i18nc("@label:category menu label", "Material")
property int extruderIndex: 0
Cura.FavoriteMaterialsModel
{
id: favoriteMaterialsModel
extruderPosition: menu.extruderIndex
}
Cura.GenericMaterialsModel
{
id: genericMaterialsModel
extruderPosition: menu.extruderIndex
}
Cura.MaterialBrandsModel
{
id: brandModel
extruderPosition: menu.extruderIndex
}
MenuItem
{
text: catalog.i18nc("@label:category menu label", "Favorites")
enabled: false
visible: favoriteMaterialsModel.items.length > 0
}
Instantiator
{
model: genericMaterialsModel
MenuItem
model: favoriteMaterialsModel
delegate: MenuItem
{
text: model.name
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
onTriggered:
{
Cura.MachineManager.setMaterial(extruderIndex, model.container_node);
}
}
onObjectAdded: menu.insertItem(index, object)
onObjectRemoved: menu.removeItem(object)
onObjectRemoved: menu.removeItem(object) // TODO: This ain't gonna work, removeItem() takes an index, not object
}
MenuSeparator { }
MenuSeparator {}
Menu
{
id: genericMenu
title: catalog.i18nc("@label:category menu label", "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
@ -40,12 +86,12 @@ Menu
id: brandMenu
title: brandName
property string brandName: model.name
property var brandMaterials: model.materials
property var brandMaterials: model.material_types
Instantiator
{
model: brandMaterials
Menu
delegate: Menu
{
id: brandMaterialsMenu
title: materialName
@ -55,16 +101,13 @@ Menu
Instantiator
{
model: brandMaterialColors
MenuItem
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);
}
onTriggered: Cura.MachineManager.setMaterial(extruderIndex, model.container_node)
}
onObjectAdded: brandMaterialsMenu.insertItem(index, object)
onObjectRemoved: brandMaterialsMenu.removeItem(object)
@ -78,21 +121,14 @@ Menu
onObjectRemoved: menu.removeItem(object)
}
Cura.GenericMaterialsModel
{
id: genericMaterialsModel
extruderPosition: menu.extruderIndex
ExclusiveGroup {
id: group
}
Cura.BrandMaterialsModel
MenuSeparator {}
MenuItem
{
id: brandModel
extruderPosition: menu.extruderIndex
action: Cura.Actions.manageMaterials
}
ExclusiveGroup { id: group }
MenuSeparator { }
MenuItem { action: Cura.Actions.manageMaterials }
}

View File

@ -0,0 +1,100 @@
// 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: base.collapsed_brands.indexOf(model.name) > -1
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:
{
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
{
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 {}
}
}
}

View File

@ -0,0 +1,102 @@
// 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
property var currentItem: base.currentItem
onCurrentItemChanged: { updateMaterialPropertiesObject(currentItem) }
function updateMaterialPropertiesObject( currentItem )
{
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
{
anchors.fill: parent
Item // Material title Label
{
id: profileName
width: parent.width
height: childrenRect.height
Label {
text: materialProperties.name
font: UM.Theme.getFont("large")
}
}
MaterialsView // 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.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: "";
}
}
}

View File

@ -0,0 +1,199 @@
// 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
width: materialScrollView.width - 17
height: childrenRect.height
// Children
UM.I18nCatalog { id: catalog; name: "cura"; }
Cura.MaterialBrandsModel { id: materialsModel }
Cura.FavoriteMaterialsModel { id: favoriteMaterialsModel }
Cura.GenericMaterialsModel { id: genericMaterialsModel }
Column
{
Rectangle
{
property var expanded: true
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
{
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
}
}
}
}
Repeater
{
id: brand_list
model: materialsModel
delegate: MaterialsBrandSection {}
}
}
}

View File

@ -9,25 +9,110 @@ 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
UM.I18nCatalog { id: catalog; name: "cura"; }
Cura.MaterialManagementModel
// Keep PreferencesDialog happy
property var resetEnabled: false
property var currentItem: null
property var isCurrentItemActivated:
{
id: materialsModel
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: []
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)
}
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;
}
}
// Main layout
Label
{
id: titleLabel
anchors
{
top: parent.top
@ -35,45 +120,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
@ -166,63 +218,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;
top: titleLabel.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
margins: 5 * screenScaleFactor
bottomMargin: 0
}
clip: true
}
// try to pick the currently selected item; it may have been moved
if (base.newRootMaterialIdToSwitchTo == "")
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
{
base.newRootMaterialIdToSwitchTo = currentItemId;
top: parent.top
left: parent.left
}
for (var idx = 0; idx < materialsModel.rowCount(); ++idx)
visible: text != ""
text:
{
var item = materialsModel.getItem(idx);
if (item.root_material_id == base.newRootMaterialIdToSwitchTo)
var caption = catalog.i18nc("@action:label", "Printer") + ": " + Cura.MachineManager.activeMachineName;
if (Cura.MachineManager.hasVariants)
{
// 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
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
}
materialListView.currentIndex = 0;
materialListView.activateDetailsWithIndex(materialListView.currentIndex);
if (base.toActivateNewMaterial)
Rectangle
{
Cura.MachineManager.setMaterial(position, materialsModel.getItem(0).container_node);
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
}
base.newRootMaterialIdToSwitchTo = "";
base.toActivateNewMaterial = false;
}
}
// 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);
@ -292,281 +383,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
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);
}
}
}
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()
{
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: "";
}
}
}
}
}

View File

@ -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"
Item
{
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")
}
}
}
}

View File

@ -0,0 +1,109 @@
// 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: base.collapsed_types.indexOf(model.brand + "_" + model.name) > -1
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:
{
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
{
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: MaterialsSlot {
material: model
}
}
}
}

View File

@ -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
@ -38,7 +40,7 @@ TabView
{
return ""
}
var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentMaterialNode, true);
var linkedMaterials = Cura.ContainerManager.getLinkedMaterials(base.currentItem.container_node, true);
if (linkedMaterials.length == 0)
{
return ""

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path d="M255.8,69l56.6,114.7l5.8,11.8l13,1.9l126.6,18.4l-91.6,89.3l-9.4,9.2l2.2,13l21.6,126.1l-113.2-59.5l-11.6-6.1l-11.6,6.1
l-113.2,59.5l21.6-126.1l2.2-13l-9.4-9.2l-91.6-89.3l126.6-18.4l13-1.9l5.8-11.8L255.8,69 M255.8,12.5l-79,160.1L0,198.3L127.9,323
L97.7,499l158.1-83.1L413.8,499l-30.2-176l127.9-124.6l-176.7-25.7L255.8,12.5L255.8,12.5z"/>
</svg>

After

Width:  |  Height:  |  Size: 703 B

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<polygon points="255.8,12.5 334.8,172.7 511.5,198.3 383.6,323 413.8,499 255.8,415.9 97.7,499 127.9,323 0,198.3 176.7,172.7 "/>
</svg>

After

Width:  |  Height:  |  Size: 483 B

View File

@ -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],