Merge branch 'master' into CURA-6793_performance

Conflicts:
	cura/Machines/MaterialManager.py -> File was deleted in Master but I changed things for the lazy loading.
	cura/Machines/Models/BaseMaterialsModel.py -> I clarified documentation on a line above a place where a timer was added in between.

Contributes to issue CURA-6793.
This commit is contained in:
Ghostkeeper 2019-10-23 09:58:08 +02:00
commit 94eb76a844
No known key found for this signature in database
GPG key ID: 59A4C0959592C05C
318 changed files with 881 additions and 2183 deletions

View file

@ -1,9 +1,9 @@
# Copyright (c) 2019 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from typing import Optional, Dict, Set
from typing import Dict, Set
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtProperty
from UM.Qt.ListModel import ListModel
@ -38,14 +38,25 @@ class BaseMaterialsModel(ListModel):
self._extruder_stack = None
self._enabled = True
# CURA-6904
# Updating the material model requires information from material nodes and containers. We use a timer here to
# make sure that an update function call will not be directly invoked by an event. Because the triggered event
# can be caused in the middle of a XMLMaterial loading, and the material container we try to find may not be
# in the system yet. This will cause an infinite recursion of (1) trying to load a material, (2) trying to
# update the material model, (3) cannot find the material container, load it, (4) repeat #1.
self._update_timer = QTimer()
self._update_timer.setInterval(100)
self._update_timer.setSingleShot(True)
self._update_timer.timeout.connect(self._update)
# Update the stack and the model data when the machine changes
self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack)
self._updateExtruderStack()
# Update this model when switching machines or tabs, when adding materials or changing their metadata.
self._machine_manager.activeStackChanged.connect(self._update)
self._machine_manager.activeStackChanged.connect(self._onChanged)
ContainerTree.getInstance().materialsChanged.connect(self._materialsListChanged)
self._application.getMaterialManagementModel().favoritesChanged.connect(self._update)
self._application.getMaterialManagementModel().favoritesChanged.connect(self._onChanged)
self.addRoleName(Qt.UserRole + 1, "root_material_id")
self.addRoleName(Qt.UserRole + 2, "id")
@ -64,14 +75,17 @@ class BaseMaterialsModel(ListModel):
self.addRoleName(Qt.UserRole + 15, "container_node")
self.addRoleName(Qt.UserRole + 16, "is_favorite")
def _onChanged(self) -> None:
self._update_timer.start()
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.approximateMaterialDiameterChanged.disconnect(self._update)
self._extruder_stack.pyqtContainersChanged.disconnect(self._onChanged)
self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._onChanged)
try:
self._extruder_stack = global_stack.extruderList[self._extruder_position]
@ -79,10 +93,10 @@ class BaseMaterialsModel(ListModel):
self._extruder_stack = None
if self._extruder_stack is not None:
self._extruder_stack.pyqtContainersChanged.connect(self._update)
self._extruder_stack.approximateMaterialDiameterChanged.connect(self._update)
self._extruder_stack.pyqtContainersChanged.connect(self._onChanged)
self._extruder_stack.approximateMaterialDiameterChanged.connect(self._onChanged)
# Force update the model when the extruder stack changes
self._update()
self._onChanged()
def setExtruderPosition(self, position: int):
if self._extruder_stack is None or self._extruder_position != position:
@ -99,7 +113,7 @@ class BaseMaterialsModel(ListModel):
self._enabled = enabled
if self._enabled:
# ensure the data is there again.
self._update()
self._onChanged()
self.enabledChanged.emit()
@pyqtProperty(bool, fset = setEnabled, notify = enabledChanged)
@ -119,12 +133,12 @@ class BaseMaterialsModel(ListModel):
return
if material.variant.machine.container_id != global_stack.definition.getId():
return
self._update()
self._onChanged()
## Triggered when the list of favorite materials is changed.
def _favoritesChanged(self, material_base_file: str) -> None:
if material_base_file in self._available_materials:
self._update()
self._onChanged()
## This is an abstract method that needs to be implemented by the specific
# models themselves.

View file

@ -9,14 +9,14 @@ class FavoriteMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
cura.CuraApplication.CuraApplication.getInstance().getPreferences().preferenceChanged.connect(self._onFavoritesChanged)
self._update()
self._onChanged()
## Triggered when any preference changes, but only handles it when the list
# of favourites is changed.
def _onFavoritesChanged(self, preference_key: str) -> None:
if preference_key != "cura/favorite_materials":
return
self._update()
self._onChanged()
def _update(self):
if not self._canUpdate():

View file

@ -7,7 +7,7 @@ class GenericMaterialsModel(BaseMaterialsModel):
def __init__(self, parent = None):
super().__init__(parent)
self._update()
self._onChanged()
def _update(self):
if not self._canUpdate():

View file

@ -3,7 +3,7 @@
from PyQt5.QtCore import Qt
import collections
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Optional, Dict
from cura.Machines.Models.IntentModel import IntentModel
from cura.Settings.IntentManager import IntentManager
@ -25,16 +25,26 @@ class IntentCategoryModel(ListModel):
IntentCategoryRole = Qt.UserRole + 2
WeightRole = Qt.UserRole + 3
QualitiesRole = Qt.UserRole + 4
#Translations to user-visible string. Ordered by weight.
#TODO: Create a solution for this name and weight to be used dynamically.
name_translation = collections.OrderedDict() #type: "collections.OrderedDict[str,str]"
name_translation["default"] = catalog.i18nc("@label", "Default")
name_translation["engineering"] = catalog.i18nc("@label", "Engineering")
name_translation["smooth"] = catalog.i18nc("@label", "Smooth")
DescriptionRole = Qt.UserRole + 5
modelUpdated = pyqtSignal()
# Translations to user-visible string. Ordered by weight.
# TODO: Create a solution for this name and weight to be used dynamically.
_translations = collections.OrderedDict() # type: "collections.OrderedDict[str,Dict[str,Optional[str]]]"
_translations["default"] = {
"name": catalog.i18nc("@label", "Default")
}
_translations["engineering"] = {
"name": catalog.i18nc("@label", "Engineering"),
"description": catalog.i18nc("@text", "Suitable for engineering work")
}
_translations["smooth"] = {
"name": catalog.i18nc("@label", "Smooth"),
"description": catalog.i18nc("@text", "Optimized for a smooth surfaces")
}
## Creates a new model for a certain intent category.
# \param The category to list the intent profiles for.
def __init__(self, intent_category: str) -> None:
@ -45,6 +55,7 @@ class IntentCategoryModel(ListModel):
self.addRoleName(self.IntentCategoryRole, "intent_category")
self.addRoleName(self.WeightRole, "weight")
self.addRoleName(self.QualitiesRole, "qualities")
self.addRoleName(self.DescriptionRole, "description")
application = cura.CuraApplication.CuraApplication.getInstance()
@ -73,10 +84,18 @@ class IntentCategoryModel(ListModel):
qualities = IntentModel()
qualities.setIntentCategory(category)
result.append({
"name": self.name_translation.get(category, catalog.i18nc("@label", "Unknown")),
"name": IntentCategoryModel.translation(category, "name", catalog.i18nc("@label", "Unknown")),
"description": IntentCategoryModel.translation(category, "description", None),
"intent_category": category,
"weight": list(self.name_translation.keys()).index(category),
"weight": list(self._translations.keys()).index(category),
"qualities": qualities
})
result.sort(key = lambda k: k["weight"])
self.setItems(result)
## Get a display value for a category. See IntenCategoryModel._translations
## for categories and keys
@staticmethod
def translation(category: str, key: str, default: Optional[str] = None):
display_strings = IntentCategoryModel._translations.get(category, {})
return display_strings.get(key, default)

View file

@ -345,11 +345,13 @@ class QualityManagementModel(ListModel):
# Create quality_changes group items
quality_changes_item_list = []
for quality_changes_group in quality_changes_group_list:
# CURA-6913 Note that custom qualities can be based on "not supported", so the quality group can be None.
quality_group = quality_group_dict.get(quality_changes_group.quality_type)
quality_type = quality_changes_group.quality_type
item = {"name": quality_changes_group.name,
"is_read_only": False,
"quality_group": quality_group,
"quality_type": quality_group.quality_type,
"quality_type": quality_type,
"quality_changes_group": quality_changes_group,
"intent_category": quality_changes_group.intent_category,
"section_name": catalog.i18nc("@label", "Custom profiles"),