diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index c4e1c416dd..62ece1ef1e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -127,7 +127,7 @@ class CuraApplication(QtApplication): # Cura will always show the Add Machine Dialog upon start. stacksValidationFinished = pyqtSignal() # Emitted whenever a validation is finished - def __init__(self): + def __init__(self, **kwargs): # this list of dir names will be used by UM to detect an old cura directory for dir_name in ["extruders", "machine_instances", "materials", "plugins", "quality", "user", "variants"]: @@ -208,9 +208,12 @@ class CuraApplication(QtApplication): self._additional_components = {} # Components to add to certain areas in the interface - super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType, + super().__init__(name = "cura", + version = CuraVersion, + buildtype = CuraBuildType, is_debug_mode = CuraDebugMode, - tray_icon_name = "cura-icon-32.png") + tray_icon_name = "cura-icon-32.png", + **kwargs) self.default_theme = "cura-light" @@ -400,7 +403,11 @@ class CuraApplication(QtApplication): @pyqtSlot() def closeApplication(self): Logger.log("i", "Close application") - self._main_window.close() + main_window = self.getMainWindow() + if main_window is not None: + main_window.close() + else: + self.exit(0) ## A reusable dialogbox # @@ -508,8 +515,8 @@ class CuraApplication(QtApplication): self._plugins_loaded = True @classmethod - def addCommandLineOptions(self, parser): - super().addCommandLineOptions(parser) + def addCommandLineOptions(self, parser, parsed_command_line = {}): + super().addCommandLineOptions(parser, parsed_command_line = parsed_command_line) parser.add_argument("file", nargs="*", help="Files to load after starting the application.") parser.add_argument("--single-instance", action="store_true", default=False) parser.add_argument("--headless", action = "store_true", default=False) @@ -566,13 +573,16 @@ class CuraApplication(QtApplication): # This should be called directly before creating an instance of CuraApplication. # \returns \type{bool} True if the whole Cura app should continue running. @classmethod - def preStartUp(cls): + def preStartUp(cls, parser = None, parsed_command_line = {}): # Peek the arguments and look for the 'single-instance' flag. - parser = argparse.ArgumentParser(prog="cura") # pylint: disable=bad-whitespace - CuraApplication.addCommandLineOptions(parser) - parsed_command_line = vars(parser.parse_args()) + if not parser: + parser = argparse.ArgumentParser(prog = "cura", add_help = False) # pylint: disable=bad-whitespace + CuraApplication.addCommandLineOptions(parser, parsed_command_line = parsed_command_line) + # Important: It is important to keep this line here! + # In Uranium we allow to pass unknown arguments to the final executable or script. + parsed_command_line.update(vars(parser.parse_known_args()[0])) - if "single_instance" in parsed_command_line and parsed_command_line["single_instance"]: + if parsed_command_line["single_instance"]: Logger.log("i", "Checking for the presence of an ready running Cura instance.") single_instance_socket = QLocalSocket() Logger.log("d", "preStartUp(): full server name: " + single_instance_socket.fullServerName()) @@ -604,7 +614,22 @@ class CuraApplication(QtApplication): return False return True + def preRun(self): + # Last check for unknown commandline arguments + parser = self.getCommandlineParser() + parser.add_argument("--help", "-h", + action='store_true', + default = False, + help = "Show this help message and exit." + ) + parsed_args = vars(parser.parse_args()) # This won't allow unknown arguments + if parsed_args["help"]: + parser.print_help() + sys.exit(0) + def run(self): + self.preRun() + self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene...")) self._setUpSingleInstanceServer() @@ -659,12 +684,11 @@ class CuraApplication(QtApplication): self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml")) self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) - run_headless = self.getCommandLineOption("headless", False) - if not run_headless: + run_without_gui = self.getCommandLineOption("headless", False) or self.getCommandLineOption("invisible", False) + if not run_without_gui: self.initializeEngine() - controller.setActiveStage("PrepareStage") - if run_headless or self._engine.rootObjects: + if run_without_gui or self._engine.rootObjects: self.closeSplash() for file_name in self.getCommandLineOption("file", []): @@ -1362,7 +1386,8 @@ class CuraApplication(QtApplication): # If a model is to small then it will not contain any points if offset_shape_arr is None and hull_shape_arr is None: Message(self._i18n_catalog.i18nc("@info:status", "The selected model was too small to load."), - title=self._i18n_catalog.i18nc("@info:title", "Warning")).show() + title=self._i18n_catalog.i18nc("@info:title", "Warning") + ).show() return # Step is for skipping tests to make it a lot faster. it also makes the outcome somewhat rougher diff --git a/cura_app.py b/cura_app.py index 7583dd054e..b5844055ab 100755 --- a/cura_app.py +++ b/cura_app.py @@ -2,13 +2,40 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. + +import argparse import os import sys -import platform -import faulthandler 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." + ) +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") + + 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") + sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w") + +import platform +import faulthandler + #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 @@ -47,8 +74,8 @@ def exceptHook(hook_type, value, traceback): _crash_handler = CrashHandler(hook_type, value, traceback) _crash_handler.show() - -sys.excepthook = exceptHook +if not known_args["debug"]: + sys.excepthook = exceptHook # Workaround for a race condition on certain systems where there # is a race condition between Arcus and PyQt. Importing Arcus @@ -58,29 +85,14 @@ import Arcus #@UnusedImport import cura.CuraApplication import cura.Settings.CuraContainerRegistry -def get_cura_dir_path(): - if Platform.isWindows(): - return os.path.expanduser("~/AppData/Local/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") - sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w") - faulthandler.enable() # Force an instance of CuraContainerRegistry to be created and reused later. cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance() # This pre-start up check is needed to determine if we should start the application at all. -if not cura.CuraApplication.CuraApplication.preStartUp(): +if not cura.CuraApplication.CuraApplication.preStartUp(parser = parser, parsed_command_line = known_args): sys.exit(0) -app = cura.CuraApplication.CuraApplication.getInstance() +app = cura.CuraApplication.CuraApplication.getInstance(parser = parser, parsed_command_line = known_args) app.run()