mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-04 04:23:58 -06:00
Fix material model update and signal recursion
CURA-6904
This commit is contained in:
parent
cd0dbb3902
commit
5602c71ec7
3 changed files with 29 additions and 15 deletions
|
@ -1,9 +1,9 @@
|
||||||
# Copyright (c) 2019 Ultimaker B.V.
|
# Copyright (c) 2019 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# 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
|
from UM.Qt.ListModel import ListModel
|
||||||
|
|
||||||
|
@ -38,14 +38,25 @@ class BaseMaterialsModel(ListModel):
|
||||||
self._extruder_stack = None
|
self._extruder_stack = None
|
||||||
self._enabled = True
|
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
|
# Update the stack and the model data when the machine changes
|
||||||
self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack)
|
self._machine_manager.globalContainerChanged.connect(self._updateExtruderStack)
|
||||||
self._updateExtruderStack()
|
self._updateExtruderStack()
|
||||||
|
|
||||||
# Update this model when switching machines, when adding materials or changing their metadata.
|
# Update this model when switching machines, 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)
|
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 + 1, "root_material_id")
|
||||||
self.addRoleName(Qt.UserRole + 2, "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 + 15, "container_node")
|
||||||
self.addRoleName(Qt.UserRole + 16, "is_favorite")
|
self.addRoleName(Qt.UserRole + 16, "is_favorite")
|
||||||
|
|
||||||
|
def _onChanged(self) -> None:
|
||||||
|
self._update_timer.start()
|
||||||
|
|
||||||
def _updateExtruderStack(self):
|
def _updateExtruderStack(self):
|
||||||
global_stack = self._machine_manager.activeMachine
|
global_stack = self._machine_manager.activeMachine
|
||||||
if global_stack is None:
|
if global_stack is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._extruder_stack is not None:
|
if self._extruder_stack is not None:
|
||||||
self._extruder_stack.pyqtContainersChanged.disconnect(self._update)
|
self._extruder_stack.pyqtContainersChanged.disconnect(self._onChanged)
|
||||||
self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._update)
|
self._extruder_stack.approximateMaterialDiameterChanged.disconnect(self._onChanged)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._extruder_stack = global_stack.extruderList[self._extruder_position]
|
self._extruder_stack = global_stack.extruderList[self._extruder_position]
|
||||||
|
@ -79,10 +93,10 @@ class BaseMaterialsModel(ListModel):
|
||||||
self._extruder_stack = None
|
self._extruder_stack = None
|
||||||
|
|
||||||
if self._extruder_stack is not None:
|
if self._extruder_stack is not None:
|
||||||
self._extruder_stack.pyqtContainersChanged.connect(self._update)
|
self._extruder_stack.pyqtContainersChanged.connect(self._onChanged)
|
||||||
self._extruder_stack.approximateMaterialDiameterChanged.connect(self._update)
|
self._extruder_stack.approximateMaterialDiameterChanged.connect(self._onChanged)
|
||||||
# Force update the model when the extruder stack changes
|
# Force update the model when the extruder stack changes
|
||||||
self._update()
|
self._onChanged()
|
||||||
|
|
||||||
def setExtruderPosition(self, position: int):
|
def setExtruderPosition(self, position: int):
|
||||||
if self._extruder_stack is None or self._extruder_position != position:
|
if self._extruder_stack is None or self._extruder_position != position:
|
||||||
|
@ -99,7 +113,7 @@ class BaseMaterialsModel(ListModel):
|
||||||
self._enabled = enabled
|
self._enabled = enabled
|
||||||
if self._enabled:
|
if self._enabled:
|
||||||
# ensure the data is there again.
|
# ensure the data is there again.
|
||||||
self._update()
|
self._onChanged()
|
||||||
self.enabledChanged.emit()
|
self.enabledChanged.emit()
|
||||||
|
|
||||||
@pyqtProperty(bool, fset = setEnabled, notify = enabledChanged)
|
@pyqtProperty(bool, fset = setEnabled, notify = enabledChanged)
|
||||||
|
@ -119,12 +133,12 @@ class BaseMaterialsModel(ListModel):
|
||||||
return
|
return
|
||||||
if material.variant.machine.container_id != global_stack.definition.getId():
|
if material.variant.machine.container_id != global_stack.definition.getId():
|
||||||
return
|
return
|
||||||
self._update()
|
self._onChanged()
|
||||||
|
|
||||||
## Triggered when the list of favorite materials is changed.
|
## Triggered when the list of favorite materials is changed.
|
||||||
def _favoritesChanged(self, material_base_file: str) -> None:
|
def _favoritesChanged(self, material_base_file: str) -> None:
|
||||||
if material_base_file in self._available_materials:
|
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
|
## This is an abstract method that needs to be implemented by the specific
|
||||||
# models themselves.
|
# models themselves.
|
||||||
|
|
|
@ -9,14 +9,14 @@ class FavoriteMaterialsModel(BaseMaterialsModel):
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
cura.CuraApplication.CuraApplication.getInstance().getPreferences().preferenceChanged.connect(self._onFavoritesChanged)
|
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
|
## Triggered when any preference changes, but only handles it when the list
|
||||||
# of favourites is changed.
|
# of favourites is changed.
|
||||||
def _onFavoritesChanged(self, preference_key: str) -> None:
|
def _onFavoritesChanged(self, preference_key: str) -> None:
|
||||||
if preference_key != "cura/favorite_materials":
|
if preference_key != "cura/favorite_materials":
|
||||||
return
|
return
|
||||||
self._update()
|
self._onChanged()
|
||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
if not self._canUpdate():
|
if not self._canUpdate():
|
||||||
|
|
|
@ -7,7 +7,7 @@ class GenericMaterialsModel(BaseMaterialsModel):
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._update()
|
self._onChanged()
|
||||||
|
|
||||||
def _update(self):
|
def _update(self):
|
||||||
if not self._canUpdate():
|
if not self._canUpdate():
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue