mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-06 21:44:01 -06:00
Merge branch 'CURA-6016_Improve_UI_Speed' into 4.0
This commit is contained in:
commit
1b2ef91c13
13 changed files with 80 additions and 51 deletions
|
@ -83,7 +83,14 @@ class BuildVolume(SceneNode):
|
|||
" with printed models."), title = catalog.i18nc("@info:title", "Build Volume"))
|
||||
|
||||
self._global_container_stack = None
|
||||
|
||||
self._stack_change_timer = QTimer()
|
||||
self._stack_change_timer.setInterval(100)
|
||||
self._stack_change_timer.setSingleShot(True)
|
||||
self._stack_change_timer.timeout.connect(self._onStackChangeTimerFinished)
|
||||
|
||||
self._application.globalContainerStackChanged.connect(self._onStackChanged)
|
||||
|
||||
self._onStackChanged()
|
||||
|
||||
self._engine_ready = False
|
||||
|
@ -105,6 +112,8 @@ class BuildVolume(SceneNode):
|
|||
self._setting_change_timer.setSingleShot(True)
|
||||
self._setting_change_timer.timeout.connect(self._onSettingChangeTimerFinished)
|
||||
|
||||
|
||||
|
||||
# Must be after setting _build_volume_message, apparently that is used in getMachineManager.
|
||||
# activeQualityChanged is always emitted after setActiveVariant, setActiveMaterial and setActiveQuality.
|
||||
# Therefore this works.
|
||||
|
@ -526,8 +535,11 @@ class BuildVolume(SceneNode):
|
|||
if extra_z != self._extra_z_clearance:
|
||||
self._extra_z_clearance = extra_z
|
||||
|
||||
## Update the build volume visualization
|
||||
def _onStackChanged(self):
|
||||
self._stack_change_timer.start()
|
||||
|
||||
## Update the build volume visualization
|
||||
def _onStackChangeTimerFinished(self):
|
||||
if self._global_container_stack:
|
||||
self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
|
||||
extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
|
||||
|
|
|
@ -64,21 +64,21 @@ class MachineErrorChecker(QObject):
|
|||
|
||||
def _onMachineChanged(self) -> None:
|
||||
if self._global_stack:
|
||||
self._global_stack.propertyChanged.disconnect(self.startErrorCheck)
|
||||
self._global_stack.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
|
||||
self._global_stack.containersChanged.disconnect(self.startErrorCheck)
|
||||
|
||||
for extruder in self._global_stack.extruders.values():
|
||||
extruder.propertyChanged.disconnect(self.startErrorCheck)
|
||||
extruder.propertyChanged.disconnect(self.startErrorCheckPropertyChanged)
|
||||
extruder.containersChanged.disconnect(self.startErrorCheck)
|
||||
|
||||
self._global_stack = self._machine_manager.activeMachine
|
||||
|
||||
if self._global_stack:
|
||||
self._global_stack.propertyChanged.connect(self.startErrorCheck)
|
||||
self._global_stack.propertyChanged.connect(self.startErrorCheckPropertyChanged)
|
||||
self._global_stack.containersChanged.connect(self.startErrorCheck)
|
||||
|
||||
for extruder in self._global_stack.extruders.values():
|
||||
extruder.propertyChanged.connect(self.startErrorCheck)
|
||||
extruder.propertyChanged.connect(self.startErrorCheckPropertyChanged)
|
||||
extruder.containersChanged.connect(self.startErrorCheck)
|
||||
|
||||
hasErrorUpdated = pyqtSignal()
|
||||
|
@ -93,6 +93,13 @@ class MachineErrorChecker(QObject):
|
|||
def needToWaitForResult(self) -> bool:
|
||||
return self._need_to_check or self._check_in_progress
|
||||
|
||||
# Start the error check for property changed
|
||||
# this is seperate from the startErrorCheck because it ignores a number property types
|
||||
def startErrorCheckPropertyChanged(self, key, property_name):
|
||||
if property_name != "value":
|
||||
return
|
||||
self.startErrorCheck()
|
||||
|
||||
# Starts the error check timer to schedule a new error check.
|
||||
def startErrorCheck(self, *args) -> None:
|
||||
if not self._check_in_progress:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
from typing import Optional, Dict, Set
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty
|
||||
from UM.Qt.ListModel import ListModel
|
||||
|
@ -9,6 +10,9 @@ from UM.Qt.ListModel import ListModel
|
|||
# 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
|
||||
from cura.Machines.MaterialNode import MaterialNode
|
||||
|
||||
|
||||
class BaseMaterialsModel(ListModel):
|
||||
|
||||
extruderPositionChanged = pyqtSignal()
|
||||
|
@ -54,8 +58,8 @@ class BaseMaterialsModel(ListModel):
|
|||
self._extruder_position = 0
|
||||
self._extruder_stack = None
|
||||
|
||||
self._available_materials = None
|
||||
self._favorite_ids = None
|
||||
self._available_materials = None # type: Optional[Dict[str, MaterialNode]]
|
||||
self._favorite_ids = set() # type: Set[str]
|
||||
|
||||
def _updateExtruderStack(self):
|
||||
global_stack = self._machine_manager.activeMachine
|
||||
|
@ -102,8 +106,10 @@ class BaseMaterialsModel(ListModel):
|
|||
return False
|
||||
|
||||
extruder_stack = global_stack.extruders[extruder_position]
|
||||
|
||||
self._available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
|
||||
available_materials = self._material_manager.getAvailableMaterialsForMachineExtruder(global_stack, extruder_stack)
|
||||
if available_materials == self._available_materials:
|
||||
return False
|
||||
self._available_materials = available_materials
|
||||
if self._available_materials is None:
|
||||
return False
|
||||
|
||||
|
|
|
@ -4,17 +4,14 @@
|
|||
from UM.Logger import Logger
|
||||
from cura.Machines.Models.BaseMaterialsModel import BaseMaterialsModel
|
||||
|
||||
class FavoriteMaterialsModel(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
|
||||
|
|
|
@ -11,10 +11,7 @@ class GenericMaterialsModel(BaseMaterialsModel):
|
|||
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
|
||||
|
|
|
@ -28,12 +28,8 @@ class MaterialBrandsModel(BaseMaterialsModel):
|
|||
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()
|
||||
|
||||
|
|
|
@ -83,8 +83,9 @@ class ExtruderManager(QObject):
|
|||
# \param index The index of the new active extruder.
|
||||
@pyqtSlot(int)
|
||||
def setActiveExtruderIndex(self, index: int) -> None:
|
||||
self._active_extruder_index = index
|
||||
self.activeExtruderChanged.emit()
|
||||
if self._active_extruder_index != index:
|
||||
self._active_extruder_index = index
|
||||
self.activeExtruderChanged.emit()
|
||||
|
||||
@pyqtProperty(int, notify = activeExtruderChanged)
|
||||
def activeExtruderIndex(self) -> int:
|
||||
|
@ -344,6 +345,7 @@ class ExtruderManager(QObject):
|
|||
if extruders_changed:
|
||||
self.extrudersChanged.emit(global_stack_id)
|
||||
self.setActiveExtruderIndex(0)
|
||||
self.activeExtruderChanged.emit()
|
||||
|
||||
# After 3.4, all single-extrusion machines have their own extruder definition files instead of reusing
|
||||
# "fdmextruder". We need to check a machine here so its extruder definition is correct according to this.
|
||||
|
|
|
@ -224,6 +224,6 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel):
|
|||
"definition": ""
|
||||
}
|
||||
items.append(item)
|
||||
|
||||
self.setItems(items)
|
||||
self.modelChanged.emit()
|
||||
if self._items != items:
|
||||
self.setItems(items)
|
||||
self.modelChanged.emit()
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
from collections import defaultdict
|
||||
import threading
|
||||
from typing import Any, Dict, Optional, Set, TYPE_CHECKING
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSlot
|
||||
from typing import Any, Dict, Optional, Set, TYPE_CHECKING, List
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSlot, pyqtSignal
|
||||
|
||||
from UM.Decorators import override
|
||||
from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase
|
||||
|
@ -42,13 +42,23 @@ class GlobalStack(CuraContainerStack):
|
|||
# Per thread we have our own resolving_settings, or strange things sometimes occur.
|
||||
self._resolving_settings = defaultdict(set) #type: Dict[str, Set[str]] # keys are thread names
|
||||
|
||||
extrudersChanged = pyqtSignal()
|
||||
|
||||
## Get the list of extruders of this stack.
|
||||
#
|
||||
# \return The extruders registered with this stack.
|
||||
@pyqtProperty("QVariantMap")
|
||||
@pyqtProperty("QVariantMap", notify = extrudersChanged)
|
||||
def extruders(self) -> Dict[str, "ExtruderStack"]:
|
||||
return self._extruders
|
||||
|
||||
@pyqtProperty("QVariantList", notify = extrudersChanged)
|
||||
def extruderList(self) -> List["ExtruderStack"]:
|
||||
result_tuple_list = sorted(list(self.extruders.items()), key=lambda x: int(x[0]))
|
||||
result_list = [item[1] for item in result_tuple_list]
|
||||
|
||||
machine_extruder_count = self.getProperty("machine_extruder_count", "value")
|
||||
return result_list[:machine_extruder_count]
|
||||
|
||||
@classmethod
|
||||
def getLoadingPriority(cls) -> int:
|
||||
return 2
|
||||
|
|
|
@ -203,7 +203,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
|
||||
@pyqtSlot()
|
||||
def stopSlicing(self) -> None:
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
if self._slicing: # We were already slicing. Stop the old job.
|
||||
self._terminate()
|
||||
self._createSocket()
|
||||
|
@ -322,7 +322,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._start_slice_job = None
|
||||
|
||||
if job.isCancelled() or job.getError() or job.getResult() == StartJobResult.Error:
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
return
|
||||
|
||||
|
@ -331,10 +331,10 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._error_message = Message(catalog.i18nc("@info:status",
|
||||
"Unable to slice with the current material as it is incompatible with the selected machine or configuration."), title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
else:
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
return
|
||||
|
||||
if job.getResult() == StartJobResult.SettingError:
|
||||
|
@ -362,10 +362,10 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. The following settings have errors: {0}").format(", ".join(error_labels)),
|
||||
title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
else:
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
return
|
||||
|
||||
elif job.getResult() == StartJobResult.ObjectSettingError:
|
||||
|
@ -386,7 +386,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice due to some per-model settings. The following settings have errors on one or more models: {error_labels}").format(error_labels = ", ".join(errors.values())),
|
||||
title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
return
|
||||
|
||||
|
@ -395,16 +395,16 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because the prime tower or prime position(s) are invalid."),
|
||||
title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
else:
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
|
||||
if job.getResult() == StartJobResult.ObjectsWithDisabledExtruder:
|
||||
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice because there are objects associated with disabled Extruder %s." % job.getMessage()),
|
||||
title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
return
|
||||
|
||||
|
@ -413,10 +413,10 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._error_message = Message(catalog.i18nc("@info:status", "Nothing to slice because none of the models fit the build volume. Please scale or rotate models to fit."),
|
||||
title = catalog.i18nc("@info:title", "Unable to slice"))
|
||||
self._error_message.show()
|
||||
self.backendStateChange.emit(BackendState.Error)
|
||||
self.setState(BackendState.Error)
|
||||
self.backendError.emit(job)
|
||||
else:
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
self._invokeSlice()
|
||||
return
|
||||
|
||||
|
@ -424,7 +424,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._socket.sendMessage(job.getSliceMessage())
|
||||
|
||||
# Notify the user that it's now up to the backend to do it's job
|
||||
self.backendStateChange.emit(BackendState.Processing)
|
||||
self.setState(BackendState.Processing)
|
||||
|
||||
if self._slice_start_time:
|
||||
Logger.log("d", "Sending slice message took %s seconds", time() - self._slice_start_time )
|
||||
|
@ -442,7 +442,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
|
||||
if node.callDecoration("isBlockSlicing"):
|
||||
enable_timer = False
|
||||
self.backendStateChange.emit(BackendState.Disabled)
|
||||
self.setState(BackendState.Disabled)
|
||||
self._is_disabled = True
|
||||
gcode_list = node.callDecoration("getGCodeList")
|
||||
if gcode_list is not None:
|
||||
|
@ -451,7 +451,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
if self._use_timer == enable_timer:
|
||||
return self._use_timer
|
||||
if enable_timer:
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
self.enableTimer()
|
||||
return True
|
||||
else:
|
||||
|
@ -518,7 +518,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._build_plates_to_be_sliced.append(build_plate_number)
|
||||
self.printDurationMessage.emit(source_build_plate_number, {}, [])
|
||||
self.processingProgress.emit(0.0)
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
# if not self._use_timer:
|
||||
# With manually having to slice, we want to clear the old invalid layer data.
|
||||
self._clearLayerData(build_plate_changed)
|
||||
|
@ -567,7 +567,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self.stopSlicing()
|
||||
self.markSliceAll()
|
||||
self.processingProgress.emit(0.0)
|
||||
self.backendStateChange.emit(BackendState.NotStarted)
|
||||
self.setState(BackendState.NotStarted)
|
||||
if not self._use_timer:
|
||||
# With manually having to slice, we want to clear the old invalid layer data.
|
||||
self._clearLayerData()
|
||||
|
@ -613,7 +613,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
# \param message The protobuf message containing the slicing progress.
|
||||
def _onProgressMessage(self, message: Arcus.PythonMessage) -> None:
|
||||
self.processingProgress.emit(message.amount)
|
||||
self.backendStateChange.emit(BackendState.Processing)
|
||||
self.setState(BackendState.Processing)
|
||||
|
||||
def _invokeSlice(self) -> None:
|
||||
if self._use_timer:
|
||||
|
@ -632,7 +632,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
#
|
||||
# \param message The protobuf message signalling that slicing is finished.
|
||||
def _onSlicingFinishedMessage(self, message: Arcus.PythonMessage) -> None:
|
||||
self.backendStateChange.emit(BackendState.Done)
|
||||
self.setState(BackendState.Done)
|
||||
self.processingProgress.emit(1.0)
|
||||
|
||||
gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate] #type: ignore #Because we generate this attribute dynamically.
|
||||
|
|
|
@ -323,7 +323,7 @@ class StartSliceJob(Job):
|
|||
value = stack.getProperty(key, "value")
|
||||
result[key] = value
|
||||
Job.yieldThread()
|
||||
|
||||
|
||||
result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings.
|
||||
result["print_temperature"] = result["material_print_temperature"]
|
||||
result["time"] = time.strftime("%H:%M:%S") #Some extra settings.
|
||||
|
|
|
@ -11,6 +11,7 @@ import Cura 1.0 as Cura
|
|||
|
||||
UM.Dialog
|
||||
{
|
||||
id: base
|
||||
title: catalog.i18nc("@title:window", "Save Project")
|
||||
|
||||
minimumWidth: 500 * screenScaleFactor
|
||||
|
@ -49,7 +50,7 @@ UM.Dialog
|
|||
UM.SettingDefinitionsModel
|
||||
{
|
||||
id: definitionsModel
|
||||
containerId: Cura.MachineManager.activeDefinitionId
|
||||
containerId: base.visible ? Cura.MachineManager.activeDefinitionId: ""
|
||||
showAll: true
|
||||
exclude: ["command_line_settings"]
|
||||
showAncestors: true
|
||||
|
|
|
@ -16,10 +16,11 @@ Menu
|
|||
|
||||
Instantiator
|
||||
{
|
||||
model: Cura.ExtrudersModel { simpleNames: true }
|
||||
model: Cura.MachineManager.activeMachine.extruderList
|
||||
|
||||
Menu
|
||||
{
|
||||
title: model.name
|
||||
title: modelData.name
|
||||
|
||||
NozzleMenu { title: Cura.MachineManager.activeDefinitionVariantsName; visible: Cura.MachineManager.hasVariants; extruderIndex: index }
|
||||
MaterialMenu { title: catalog.i18nc("@title:menu", "&Material"); visible: Cura.MachineManager.hasMaterials; extruderIndex: index }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue