resolve merge conflict

This commit is contained in:
Mark 2018-04-17 10:39:35 +02:00
commit f61efb8e20
7 changed files with 61 additions and 46 deletions

View file

@ -501,11 +501,6 @@ class CuraApplication(QtApplication):
def getStaticVersion(cls): def getStaticVersion(cls):
return CuraVersion return CuraVersion
## Handle removing the unneeded plugins
# \sa PluginRegistry
def _removePlugins(self):
self._plugin_registry.removePlugins()
## Handle loading of all plugin types (and the backend explicitly) ## Handle loading of all plugin types (and the backend explicitly)
# \sa PluginRegistry # \sa PluginRegistry
def _loadPlugins(self): def _loadPlugins(self):

34
cura/Utils/Threading.py Normal file
View file

@ -0,0 +1,34 @@
import threading
from cura.CuraApplication import CuraApplication
#
# HACK:
#
# In project loading, when override the existing machine is selected, the stacks and containers that are correctly
# active in the system will be overridden at runtime. Because the project loading is done in a different thread than
# the Qt thread, something else can kick in the middle of the process. One of them is the rendering. It will access
# the current stacks and container, which have not completely been updated yet, so Cura will crash in this case.
#
# This "@call_on_qt_thread" decorator makes sure that a function will always be called on the Qt thread (blocking).
# It is applied to the read() function of project loading so it can be guaranteed that only after the project loading
# process is completely done, everything else that needs to occupy the QT thread will be executed.
#
class InterCallObject:
def __init__(self):
self.finish_event = threading.Event()
self.result = None
def call_on_qt_thread(func):
def _call_on_qt_thread_wrapper(*args, **kwargs):
def _handle_call(ico, *args, **kwargs):
ico.result = func(*args, **kwargs)
ico.finish_event.set()
inter_call_object = InterCallObject()
new_args = tuple([inter_call_object] + list(args)[:])
CuraApplication.getInstance().callLater(_handle_call, *new_args, **kwargs)
inter_call_object.finish_event.wait()
return inter_call_object.result
return _call_on_qt_thread_wrapper

View file

@ -7,6 +7,7 @@ import os
import threading import threading
from typing import List, Tuple from typing import List, Tuple
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from UM.Workspace.WorkspaceReader import WorkspaceReader from UM.Workspace.WorkspaceReader import WorkspaceReader
@ -28,43 +29,13 @@ from cura.Settings.ExtruderStack import ExtruderStack
from cura.Settings.GlobalStack import GlobalStack from cura.Settings.GlobalStack import GlobalStack
from cura.Settings.CuraContainerStack import _ContainerIndexes from cura.Settings.CuraContainerStack import _ContainerIndexes
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from cura.Utils.Threading import call_on_qt_thread
from .WorkspaceDialog import WorkspaceDialog from .WorkspaceDialog import WorkspaceDialog
i18n_catalog = i18nCatalog("cura") i18n_catalog = i18nCatalog("cura")
#
# HACK:
#
# In project loading, when override the existing machine is selected, the stacks and containers that are correctly
# active in the system will be overridden at runtime. Because the project loading is done in a different thread than
# the Qt thread, something else can kick in the middle of the process. One of them is the rendering. It will access
# the current stacks and container, which have not completely been updated yet, so Cura will crash in this case.
#
# This "@call_on_qt_thread" decorator makes sure that a function will always be called on the Qt thread (blocking).
# It is applied to the read() function of project loading so it can be guaranteed that only after the project loading
# process is completely done, everything else that needs to occupy the QT thread will be executed.
#
class InterCallObject:
def __init__(self):
self.finish_event = threading.Event()
self.result = None
def call_on_qt_thread(func):
def _call_on_qt_thread_wrapper(*args, **kwargs):
def _handle_call(ico, *args, **kwargs):
ico.result = func(*args, **kwargs)
ico.finish_event.set()
inter_call_object = InterCallObject()
new_args = tuple([inter_call_object] + list(args)[:])
CuraApplication.getInstance().callLater(_handle_call, *new_args, **kwargs)
inter_call_object.finish_event.wait()
return inter_call_object.result
return _call_on_qt_thread_wrapper
class ContainerInfo: class ContainerInfo:
def __init__(self, file_name: str, serialized: str, parser: ConfigParser): def __init__(self, file_name: str, serialized: str, parser: ConfigParser):
self.file_name = file_name self.file_name = file_name

View file

@ -6,16 +6,18 @@ from io import StringIO
import zipfile import zipfile
from UM.Application import Application from UM.Application import Application
from UM.Logger import Logger
from UM.Preferences import Preferences from UM.Preferences import Preferences
from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.ContainerRegistry import ContainerRegistry
from UM.Workspace.WorkspaceWriter import WorkspaceWriter from UM.Workspace.WorkspaceWriter import WorkspaceWriter
from cura.Utils.Threading import call_on_qt_thread
class ThreeMFWorkspaceWriter(WorkspaceWriter): class ThreeMFWorkspaceWriter(WorkspaceWriter):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@call_on_qt_thread
def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode): def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode):
application = Application.getInstance() application = Application.getInstance()
machine_manager = application.getMachineManager() machine_manager = application.getMachineManager()

View file

@ -121,7 +121,7 @@ class CuraEngineBackend(QObject, Backend):
self._slice_start_time = None self._slice_start_time = None
self._is_disabled = False self._is_disabled = False
Preferences.getInstance().addPreference("general/auto_slice", True) Preferences.getInstance().addPreference("general/auto_slice", False)
self._use_timer = False self._use_timer = False
# When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.

View file

@ -49,6 +49,13 @@ class ModelChecker(QObject, Extension):
warning_size_xy = 150 #The horizontal size of a model that would be too large when dealing with shrinking materials. warning_size_xy = 150 #The horizontal size of a model that would be too large when dealing with shrinking materials.
warning_size_z = 100 #The vertical size of a model that would be too large when dealing with shrinking materials. warning_size_z = 100 #The vertical size of a model that would be too large when dealing with shrinking materials.
# This function can be triggered in the middle of a machine change, so do not proceed if the machine change
# has not done yet.
global_container_stack = Application.getInstance().getGlobalContainerStack()
if global_container_stack is None:
Application.getInstance().callLater(lambda: self.onChanged.emit())
return False
material_shrinkage = self._getMaterialShrinkage() material_shrinkage = self._getMaterialShrinkage()
warning_nodes = [] warning_nodes = []
@ -56,6 +63,13 @@ class ModelChecker(QObject, Extension):
# Check node material shrinkage and bounding box size # Check node material shrinkage and bounding box size
for node in self.sliceableNodes(): for node in self.sliceableNodes():
node_extruder_position = node.callDecoration("getActiveExtruderPosition") node_extruder_position = node.callDecoration("getActiveExtruderPosition")
# This function can be triggered in the middle of a machine change, so do not proceed if the machine change
# has not done yet.
if str(node_extruder_position) not in global_container_stack.extruders:
Application.getInstance().callLater(lambda: self.onChanged.emit())
return False
if material_shrinkage[node_extruder_position] > shrinkage_threshold: if material_shrinkage[node_extruder_position] > shrinkage_threshold:
bbox = node.getBoundingBox() bbox = node.getBoundingBox()
if bbox.width >= warning_size_xy or bbox.depth >= warning_size_xy or bbox.height >= warning_size_z: if bbox.width >= warning_size_xy or bbox.depth >= warning_size_xy or bbox.height >= warning_size_z:
@ -63,11 +77,11 @@ class ModelChecker(QObject, Extension):
self._caution_message.setText(catalog.i18nc( self._caution_message.setText(catalog.i18nc(
"@info:status", "@info:status",
"Some models may not be printed optimally due to object size and chosen material for models: {model_names}.\n" "<p>One or more 3D models may not print optimally due to the model size and material configuration:</p>\n"
"Tips that may be useful to improve the print quality:\n" "<p>{model_names}</p>\n"
"1) Use rounded corners.\n" "<p>Find out how to ensure the best possible print quality and reliability.</p>\n"
"2) Turn the fan off (only if there are no tiny details on the model).\n" "<p><a href=\"https://ultimaker.com/3D-model-assistant\">View print quality guide</a></p>"
"3) Use a different material.").format(model_names = ", ".join([n.getName() for n in warning_nodes]))) ).format(model_names = ", ".join([n.getName() for n in warning_nodes])))
return len(warning_nodes) > 0 return len(warning_nodes) > 0
@ -92,9 +106,8 @@ class ModelChecker(QObject, Extension):
Logger.log("d", "Model checker view created.") Logger.log("d", "Model checker view created.")
@pyqtProperty(bool, notify = onChanged) @pyqtProperty(bool, notify = onChanged)
def runChecks(self): def hasWarnings(self):
danger_shrinkage = self.checkObjectsForShrinkage() danger_shrinkage = self.checkObjectsForShrinkage()
return any((danger_shrinkage, )) #If any of the checks fail, show the warning button. return any((danger_shrinkage, )) #If any of the checks fail, show the warning button.
@pyqtSlot() @pyqtSlot()

View file

@ -18,7 +18,7 @@ Button
UM.I18nCatalog{id: catalog; name:"cura"} UM.I18nCatalog{id: catalog; name:"cura"}
visible: manager.runChecks visible: manager.hasWarnings
tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.") tooltip: catalog.i18nc("@info:tooltip", "Some things could be problematic in this print. Click to see tips for adjustment.")
onClicked: manager.showWarnings() onClicked: manager.showWarnings()