Merge branch 'CURA-6706_intents_on_quality_mgr_page' of github.com:Ultimaker/Cura into feature_intent

This commit is contained in:
Jaime van Kessel 2019-10-07 16:14:24 +02:00
commit cb526f0f31
No known key found for this signature in database
GPG Key ID: 3710727397403C91
6 changed files with 123 additions and 39 deletions

View File

@ -65,30 +65,28 @@ class IntentModel(ListModel):
material_nodes = self._getActiveMaterials() material_nodes = self._getActiveMaterials()
layer_heights_added = [] # type: List[float] added_quality_type_set = set() # type: Set[str]
for material_node in material_nodes: for material_node in material_nodes:
intents = self._getIntentsForMaterial(material_node, quality_groups) intents = self._getIntentsForMaterial(material_node, quality_groups)
for intent in intents: for intent in intents:
if intent["layer_height"] not in layer_heights_added: if intent["quality_type"] not in added_quality_type_set:
new_items.append(intent) new_items.append(intent)
layer_heights_added.append(intent["layer_height"]) added_quality_type_set.add(intent["quality_type"])
# Now that we added all intents that we found something for, ensure that we set add ticks (and layer_heights) # Now that we added all intents that we found something for, ensure that we set add ticks (and layer_heights)
# for all groups that we don't have anything for (and set it to not available) # for all groups that we don't have anything for (and set it to not available)
for quality_tuple, quality_group in quality_groups.items(): for quality_type, quality_group in quality_groups.items():
# Add the intents that are of the correct category # Add the intents that are of the correct category
if quality_tuple[0] != self._intent_category: if quality_type not in added_quality_type_set:
layer_height = fetchLayerHeight(quality_group) layer_height = fetchLayerHeight(quality_group)
if layer_height not in layer_heights_added: new_items.append({"name": "Unavailable",
new_items.append({"name": "Unavailable", "quality_type": quality_type,
"quality_type": "", "layer_height": layer_height,
"layer_height": layer_height, "intent_category": self._intent_category,
"intent_category": self._intent_category, "available": False})
"available": False}) added_quality_type_set.add(quality_type)
layer_heights_added.append(layer_height)
new_items = sorted(new_items, key=lambda x: x["layer_height"]) new_items = sorted(new_items, key = lambda x: x["layer_height"])
self.setItems(new_items) self.setItems(new_items)
## Get the active materials for all extruders. No duplicates will be returned ## Get the active materials for all extruders. No duplicates will be returned
@ -122,11 +120,11 @@ class IntentModel(ListModel):
if intent_node.intent_category != self._intent_category: if intent_node.intent_category != self._intent_category:
continue continue
extruder_intents.append({"name": quality_group.name, extruder_intents.append({"name": quality_group.name,
"quality_type": quality_group.quality_type, "quality_type": quality_group.quality_type,
"layer_height": layer_height, "layer_height": layer_height,
"available": quality_group.is_available, "available": quality_group.is_available,
"intent_category": self._intent_category "intent_category": self._intent_category
}) })
return extruder_intents return extruder_intents
def __repr__(self): def __repr__(self):

View File

@ -12,6 +12,10 @@ import cura.CuraApplication # Imported this way to prevent circular imports.
from cura.Settings.ContainerManager import ContainerManager from cura.Settings.ContainerManager import ContainerManager
from cura.Machines.ContainerTree import ContainerTree from cura.Machines.ContainerTree import ContainerTree
from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container
from cura.Settings.IntentManager import IntentManager
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
if TYPE_CHECKING: if TYPE_CHECKING:
from UM.Settings.Interfaces import ContainerInterface from UM.Settings.Interfaces import ContainerInterface
@ -19,6 +23,7 @@ if TYPE_CHECKING:
from cura.Settings.ExtruderStack import ExtruderStack from cura.Settings.ExtruderStack import ExtruderStack
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
# #
# This the QML model for the quality management page. # This the QML model for the quality management page.
# #
@ -26,15 +31,21 @@ class QualityManagementModel(ListModel):
NameRole = Qt.UserRole + 1 NameRole = Qt.UserRole + 1
IsReadOnlyRole = Qt.UserRole + 2 IsReadOnlyRole = Qt.UserRole + 2
QualityGroupRole = Qt.UserRole + 3 QualityGroupRole = Qt.UserRole + 3
QualityChangesGroupRole = Qt.UserRole + 4 QualityTypeRole = Qt.UserRole + 4
QualityChangesGroupRole = Qt.UserRole + 5
IntentCategoryRole = Qt.UserRole + 6
SectionNameRole = Qt.UserRole + 7
def __init__(self, parent = None): def __init__(self, parent: Optional["QObject"] = None) -> None:
super().__init__(parent) super().__init__(parent)
self.addRoleName(self.NameRole, "name") self.addRoleName(self.NameRole, "name")
self.addRoleName(self.IsReadOnlyRole, "is_read_only") self.addRoleName(self.IsReadOnlyRole, "is_read_only")
self.addRoleName(self.QualityGroupRole, "quality_group") self.addRoleName(self.QualityGroupRole, "quality_group")
self.addRoleName(self.QualityTypeRole, "quality_type")
self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group") self.addRoleName(self.QualityChangesGroupRole, "quality_changes_group")
self.addRoleName(self.IntentCategoryRole, "intent_category")
self.addRoleName(self.SectionNameRole, "section_name")
application = cura.CuraApplication.CuraApplication.getInstance() application = cura.CuraApplication.CuraApplication.getInstance()
container_registry = application.getContainerRegistry() container_registry = application.getContainerRegistry()
@ -127,11 +138,13 @@ class QualityManagementModel(ListModel):
container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry() container_registry = cura.CuraApplication.CuraApplication.getInstance().getContainerRegistry()
new_name = container_registry.uniqueName(new_name) new_name = container_registry.uniqueName(new_name)
intent_category = quality_model_item["intent_category"]
quality_group = quality_model_item["quality_group"] quality_group = quality_model_item["quality_group"]
quality_changes_group = quality_model_item["quality_changes_group"] quality_changes_group = quality_model_item["quality_changes_group"]
if quality_changes_group is None: if quality_changes_group is None:
# Create global quality changes only. # Create global quality changes only.
new_quality_changes = self._createQualityChanges(quality_group.quality_type, None, new_name, global_stack, extruder_stack = None) new_quality_changes = self._createQualityChanges(quality_group.quality_type, intent_category, new_name,
global_stack, extruder_stack = None)
container_registry.addContainer(new_quality_changes) container_registry.addContainer(new_quality_changes)
else: else:
for metadata in [quality_changes_group.metadata_for_global] + list(quality_changes_group.metadata_per_extruder.values()): for metadata in [quality_changes_group.metadata_for_global] + list(quality_changes_group.metadata_per_extruder.values()):
@ -233,6 +246,30 @@ class QualityManagementModel(ListModel):
if container.getMetaDataEntry("type") == "quality_changes": if container.getMetaDataEntry("type") == "quality_changes":
self._update() self._update()
@pyqtSlot("QVariantMap", result = str)
def getQualityItemDisplayName(self, quality_model_item: Dict[str, Any]) -> str:
quality_group = quality_model_item["quality_group"]
is_read_only = quality_model_item["is_read_only"]
intent_category = quality_model_item["intent_category"]
quality_level_name = "Not Supported"
if quality_group is not None:
quality_level_name = quality_group.name
display_name = quality_level_name
if intent_category != "default":
intent_display_name = catalog.i18nc("@label", intent_category.capitalize())
display_name = "{intent_name} - {the_rest}".format(intent_name = intent_display_name,
the_rest = display_name)
# A custom quality
if not is_read_only:
display_name = "{custom_profile_name} - {the_rest}".format(custom_profile_name = quality_model_item["name"],
the_rest = display_name)
return display_name
def _update(self): def _update(self):
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__)) Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
@ -253,7 +290,7 @@ class QualityManagementModel(ListModel):
return return
item_list = [] item_list = []
# Create quality group items # Create quality group items (intent category = "default")
for quality_group in quality_group_dict.values(): for quality_group in quality_group_dict.values():
if not quality_group.is_available: if not quality_group.is_available:
continue continue
@ -261,11 +298,33 @@ class QualityManagementModel(ListModel):
item = {"name": quality_group.name, item = {"name": quality_group.name,
"is_read_only": True, "is_read_only": True,
"quality_group": quality_group, "quality_group": quality_group,
"quality_changes_group": None} "quality_type": quality_group.quality_type,
"quality_changes_group": None,
"intent_category": "default",
"section_name": catalog.i18nc("@label", "Default"),
}
item_list.append(item) item_list.append(item)
# Sort by quality names # Sort by quality names
item_list = sorted(item_list, key = lambda x: x["name"].upper()) item_list = sorted(item_list, key = lambda x: x["name"].upper())
# Create intent items (non-default)
available_intent_list = IntentManager.getInstance().getCurrentAvailableIntents()
available_intent_list = [i for i in available_intent_list if i[0] != "default"]
result = []
for intent_category, quality_type in available_intent_list:
result.append({
"name": quality_group_dict[quality_type].name, # Use the quality name as the display name
"is_read_only": True,
"quality_group": quality_group_dict[quality_type],
"quality_type": quality_type,
"quality_changes_group": None,
"intent_category": intent_category,
"section_name": catalog.i18nc("@label", intent_category.capitalize()),
})
# Sort by quality_type for each intent category
result = sorted(result, key = lambda x: (x["intent_category"], x["quality_type"]))
item_list += result
# Create quality_changes group items # Create quality_changes group items
quality_changes_item_list = [] quality_changes_item_list = []
for quality_changes_group in quality_changes_group_list: for quality_changes_group in quality_changes_group_list:
@ -273,7 +332,11 @@ class QualityManagementModel(ListModel):
item = {"name": quality_changes_group.name, item = {"name": quality_changes_group.name,
"is_read_only": False, "is_read_only": False,
"quality_group": quality_group, "quality_group": quality_group,
"quality_changes_group": quality_changes_group} "quality_type": quality_group.quality_type,
"quality_changes_group": quality_changes_group,
"intent_category": quality_changes_group.intent_category,
"section_name": catalog.i18nc("@label", "Custom profiles"),
}
quality_changes_item_list.append(item) quality_changes_item_list.append(item)
# Sort quality_changes items by names and append to the item list # Sort quality_changes items by names and append to the item list

View File

@ -80,7 +80,7 @@ class IntentManager(QObject):
for extruder_stack in global_stack.extruderList: for extruder_stack in global_stack.extruderList:
nozzle_name = extruder_stack.variant.getMetaDataEntry("name") nozzle_name = extruder_stack.variant.getMetaDataEntry("name")
material_id = extruder_stack.material.getMetaDataEntry("base_file") material_id = extruder_stack.material.getMetaDataEntry("base_file")
final_intent_ids |= {metadata["id"] for metadata in self.intentMetadatas(current_definition_id, nozzle_name, material_id) if metadata["quality_type"] in available_quality_types} final_intent_ids |= {metadata["id"] for metadata in self.intentMetadatas(current_definition_id, nozzle_name, material_id) if metadata.get("quality_type") in available_quality_types}
result = set() # type: Set[Tuple[str, str]] result = set() # type: Set[Tuple[str, str]]
for intent_id in final_intent_ids: for intent_id in final_intent_ids:

View File

@ -637,6 +637,7 @@ class MachineManager(QObject):
category = extruder.intent.getMetaDataEntry("intent_category", "default") category = extruder.intent.getMetaDataEntry("intent_category", "default")
if category != "default" and category != intent_category: if category != "default" and category != intent_category:
intent_category = category intent_category = category
return intent_category return intent_category
# Provies a list of extruder positions that have a different intent from the active one. # Provies a list of extruder positions that have a different intent from the active one.
@ -1626,6 +1627,7 @@ class MachineManager(QObject):
# Otherwise the intent profile will be left to the empty profile, which # Otherwise the intent profile will be left to the empty profile, which
# represents the "default" intent category. # represents the "default" intent category.
# \param intent_category The intent category to change to. # \param intent_category The intent category to change to.
@pyqtSlot(str)
def setIntentByCategory(self, intent_category: str) -> None: def setIntentByCategory(self, intent_category: str) -> None:
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
if global_stack is None: if global_stack is None:

View File

@ -7,7 +7,7 @@ import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import UM 1.2 as UM import UM 1.2 as UM
import Cura 1.0 as Cura import Cura 1.6 as Cura
Item Item
@ -43,6 +43,7 @@ Item
} }
property var currentItemName: hasCurrentItem ? base.currentItem.name : "" property var currentItemName: hasCurrentItem ? base.currentItem.name : ""
property var currentItemDisplayName: hasCurrentItem ? base.qualityManagementModel.getQualityItemDisplayName(base.currentItem) : ""
property var isCurrentItemActivated: property var isCurrentItemActivated:
{ {
@ -50,7 +51,14 @@ Item
{ {
return false; return false;
} }
return base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName; if (base.currentItem.is_read_only)
{
return (base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName) && (base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory);
}
else
{
return base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName;
}
} }
property var canCreateProfile: property var canCreateProfile:
@ -80,7 +88,7 @@ Item
{ {
if (base.currentItem.is_read_only) if (base.currentItem.is_read_only)
{ {
Cura.MachineManager.setQualityGroup(base.currentItem.quality_group); Cura.IntentManager.selectIntent(base.currentItem.intent_category, base.currentItem.quality_type);
} }
else else
{ {
@ -434,7 +442,7 @@ Item
} }
} }
section.property: "is_read_only" section.property: "section_name"
section.delegate: Rectangle section.delegate: Rectangle
{ {
height: childrenRect.height height: childrenRect.height
@ -443,7 +451,7 @@ Item
{ {
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_lining").width anchors.leftMargin: UM.Theme.getSize("default_lining").width
text: section == "true" ? catalog.i18nc("@label", "Default profiles") : catalog.i18nc("@label", "Custom profiles") text: section
font.bold: true font.bold: true
} }
} }
@ -467,7 +475,19 @@ Item
width: Math.floor((parent.width * 0.8)) width: Math.floor((parent.width * 0.8))
text: model.name text: model.name
elide: Text.ElideRight elide: Text.ElideRight
font.italic: model.name == Cura.MachineManager.activeQualityOrQualityChangesName font.italic:
{
if (model.is_read_only)
{
// For built-in qualities, it needs to match both the intent category and the quality name
return model.name == Cura.MachineManager.activeQualityOrQualityChangesName && model.intent_category == Cura.MachineManager.activeIntentCategory
}
else
{
// For custom qualities, it only needs to match the name
return model.name == Cura.MachineManager.activeQualityOrQualityChangesName
}
}
color: parent.isCurrentItem ? palette.highlightedText : palette.text color: parent.isCurrentItem ? palette.highlightedText : palette.text
} }
@ -511,7 +531,7 @@ Item
Label Label
{ {
text: base.currentItemName text: base.currentItemDisplayName
font: UM.Theme.getFont("large_bold") font: UM.Theme.getFont("large_bold")
} }
} }
@ -519,7 +539,7 @@ Item
Flow Flow
{ {
id: currentSettingsActions id: currentSettingsActions
visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName visible: base.hasCurrentItem && base.currentItem.name == Cura.MachineManager.activeQualityOrQualityChangesName && base.currentItem.intent_category == Cura.MachineManager.activeIntentCategory
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: profileName.bottom anchors.top: profileName.bottom
@ -567,7 +587,6 @@ Item
} }
} }
TabView TabView
{ {
anchors.left: parent.left anchors.left: parent.left

View File

@ -118,10 +118,12 @@ def test_duplicateQualityChanges(quality_mocked_application):
quality_group.getAllNodes = MagicMock(return_value = mocked_quality) quality_group.getAllNodes = MagicMock(return_value = mocked_quality)
quality_changes_group = MagicMock() quality_changes_group = MagicMock()
mocked_quality_changes = MagicMock() mocked_quality_changes = MagicMock()
quality_changes_group.getAllNodes = MagicMock(return_value=[mocked_quality_changes]) quality_changes_group.getAllNodes = MagicMock(return_value = [mocked_quality_changes])
mocked_quality_changes.duplicate = MagicMock(return_value = mocked_quality_changes) mocked_quality_changes.duplicate = MagicMock(return_value = mocked_quality_changes)
manager._container_registry.addContainer = MagicMock() # Side effect we want to check. manager._container_registry.addContainer = MagicMock() # Side effect we want to check.
manager.duplicateQualityChanges("zomg", {"quality_group": quality_group, "quality_changes_group": quality_changes_group}) manager.duplicateQualityChanges("zomg", {"intent_category": "default",
"quality_group": quality_group,
"quality_changes_group": quality_changes_group})
assert manager._container_registry.addContainer.called_once_with(mocked_quality_changes) assert manager._container_registry.addContainer.called_once_with(mocked_quality_changes)