mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 06:57:28 -06:00
Add call_on_qt_thread to fix project loading crashing on rendering
CURA-4839 See comments...
This commit is contained in:
parent
2eef282b40
commit
3fb9877a30
1 changed files with 33 additions and 0 deletions
|
@ -31,10 +31,42 @@ import zipfile
|
||||||
import io
|
import io
|
||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
|
import threading
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
## Base implementation for reading 3MF workspace files.
|
## Base implementation for reading 3MF workspace files.
|
||||||
class ThreeMFWorkspaceReader(WorkspaceReader):
|
class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -401,6 +433,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
# containing global.cfg / extruder.cfg
|
# containing global.cfg / extruder.cfg
|
||||||
#
|
#
|
||||||
# \param file_name
|
# \param file_name
|
||||||
|
@call_on_qt_thread
|
||||||
def read(self, file_name):
|
def read(self, file_name):
|
||||||
archive = zipfile.ZipFile(file_name, "r")
|
archive = zipfile.ZipFile(file_name, "r")
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue