WIP: Make application initialization and start up more clear

- Create SingleInstance class to handling single instance stuff.
 - Instead of calling getInstance() everywhere, initialize each object
   explicitly in order when application starts and getInstance()s do not
   create instances any more and they merely return the created
   instances.
 - Only set initial values in construtor functions __init__(). Move the
   initialization of context-aware (i.e. things that depend on other
   things) to separate functions.
 - Split application creation and initialziation into several steps and
   them should be called explicitly in the correct order.
This commit is contained in:
Lipu Fei 2018-04-30 16:47:14 +02:00
parent c8f73d303e
commit 051dd7a6e9
14 changed files with 521 additions and 471 deletions

View file

@ -1,51 +1,36 @@
#!/usr/bin/env python3
# Copyright (c) 2015 Ultimaker B.V.
# Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
import argparse
import faulthandler
import os
import sys
from UM.Platform import Platform
parser = argparse.ArgumentParser(prog = "cura",
add_help = False)
parser.add_argument('--debug',
action='store_true',
default = False,
help = "Turn on the debug mode by setting this option."
)
parser.add_argument('--trigger-early-crash',
dest = 'trigger_early_crash',
action = 'store_true',
default = False,
help = "FOR TESTING ONLY. Trigger an early crash to show the crash dialog."
)
known_args = vars(parser.parse_known_args()[0])
if not known_args["debug"]:
def get_cura_dir_path():
if Platform.isWindows():
return os.path.expanduser("~/AppData/Roaming/cura/")
elif Platform.isLinux():
return os.path.expanduser("~/.local/share/cura")
elif Platform.isOSX():
return os.path.expanduser("~/Library/Logs/cura")
# Gets the directory for stdout and stderr
def get_cura_dir_for_stdoutputs() -> str:
if Platform.isWindows():
return os.path.expanduser("~/AppData/Roaming/cura/")
elif Platform.isLinux():
return os.path.expanduser("~/.local/share/cura")
elif Platform.isOSX():
return os.path.expanduser("~/Library/Logs/cura")
if hasattr(sys, "frozen"):
dirpath = get_cura_dir_path()
os.makedirs(dirpath, exist_ok = True)
sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding = "utf-8")
sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w", encoding = "utf-8")
import platform
import faulthandler
# Change stdout and stderr to files if Cura is running as a packaged application.
if hasattr(sys, "frozen"):
dir_path = get_cura_dir_for_stdoutputs()
os.makedirs(dir_path, exist_ok = True)
sys.stdout = open(os.path.join(dir_path, "stdout.log"), "w", encoding = "utf-8")
sys.stderr = open(os.path.join(dir_path, "stderr.log"), "w", encoding = "utf-8")
#WORKAROUND: GITHUB-88 GITHUB-385 GITHUB-612
# WORKAROUND: GITHUB-88 GITHUB-385 GITHUB-612
if Platform.isLinux(): # Needed for platform.linux_distribution, which is not available on Windows and OSX
# For Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826
linux_distro_name = platform.linux_distribution()[0].lower()
# The workaround is only needed on Ubuntu+NVidia drivers. Other drivers are not affected, but fine with this fix.
try:
import ctypes
@ -79,6 +64,7 @@ if "PYTHONPATH" in os.environ.keys(): # If PYTHONPATH is u
sys.path.remove(PATH_real)
sys.path.insert(1, PATH_real) # Insert it at 1 after os.curdir, which is 0.
def exceptHook(hook_type, value, traceback):
from cura.CrashHandler import CrashHandler
from cura.CuraApplication import CuraApplication
@ -121,25 +107,25 @@ def exceptHook(hook_type, value, traceback):
_crash_handler.early_crash_dialog.show()
sys.exit(application.exec_())
if not known_args["debug"]:
sys.excepthook = exceptHook
# Set exception hook to use the crash dialog handler
sys.excepthook = exceptHook
# Enable dumping traceback for all threads
faulthandler.enable(all_threads = True)
# Workaround for a race condition on certain systems where there
# is a race condition between Arcus and PyQt. Importing Arcus
# first seems to prevent Sip from going into a state where it
# tries to create PyQt objects on a non-main thread.
import Arcus #@UnusedImport
import cura.CuraApplication
import cura.Settings.CuraContainerRegistry
from cura.CuraApplication import CuraApplication
faulthandler.enable()
app = CuraApplication()
app.addCommandLineOptions()
app.parseCliOptions()
app.initialize()
# Force an instance of CuraContainerRegistry to be created and reused later.
cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance()
app.startSlashWindowPhase()
app.startPostSlashWindowPhase()
# This pre-start up check is needed to determine if we should start the application at all.
if not cura.CuraApplication.CuraApplication.preStartUp(parser = parser, parsed_command_line = known_args):
sys.exit(0)
app = cura.CuraApplication.CuraApplication.getInstance(parser = parser, parsed_command_line = known_args)
app.run()