diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index c4e1c416dd..18d1bde57e 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,11 +515,10 @@ 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) # Set up a local socket server which listener which coordinates single instances Curas and accepts commands. def _setUpSingleInstanceServer(self): @@ -566,13 +572,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 +613,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 +683,12 @@ 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/PrintInformation.py b/cura/PrintInformation.py index ca5433f305..5e64413d27 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -16,6 +16,7 @@ import math import os.path import unicodedata import json +import re #To create abbreviations for printer names. from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -316,15 +317,14 @@ class PrintInformation(QObject): return global_stack_name = global_container_stack.getName() - split_name = global_stack_name.split(" ") abbr_machine = "" - for word in split_name: + for word in re.findall(r"[\w']+", global_stack_name): if word.lower() == "ultimaker": abbr_machine += "UM" elif word.isdigit(): abbr_machine += word else: - stripped_word = self._stripAccents(word.strip("()[]{}#").upper()) + stripped_word = self._stripAccents(word.upper()) # - use only the first character if the word is too long (> 3 characters) # - use the whole word if it's not too long (<= 3 characters) if len(stripped_word) > 3: 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() diff --git a/resources/definitions/innovo_inventor.def.json b/resources/definitions/innovo_inventor.def.json index 84b6697d34..5d587f9b30 100644 --- a/resources/definitions/innovo_inventor.def.json +++ b/resources/definitions/innovo_inventor.def.json @@ -46,7 +46,7 @@ "default_value": "RepRap (Marlin/Sprinter)" }, "machine_start_gcode": { - "default_value": "G28 ; Home extruder\nM107 ; Turn off fan\nG90 ; Absolute positioning\nM82 ; Extruder in absolute mode\nM190 S{material_bed_temperature}\nM104 T0 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\nG32 S3 ; auto level\nG92 E0 ; Reset extruder position" + "default_value": "G28 ; Home extruder\nM107 ; Turn off fan\nG90 ; Absolute positioning\nM82 ; Extruder in absolute mode\nM190 S{material_bed_temperature}\nM104 T0 S{material_print_temperature}\nM109 T0 S{material_print_temperature}\nM104 T1 S{material_print_temperature}\nM109 T1 S{material_print_temperature}\n;G32 S3 ; auto level\nG92 E0 ; Reset extruder position" }, "machine_end_gcode": { "default_value": "M104 S0 ; turn off extruders\nM140 S0 ; heated bed heater off\nG91 ; relative positioning\nG1 E-2 F5000; retract 2mm\nG28 Z; move bed down\nG90 ; absolute positioning\nM84 ; disable motors"