From 43c9df5703ed10f51a7f65ea906bdaf8232dce3d Mon Sep 17 00:00:00 2001 From: Adam Rumjahn Date: Thu, 23 Nov 2017 20:14:43 -0500 Subject: [PATCH 01/74] Deactivate G32 auto leveling before print don't need this any more on the new printers --- resources/definitions/innovo_inventor.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/innovo_inventor.def.json b/resources/definitions/innovo_inventor.def.json index dd7e87d446..ea54e1fcc9 100644 --- a/resources/definitions/innovo_inventor.def.json +++ b/resources/definitions/innovo_inventor.def.json @@ -53,7 +53,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\n{IF_BED}M190 S{BED}\n{IF_EXT0}M104 T0 S{TEMP0}\n{IF_EXT0}M109 T0 S{TEMP0}\n{IF_EXT1}M104 T1 S{TEMP1}\n{IF_EXT1}M109 T1 S{TEMP1}\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\n{IF_BED}M190 S{BED}\n{IF_EXT0}M104 T0 S{TEMP0}\n{IF_EXT0}M109 T0 S{TEMP0}\n{IF_EXT1}M104 T1 S{TEMP1}\n{IF_EXT1}M109 T1 S{TEMP1}\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" From f6909619003cd18d4888f58f2c23fb93d32e42ad Mon Sep 17 00:00:00 2001 From: Adam Rumjahn Date: Tue, 5 Dec 2017 21:20:43 -0500 Subject: [PATCH 02/74] Deactivated G32 autoleveling Update form last commit, complied with new syntax --- resources/definitions/innovo_inventor.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/innovo_inventor.def.json b/resources/definitions/innovo_inventor.def.json index ea54e1fcc9..d574a435de 100644 --- a/resources/definitions/innovo_inventor.def.json +++ b/resources/definitions/innovo_inventor.def.json @@ -53,7 +53,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\n{IF_BED}M190 S{BED}\n{IF_EXT0}M104 T0 S{TEMP0}\n{IF_EXT0}M109 T0 S{TEMP0}\n{IF_EXT1}M104 T1 S{TEMP1}\n{IF_EXT1}M109 T1 S{TEMP1}\n;G32 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" From 6d190479ac27fa9cc4aefeef1ad78d6b6d56583a Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 14:56:09 +0100 Subject: [PATCH 03/74] Getting logs earlier! Have currently the issue here, that when running Cura as a COM service, that the Cura.exe is popping up for (feels like) 1s or less and crashes. --- cura_app.py | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/cura_app.py b/cura_app.py index 7583dd054e..cae0821825 100755 --- a/cura_app.py +++ b/cura_app.py @@ -2,13 +2,28 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. + import os import sys +from UM.Platform import Platform + +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") + import platform import faulthandler -from UM.Platform import Platform - #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,7 +62,6 @@ def exceptHook(hook_type, value, traceback): _crash_handler = CrashHandler(hook_type, value, traceback) _crash_handler.show() - sys.excepthook = exceptHook # Workaround for a race condition on certain systems where there @@ -58,21 +72,6 @@ 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. From e5096f731c06f94ba18fb336883d803471bf101c Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 14:58:24 +0100 Subject: [PATCH 04/74] cura_app: We store logs now at "Roaming" --- cura_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index cae0821825..fd36aa5a24 100755 --- a/cura_app.py +++ b/cura_app.py @@ -9,7 +9,7 @@ from UM.Platform import Platform def get_cura_dir_path(): if Platform.isWindows(): - return os.path.expanduser("~/AppData/Local/cura/") + return os.path.expanduser("~/AppData/Roaming/cura/") elif Platform.isLinux(): return os.path.expanduser("~/.local/share/cura") elif Platform.isOSX(): From 00a77da9d449244f62dc61a4f8a554893be17b3f Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 15:19:28 +0100 Subject: [PATCH 05/74] COM: Adding missing argument for DCOM --- cura/CuraApplication.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a5ae286b1e..e02c44d205 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -570,6 +570,7 @@ class CuraApplication(QtApplication): 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) + parser.add_argument("-Embedding", action="store_true", default=False) # Commandline option set my DCOM (Windows Automation) # Set up a local socket server which listener which coordinates single instances Curas and accepts commands. def _setUpSingleInstanceServer(self): From 83d8c693bc0280019830f84d589872fbc32b866c Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 15:23:35 +0100 Subject: [PATCH 06/74] CuraApplication: Removing superflous check Imagine that there was no "single_instance" in parsed_command_line, then the second half of the if-clause would automatically crash. Also we defined single_instance to be False, whenever not set. Therefore it is always there. Also since no issues ever happened here, let's remove this check. --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e02c44d205..45ed6b8260 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -630,7 +630,7 @@ class CuraApplication(QtApplication): CuraApplication.addCommandLineOptions(parser) parsed_command_line = vars(parser.parse_args()) - 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()) From 11cf642a6e3c881a6a7918c6c8d5377c346403a6 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 15:43:28 +0100 Subject: [PATCH 07/74] COM: Prevent splash screen, when Embedding is set. So when dispatching our service we won't see any splash screen. Just like we want for headless applications. --- cura/CuraApplication.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 45ed6b8260..a6a54ad832 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -660,6 +660,8 @@ class CuraApplication(QtApplication): single_instance_socket.flush() single_instance_socket.waitForDisconnected() return False + if parsed_command_line["Embedding"]: + self._splash_prevent = True return True def run(self): From b22981d08973e8d08c3ae3f0c5cbf1cf45ab2f26 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 16:12:56 +0100 Subject: [PATCH 08/74] It is cls not self! --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a6a54ad832..30ce730562 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -661,7 +661,7 @@ class CuraApplication(QtApplication): single_instance_socket.waitForDisconnected() return False if parsed_command_line["Embedding"]: - self._splash_prevent = True + cls._splash_prevent = True return True def run(self): From abc2cdb7010bd06d3cbb46f89d7287b3d6d9c169 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 20:18:11 +0100 Subject: [PATCH 09/74] CuraApplication: Adding important note about the argparser --- cura/CuraApplication.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 30ce730562..1c610eebb6 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -628,6 +628,8 @@ class CuraApplication(QtApplication): # Peek the arguments and look for the 'single-instance' flag. parser = argparse.ArgumentParser(prog="cura") # pylint: disable=bad-whitespace CuraApplication.addCommandLineOptions(parser) + # 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 = vars(parser.parse_args()) if parsed_command_line["single_instance"]: From 8c74092f48d3b9322dbca3b9abf1c7bdbaf816a2 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 20:18:38 +0100 Subject: [PATCH 10/74] CuraApplication: Getting argparser from Uranium --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 1c610eebb6..f897c19f0b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -626,7 +626,7 @@ class CuraApplication(QtApplication): @classmethod def preStartUp(cls): # Peek the arguments and look for the 'single-instance' flag. - parser = argparse.ArgumentParser(prog="cura") # pylint: disable=bad-whitespace + parser = cls.getCommandlineParser() CuraApplication.addCommandLineOptions(parser) # Important: It is important to keep this line here! # In Uranium we allow to pass unknown arguments to the final executable or script. From 315efae53b68c9530bc2a2c15f46b876081cfd30 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 20:27:25 +0100 Subject: [PATCH 11/74] CuraApplication: Making use of Uranium commandline tools --- cura/CuraApplication.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index f897c19f0b..5cced81260 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -628,11 +628,9 @@ class CuraApplication(QtApplication): # Peek the arguments and look for the 'single-instance' flag. parser = cls.getCommandlineParser() CuraApplication.addCommandLineOptions(parser) - # 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 = vars(parser.parse_args()) + cls.parseCommandLine() - if parsed_command_line["single_instance"]: + if cls.getCommandLineOption("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()) @@ -651,8 +649,8 @@ class CuraApplication(QtApplication): payload = {"command": "focus"} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ASCII")) - if len(parsed_command_line["file"]) != 0: - for filename in parsed_command_line["file"]: + if len(cls.getCommandLineOption("file")) != 0: + for filename in cls.getCommandLineOption("file"): payload = {"command": "open", "filePath": filename} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ASCII")) @@ -662,7 +660,7 @@ class CuraApplication(QtApplication): single_instance_socket.flush() single_instance_socket.waitForDisconnected() return False - if parsed_command_line["Embedding"]: + if cls.getCommandLineOption("Embedding"): cls._splash_prevent = True return True From 0967651a491d644be9ad4b36051945f5dafa8032 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 20:28:46 +0100 Subject: [PATCH 12/74] CuraApplication: Adding last check for unknown arguments into _onEngineCreated So after everything is loaded, we can blame the user about wrong arguments. --- cura/CuraApplication.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 5cced81260..2d6254cc2e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -385,6 +385,10 @@ class CuraApplication(QtApplication): self._plugin_registry.addSupportedPluginExtension("curaplugin", "Cura Plugin") def _onEngineCreated(self): + # Last check for unknown commandline arguments + parser = self.getCommandlineParser() + parser.parse_args() + self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) @pyqtProperty(bool) From 9210d38412598f413952614a45151f6ad7b95f74 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 21:31:41 +0100 Subject: [PATCH 13/74] Revert "CuraApplication: Getting argparser from Uranium" This reverts commit 8c74092f48d3b9322dbca3b9abf1c7bdbaf816a2. --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2d6254cc2e..972074816b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -630,7 +630,7 @@ class CuraApplication(QtApplication): @classmethod def preStartUp(cls): # Peek the arguments and look for the 'single-instance' flag. - parser = cls.getCommandlineParser() + parser = argparse.ArgumentParser(prog="cura") # pylint: disable=bad-whitespace CuraApplication.addCommandLineOptions(parser) cls.parseCommandLine() From 35ed042a72c5504a00973d10f47e904eb6163312 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 21:49:00 +0100 Subject: [PATCH 14/74] Revert "CuraApplication: Making use of Uranium commandline tools" This reverts commit 315efae53b68c9530bc2a2c15f46b876081cfd30. --- cura/CuraApplication.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 972074816b..4349ae792d 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -632,9 +632,11 @@ class CuraApplication(QtApplication): # Peek the arguments and look for the 'single-instance' flag. parser = argparse.ArgumentParser(prog="cura") # pylint: disable=bad-whitespace CuraApplication.addCommandLineOptions(parser) - cls.parseCommandLine() + # 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 = vars(parser.parse_args()) - if cls.getCommandLineOption("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()) @@ -653,8 +655,8 @@ class CuraApplication(QtApplication): payload = {"command": "focus"} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ASCII")) - if len(cls.getCommandLineOption("file")) != 0: - for filename in cls.getCommandLineOption("file"): + if len(parsed_command_line["file"]) != 0: + for filename in parsed_command_line["file"]: payload = {"command": "open", "filePath": filename} single_instance_socket.write(bytes(json.dumps(payload) + "\n", encoding="ASCII")) @@ -664,7 +666,7 @@ class CuraApplication(QtApplication): single_instance_socket.flush() single_instance_socket.waitForDisconnected() return False - if cls.getCommandLineOption("Embedding"): + if parsed_command_line["Embedding"]: cls._splash_prevent = True return True From 044c538887acad4b4b5dbae37c2747df36a87d54 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 22:09:49 +0100 Subject: [PATCH 15/74] CuraApplication: Allow unknown arguments --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 4349ae792d..11ea6b3edb 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -634,7 +634,7 @@ class CuraApplication(QtApplication): CuraApplication.addCommandLineOptions(parser) # 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 = vars(parser.parse_args()) + parsed_command_line = vars(parser.known_args()[0]) if parsed_command_line["single_instance"]: Logger.log("i", "Checking for the presence of an ready running Cura instance.") From b098b167e51757294deddf3737bd1faf87a71caa Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Fri, 8 Dec 2017 22:31:04 +0100 Subject: [PATCH 16/74] Fixing name --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 11ea6b3edb..39da5868dd 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -634,7 +634,7 @@ class CuraApplication(QtApplication): CuraApplication.addCommandLineOptions(parser) # 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 = vars(parser.known_args()[0]) + parsed_command_line = vars(parser.parse_known_args()[0]) if parsed_command_line["single_instance"]: Logger.log("i", "Checking for the presence of an ready running Cura instance.") From 1a9c15204122073691744a58964bc8ed21fe966c Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 00:08:13 +0100 Subject: [PATCH 17/74] CuraApplication: Don't parse -h or --help before last check --- cura/CuraApplication.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 39da5868dd..069b80101b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -386,7 +386,7 @@ class CuraApplication(QtApplication): def _onEngineCreated(self): # Last check for unknown commandline arguments - parser = self.getCommandlineParser() + parser = self.getCommandlineParser(with_help = True) parser.parse_args() self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) @@ -630,7 +630,8 @@ class CuraApplication(QtApplication): @classmethod def preStartUp(cls): # Peek the arguments and look for the 'single-instance' flag. - parser = argparse.ArgumentParser(prog="cura") # pylint: disable=bad-whitespace + parser = argparse.ArgumentParser(prog = "cura", + add_help = False) # pylint: disable=bad-whitespace CuraApplication.addCommandLineOptions(parser) # Important: It is important to keep this line here! # In Uranium we allow to pass unknown arguments to the final executable or script. From 61b6831e62598e8f91edd0365f8b373e2588422a Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 01:21:58 +0100 Subject: [PATCH 18/74] CuraApplication: Making it one line again Don't know why the pylint marker is here.. --- cura/CuraApplication.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 069b80101b..4af5e4f88a 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -630,8 +630,7 @@ class CuraApplication(QtApplication): @classmethod def preStartUp(cls): # Peek the arguments and look for the 'single-instance' flag. - parser = argparse.ArgumentParser(prog = "cura", - add_help = False) # pylint: disable=bad-whitespace + parser = argparse.ArgumentParser(prog = "cura", add_help = False) # pylint: disable=bad-whitespace CuraApplication.addCommandLineOptions(parser) # Important: It is important to keep this line here! # In Uranium we allow to pass unknown arguments to the final executable or script. From ab6508657da4482c74d65b10f7e0b95fd05927d2 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 02:13:31 +0100 Subject: [PATCH 19/74] Creating an argparser early and add a "debug" option Makes sure we don't log anything at the moment, when debug is passed. Otherwise early errors are not displayed and passed to log files. --- cura/CuraApplication.py | 7 ++++--- cura_app.py | 39 +++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 4af5e4f88a..040f601cfe 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -628,13 +628,14 @@ 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", add_help = False) # pylint: disable=bad-whitespace + if not parser: + parser = argparse.ArgumentParser(prog = "cura", add_help = False) # pylint: disable=bad-whitespace CuraApplication.addCommandLineOptions(parser) # 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 = vars(parser.parse_known_args()[0]) + parsed_command_line.update(vars(parser.parse_known_args()[0])) if parsed_command_line["single_instance"]: Logger.log("i", "Checking for the presence of an ready running Cura instance.") diff --git a/cura_app.py b/cura_app.py index fd36aa5a24..c719fe3e10 100755 --- a/cura_app.py +++ b/cura_app.py @@ -3,23 +3,34 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +import argparse import os import sys + from UM.Platform import Platform -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") +parser = argparse.ArgumentParser() +parser.add_argument('--debug', + action='store_true', + default = False + ) +known_args, unknown_args = parser.parse_known_args() +known_args = vars(known_args) -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") +if 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 @@ -78,8 +89,8 @@ faulthandler.enable() 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() From bc7cb1491d735f48041384d7fc61f676477c65a2 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 02:13:47 +0100 Subject: [PATCH 20/74] Removing "Embedding" option again --- cura/CuraApplication.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 040f601cfe..a5d55773d7 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -574,7 +574,6 @@ class CuraApplication(QtApplication): 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) - parser.add_argument("-Embedding", action="store_true", default=False) # Commandline option set my DCOM (Windows Automation) # Set up a local socket server which listener which coordinates single instances Curas and accepts commands. def _setUpSingleInstanceServer(self): @@ -667,8 +666,6 @@ class CuraApplication(QtApplication): single_instance_socket.flush() single_instance_socket.waitForDisconnected() return False - if parsed_command_line["Embedding"]: - cls._splash_prevent = True return True def run(self): From 2614c8a623155ce3b257d22fc9d95d108b18a2d9 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 02:40:46 +0100 Subject: [PATCH 21/74] Don't hook to CrashHandler, if we are debugging Getting an early crash here. Hope that one helps. --- cura_app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index c719fe3e10..a09b5b07dc 100755 --- a/cura_app.py +++ b/cura_app.py @@ -73,7 +73,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 From 63acaed0a5439d05c46c43b6f6db1ac105d1805a Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 02:52:51 +0100 Subject: [PATCH 22/74] Correcting if clause We don't want logs, when debugging. --- cura_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index a09b5b07dc..627583d384 100755 --- a/cura_app.py +++ b/cura_app.py @@ -17,7 +17,7 @@ parser.add_argument('--debug', known_args, unknown_args = parser.parse_known_args() known_args = vars(known_args) -if known_args["debug"]: +if not known_args["debug"]: def get_cura_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/cura/") From e578014a2eb6e82f5b9db0b0bb7c805c955b6ae9 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 11:25:01 +0100 Subject: [PATCH 23/74] Passing the already parsed args --- cura/CuraApplication.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a5d55773d7..37e5e1f2da 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -569,8 +569,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) @@ -631,7 +631,7 @@ class CuraApplication(QtApplication): # Peek the arguments and look for the 'single-instance' flag. if not parser: parser = argparse.ArgumentParser(prog = "cura", add_help = False) # pylint: disable=bad-whitespace - CuraApplication.addCommandLineOptions(parser) + 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])) From 74be22e68223e38dfdbda144d25ac69470f1704b Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 11:26:04 +0100 Subject: [PATCH 24/74] Adding the application name Maybe it is possible to set this value later. Eg. in Uranium, so we can get the name from .getApplicationName(). --- cura_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index 627583d384..9167829754 100755 --- a/cura_app.py +++ b/cura_app.py @@ -9,7 +9,7 @@ import sys from UM.Platform import Platform -parser = argparse.ArgumentParser() +parser = argparse.ArgumentParser(prog = "cura") parser.add_argument('--debug', action='store_true', default = False From f9554475be1363d235b6a4c1e8d62b0b00179d64 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 11:47:23 +0100 Subject: [PATCH 25/74] CuraApplication: Allow getting kwargs and pass them to super().__init__() --- cura/CuraApplication.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 37e5e1f2da..72ba21edab 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"]: @@ -207,9 +207,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" From 97196190d612699420f67a142bf33875adb2d854 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 12:04:53 +0100 Subject: [PATCH 26/74] cura_app: Adding help text for debug --- cura_app.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index 9167829754..118ea97c30 100755 --- a/cura_app.py +++ b/cura_app.py @@ -12,7 +12,9 @@ from UM.Platform import Platform parser = argparse.ArgumentParser(prog = "cura") parser.add_argument('--debug', action='store_true', - default = False + default = False, + help="Turn on the debug mode by setting this option." + ) ) known_args, unknown_args = parser.parse_known_args() known_args = vars(known_args) From bae6f2cfb56bead58ea8c6117b0f9f42d3edea1b Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 12:43:41 +0100 Subject: [PATCH 27/74] Typo --- cura_app.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index 118ea97c30..3e91235d96 100755 --- a/cura_app.py +++ b/cura_app.py @@ -15,7 +15,6 @@ parser.add_argument('--debug', default = False, help="Turn on the debug mode by setting this option." ) - ) known_args, unknown_args = parser.parse_known_args() known_args = vars(known_args) From 3e775f71fd17cabd11048acabaee720fe42997a5 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 13:00:41 +0100 Subject: [PATCH 28/74] Typo --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 72ba21edab..fb6c4b451b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -211,7 +211,7 @@ class CuraApplication(QtApplication): 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" From c62b04089fd1fcafba002a4e18d650ea12754f53 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 15:43:05 +0100 Subject: [PATCH 29/74] Moving setActiveStage("PrepareStage") to initializeEngine() in UM --- cura/CuraApplication.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index fb6c4b451b..f43c10ebe4 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -729,7 +729,6 @@ class CuraApplication(QtApplication): run_headless = self.getCommandLineOption("headless", False) if not run_headless: self.initializeEngine() - controller.setActiveStage("PrepareStage") if run_headless or self._engine.rootObjects: self.closeSplash() From 4b8d05092d4cb0eca43bbe9d9402e893f2e2f040 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 15:56:06 +0100 Subject: [PATCH 30/74] Adding preRun and move last commandline argument check to it. --- cura/CuraApplication.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index f43c10ebe4..db03d7440a 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -388,10 +388,6 @@ class CuraApplication(QtApplication): self._plugin_registry.addSupportedPluginExtension("curaplugin", "Cura Plugin") def _onEngineCreated(self): - # Last check for unknown commandline arguments - parser = self.getCommandlineParser(with_help = True) - parser.parse_args() - self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) @pyqtProperty(bool) @@ -671,7 +667,14 @@ class CuraApplication(QtApplication): return False return True + def preRun(self): + # Last check for unknown commandline arguments + parser = self.getCommandlineParser(with_help = True) + parser.parse_args() + def run(self): + self.preRun() + self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene...")) self._setUpSingleInstanceServer() From 37cf78487ef8a433239ff2ade03f9ea97ecbf2ea Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 15:56:52 +0100 Subject: [PATCH 31/74] headless+invidible: It is all about being hidden So don't show any gui. --- cura/CuraApplication.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index db03d7440a..f0bdcff3e3 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -729,11 +729,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("headless", False) + if not run_without_gui: self.initializeEngine() - if run_headless or self._engine.rootObjects: + if run_without_gui or self._engine.rootObjects: self.closeSplash() for file_name in self.getCommandLineOption("file", []): From 904f7c53ccd9edf98c4a929c97a1a6e1599c904e Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 16:00:34 +0100 Subject: [PATCH 32/74] Code style --- cura_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index 3e91235d96..af4e1f2a48 100755 --- a/cura_app.py +++ b/cura_app.py @@ -13,7 +13,7 @@ parser = argparse.ArgumentParser(prog = "cura") parser.add_argument('--debug', action='store_true', default = False, - help="Turn on the debug mode by setting this option." + help = "Turn on the debug mode by setting this option." ) known_args, unknown_args = parser.parse_known_args() known_args = vars(known_args) From 7e7303a7e3a37c71a94728c7dd7c5f27dd223d96 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 16:00:56 +0100 Subject: [PATCH 33/74] Code style --- cura/CuraApplication.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index f0bdcff3e3..03429fb690 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1431,7 +1431,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 From 8e89c1b36144d4861f58093de15b6f2a480964c8 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 17:40:06 +0100 Subject: [PATCH 34/74] No comment on this.. --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 03429fb690..d6b8d416cd 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -729,7 +729,7 @@ class CuraApplication(QtApplication): self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml")) self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) - run_without_gui = self.getCommandLineOption("headless", False) or self.getCommandLineOption("headless", False) + run_without_gui = self.getCommandLineOption("headless", False) or self.getCommandLineOption("invisible", False) if not run_without_gui: self.initializeEngine() From bcc31fb19b378eb2f024ef194b4324a0a0d2baa3 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 22:26:52 +0100 Subject: [PATCH 35/74] Tell early parser not to add help --- cura_app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura_app.py b/cura_app.py index af4e1f2a48..56ae51aaa3 100755 --- a/cura_app.py +++ b/cura_app.py @@ -9,7 +9,8 @@ import sys from UM.Platform import Platform -parser = argparse.ArgumentParser(prog = "cura") +parser = argparse.ArgumentParser(prog = "cura", + add_help = False) parser.add_argument('--debug', action='store_true', default = False, From b4aed1da22de53306ef7fa812a3380503b2f18a7 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 22:27:15 +0100 Subject: [PATCH 36/74] Simplify getting known args --- cura_app.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura_app.py b/cura_app.py index 56ae51aaa3..b5844055ab 100755 --- a/cura_app.py +++ b/cura_app.py @@ -16,8 +16,7 @@ parser.add_argument('--debug', default = False, help = "Turn on the debug mode by setting this option." ) -known_args, unknown_args = parser.parse_known_args() -known_args = vars(known_args) +known_args = vars(parser.parse_known_args()[0]) if not known_args["debug"]: def get_cura_dir_path(): From f1d5bc38dcf07802827ca426cf05614239601a29 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sat, 9 Dec 2017 23:01:26 +0100 Subject: [PATCH 37/74] Adding help arguments manually .. and also print and exit as it normally does, when enabled. --- cura/CuraApplication.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index d6b8d416cd..7b067f452c 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -669,8 +669,16 @@ class CuraApplication(QtApplication): def preRun(self): # Last check for unknown commandline arguments - parser = self.getCommandlineParser(with_help = True) - parser.parse_args() + 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() From 1cd107965c320a4d3f6cd88a960b0a7a5124b635 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sun, 10 Dec 2017 00:39:20 +0100 Subject: [PATCH 38/74] Close all windows, if there is no main window --- cura/CuraApplication.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 7b067f452c..fc675e549b 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -401,7 +401,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.closeAllWindows() ## A reusable dialogbox # From 79cb1a1293f4e6874f596288e611e91d5814c153 Mon Sep 17 00:00:00 2001 From: Thomas Karl Pietrowski Date: Sun, 10 Dec 2017 01:08:06 +0100 Subject: [PATCH 39/74] closeAllWindows seems to take no effect - use exit instead Looks like it does not work, because there was never a window or any other window on top of QApplication. .exit() should let us out of the main loop. --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index fc675e549b..abe1ddf374 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -405,7 +405,7 @@ class CuraApplication(QtApplication): if main_window is not None: main_window.close() else: - self.closeAllWindows() + self.exit(0) ## A reusable dialogbox # From 3666b35ff3f0a8ddeb7b6b23f4814508a86493f9 Mon Sep 17 00:00:00 2001 From: Ruben D Date: Wed, 13 Dec 2017 01:41:36 +0100 Subject: [PATCH 40/74] Fix winding order of 3D tubes Adding a copy of the first vertex causes the winding order to reverse. --- plugins/SimulationView/layers3d.shader | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index 2633b54787..14a766f764 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -192,6 +192,7 @@ geometry41core = } else { // All normal lines are rendered as 3d tubes. myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert)); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert)); From 79d7de050e86128b6b140508eef79df66051f4d4 Mon Sep 17 00:00:00 2001 From: Ruben D Date: Wed, 13 Dec 2017 01:42:24 +0100 Subject: [PATCH 41/74] Enable backface culling for layer view This effectively doubles the rendering performance of layer view. --- plugins/SimulationView/SimulationPass.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index 46fa7f1240..24bdedd368 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -92,7 +92,7 @@ class SimulationPass(RenderPass): self.bind() - tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay) + tool_handle_batch = RenderBatch(self._tool_handle_shader, type = RenderBatch.RenderType.Overlay, backface_cull = True) head_position = None # Indicates the current position of the print head nozzle_node = None @@ -149,7 +149,7 @@ class SimulationPass(RenderPass): self._current_shader = self._layer_shader self._switching_layers = True - layers_batch = RenderBatch(self._current_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end)) + layers_batch = RenderBatch(self._current_shader, type = RenderBatch.RenderType.Solid, mode = RenderBatch.RenderMode.Lines, range = (start, end), backface_cull = True) layers_batch.addItem(node.getWorldTransformation(), layer_data) layers_batch.render(self._scene.getActiveCamera()) From e36099a3807f62ed1a811dd637a5313e149fa792 Mon Sep 17 00:00:00 2001 From: Ruben D Date: Wed, 13 Dec 2017 01:44:05 +0100 Subject: [PATCH 42/74] Draw backside of travel lines inverted This adds a front-facing primitive towards the back side of every travel line, causing those lines to be visible from both sides regardless of backface culling. This doubles the number of vertices for travel moves, but due to backface culling it comes down to approximately the same performance as the original. --- plugins/SimulationView/layers3d.shader | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index 14a766f764..cbd27a2660 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -187,6 +187,13 @@ geometry41core = myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert)); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert)); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head + g_vertex_offset_vert)); + //And reverse so that the line is also visible from the back side. + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz + g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head + g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz + g_vertex_offset_vert)); EndPrimitive(); } else { From f69375691f0e7933e897e34c4535fe4fcb07a22b Mon Sep 17 00:00:00 2001 From: Ruben D Date: Wed, 13 Dec 2017 18:58:05 +0100 Subject: [PATCH 43/74] Reduce vertices per tube by 1 Since the tubes are symmetrical, instead of using an extra vertex to flip the winding order, I just mirror all horizontal coordinates so that the triangles flip inside out. --- plugins/SimulationView/layers3d.shader | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/SimulationView/layers3d.shader b/plugins/SimulationView/layers3d.shader index cbd27a2660..86a88fab83 100644 --- a/plugins/SimulationView/layers3d.shader +++ b/plugins/SimulationView/layers3d.shader @@ -198,17 +198,16 @@ geometry41core = EndPrimitive(); } else { // All normal lines are rendered as 3d tubes. - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); - myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert)); - myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert)); myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz)); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); - myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert)); - myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert)); myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); EndPrimitive(); From cda6aa25477107bab996db8bb37cf271f1342d4e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 14 Dec 2017 14:49:18 +0100 Subject: [PATCH 44/74] CURA-4234 splitted MachineSelection into a separate file and add it to PrintMonitor as well, because now it's part of the sidebar --- resources/qml/MachineSelection.qml | 71 ++++++++++++++++++++++++++++++ resources/qml/PrintMonitor.qml | 10 ++++- resources/qml/Sidebar.qml | 60 +------------------------ 3 files changed, 81 insertions(+), 60 deletions(-) create mode 100644 resources/qml/MachineSelection.qml diff --git a/resources/qml/MachineSelection.qml b/resources/qml/MachineSelection.qml new file mode 100644 index 0000000000..e40731f3ca --- /dev/null +++ b/resources/qml/MachineSelection.qml @@ -0,0 +1,71 @@ +// Copyright (c) 2017 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Layouts 1.1 + +import UM 1.2 as UM +import Cura 1.0 as Cura +import "Menus" + +ToolButton +{ + text: Cura.MachineManager.activeMachineName + + tooltip: Cura.MachineManager.activeMachineName + + style: ButtonStyle + { + background: Rectangle + { + color: + { + if(control.pressed) + { + return UM.Theme.getColor("sidebar_header_active"); + } + else if(control.hovered) + { + return UM.Theme.getColor("sidebar_header_hover"); + } + else + { + return UM.Theme.getColor("sidebar_header_bar"); + } + } + Behavior on color { ColorAnimation { duration: 50; } } + + UM.RecolorImage + { + id: downArrow + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + width: UM.Theme.getSize("standard_arrow").width + height: UM.Theme.getSize("standard_arrow").height + sourceSize.width: width + sourceSize.height: width + color: UM.Theme.getColor("text_emphasis") + source: UM.Theme.getIcon("arrow_bottom") + } + Label + { + id: sidebarComboBoxLabel + color: UM.Theme.getColor("sidebar_header_text_active") + text: control.text; + elide: Text.ElideRight; + anchors.left: parent.left; + anchors.leftMargin: UM.Theme.getSize("default_margin").width * 2 + anchors.right: downArrow.left; + anchors.rightMargin: control.rightMargin; + anchors.verticalCenter: parent.verticalCenter; + font: UM.Theme.getFont("large") + } + } + label: Label {} + } + + menu: PrinterMenu { } +} diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index e69f7cf4fd..806e302047 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -20,6 +20,14 @@ Column simpleNames: true } + MachineSelection { + id: machineSelection + width: base.width + height: UM.Theme.getSize("sidebar_header").height + anchors.top: base.top + anchors.right: parent.right + } + Rectangle { id: connectedPrinterHeader @@ -1171,4 +1179,4 @@ Column } } } -} \ No newline at end of file +} diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index a45303aab8..66c23752ce 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -87,70 +87,12 @@ Rectangle } } - ToolButton - { + MachineSelection { id: machineSelection - text: Cura.MachineManager.activeMachineName - width: base.width height: UM.Theme.getSize("sidebar_header").height - tooltip: Cura.MachineManager.activeMachineName - anchors.top: base.top - //anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - style: ButtonStyle - { - background: Rectangle - { - color: - { - if(control.pressed) - { - return UM.Theme.getColor("sidebar_header_active"); - } - else if(control.hovered) - { - return UM.Theme.getColor("sidebar_header_hover"); - } - else - { - return UM.Theme.getColor("sidebar_header_bar"); - } - } - Behavior on color { ColorAnimation { duration: 50; } } - - UM.RecolorImage - { - id: downArrow - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - width: UM.Theme.getSize("standard_arrow").width - height: UM.Theme.getSize("standard_arrow").height - sourceSize.width: width - sourceSize.height: width - color: UM.Theme.getColor("text_emphasis") - source: UM.Theme.getIcon("arrow_bottom") - } - Label - { - id: sidebarComboBoxLabel - color: UM.Theme.getColor("sidebar_header_text_active") - text: control.text; - elide: Text.ElideRight; - anchors.left: parent.left; - anchors.leftMargin: UM.Theme.getSize("default_margin").width * 2 - anchors.right: downArrow.left; - anchors.rightMargin: control.rightMargin; - anchors.verticalCenter: parent.verticalCenter; - font: UM.Theme.getFont("large") - } - } - label: Label {} - } - - menu: PrinterMenu { } } SidebarHeader { From c056fcb23d3d9a7530cf9a21bbf0a83e63660908 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Dec 2017 14:58:51 +0100 Subject: [PATCH 45/74] Fix monitor sidebar machine selection - CURA-4234 --- resources/qml/PrintMonitor.qml | 8 -------- resources/qml/Sidebar.qml | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 806e302047..5a5c160b51 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -20,14 +20,6 @@ Column simpleNames: true } - MachineSelection { - id: machineSelection - width: base.width - height: UM.Theme.getSize("sidebar_header").height - anchors.top: base.top - anchors.right: parent.right - } - Rectangle { id: connectedPrinterHeader diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 66c23752ce..d5cffb30a6 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -272,7 +272,7 @@ Rectangle { id: controlItem anchors.bottom: footerSeparator.top - anchors.top: monitoringPrint ? base.top : headerSeparator.bottom + anchors.top: monitoringPrint ? machineSelection.bottom : headerSeparator.bottom anchors.left: base.left anchors.right: base.right sourceComponent: @@ -291,7 +291,7 @@ Rectangle Loader { anchors.bottom: footerSeparator.top - anchors.top: monitoringPrint ? base.top : headerSeparator.bottom + anchors.top: monitoringPrint ? machineSelection.bottom : headerSeparator.bottom anchors.left: base.left anchors.right: base.right source: From 47e5303a893dd5b1879a9ecd4f762278807961fd Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Dec 2017 15:16:17 +0100 Subject: [PATCH 46/74] Catch situations where backend is not correctly set --- resources/qml/SaveButton.qml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index d53b43e459..9ecde4d72a 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -14,7 +14,7 @@ Item { property real progress: UM.Backend.progress property int backendState: UM.Backend.state - property var backend: CuraApplication.getBackend() + property var backend: CuraApplication.getBackend() || "undefined" property bool activity: CuraApplication.platformActivity property alias buttonRowWidth: saveRow.width @@ -49,12 +49,16 @@ Item { } function sliceOrStopSlicing() { - if (base.backendState != "undefined" && backend !== "undefined") { - if ([1, 5].indexOf(base.backendState) != -1) { - backend.forceSlice(); - } else { - backend.stopSlicing(); + try { + if (base.backendState != "undefined" && base.backend != "undefined") { + if ([1, 5].indexOf(base.backendState) != -1) { + backend.forceSlice(); + } else { + backend.stopSlicing(); + } } + } catch (e) { + console.log('Could not start or stop slicing', e) } } From 9db320bf352c04c0e31f98d55b20f92d716fae1b Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Dec 2017 15:34:58 +0100 Subject: [PATCH 47/74] Remove unused backend property --- resources/qml/Sidebar.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index d5cffb30a6..db7851a101 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -22,7 +22,6 @@ Rectangle property bool printerConnected: Cura.MachineManager.printerOutputDevices.length != 0 property bool printerAcceptsCommands: printerConnected && Cura.MachineManager.printerOutputDevices[0].acceptsCommands property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null - property int backendState: UM.Backend.state property bool monitoringPrint: UM.Controller.activeStage.stageId == "MonitorStage" From cac561600e99eec39c036c7126b8cd2dc2f7a121 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Thu, 14 Dec 2017 15:44:11 +0100 Subject: [PATCH 48/74] Use pyqtProperty instead of slot to bind backend --- resources/qml/SaveButton.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 9ecde4d72a..2b938c1745 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -14,7 +14,7 @@ Item { property real progress: UM.Backend.progress property int backendState: UM.Backend.state - property var backend: CuraApplication.getBackend() || "undefined" + property var backend: CuraApplication.backend property bool activity: CuraApplication.platformActivity property alias buttonRowWidth: saveRow.width From 2c18127cc1bc2801a7fdf6f7ec8f8ecca048757e Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 15 Dec 2017 09:43:02 +0100 Subject: [PATCH 49/74] Tests: Removed python circular import dependency and added empty containers CURA-4687 --- cura/Settings/CuraContainerStack.py | 2 +- tests/Settings/TestCuraContainerRegistry.py | 95 ++++++++++++++------- tests/Settings/TestExtruderStack.py | 29 +++++++ tests/Settings/TestGlobalStack.py | 29 +++++++ 4 files changed, 121 insertions(+), 34 deletions(-) diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py index 61c28df570..8e13b24358 100755 --- a/cura/Settings/CuraContainerStack.py +++ b/cura/Settings/CuraContainerStack.py @@ -377,7 +377,7 @@ class CuraContainerStack(ContainerStack): if not container or not isinstance(container, DefinitionContainer): definition = self.findContainer(container_type = DefinitionContainer) if not definition: - raise InvalidContainerStackError("Stack {id} does not have a definition!".format(id = self._id)) + raise InvalidContainerStackError("Stack {id} does not have a definition!".format(id = self.getId())) new_containers[index] = definition continue diff --git a/tests/Settings/TestCuraContainerRegistry.py b/tests/Settings/TestCuraContainerRegistry.py index e6dc6b99d8..9e5692b565 100644 --- a/tests/Settings/TestCuraContainerRegistry.py +++ b/tests/Settings/TestCuraContainerRegistry.py @@ -6,7 +6,9 @@ import pytest #This module contains unit tests. import shutil #To copy files to make a temporary file. import unittest.mock #To mock and monkeypatch stuff. import urllib.parse +import copy +import cura.CuraApplication from cura.Settings.CuraContainerRegistry import CuraContainerRegistry #The class we're testing. from cura.Settings.ExtruderStack import ExtruderStack #Testing for returning the correct types of stacks. from cura.Settings.GlobalStack import GlobalStack #Testing for returning the correct types of stacks. @@ -15,6 +17,32 @@ import UM.Settings.InstanceContainer #Creating instance containers to register. import UM.Settings.ContainerRegistry #Making empty container stacks. import UM.Settings.ContainerStack #Setting the container registry here properly. from UM.Settings.DefinitionContainer import DefinitionContainer +from UM.Settings.ContainerRegistry import ContainerRegistry + +def creteEmptyContainers(): + empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() + empty_variant_container = copy.deepcopy(empty_container) + empty_variant_container.setMetaDataEntry("id", "empty_variant") + empty_variant_container.addMetaDataEntry("type", "variant") + ContainerRegistry.getInstance().addContainer(empty_variant_container) + + empty_material_container = copy.deepcopy(empty_container) + empty_material_container.setMetaDataEntry("id", "empty_material") + empty_material_container.addMetaDataEntry("type", "material") + ContainerRegistry.getInstance().addContainer(empty_material_container) + + empty_quality_container = copy.deepcopy(empty_container) + empty_quality_container.setMetaDataEntry("id", "empty_quality") + empty_quality_container.setName("Not Supported") + empty_quality_container.addMetaDataEntry("quality_type", "not_supported") + empty_quality_container.addMetaDataEntry("type", "quality") + empty_quality_container.addMetaDataEntry("supported", False) + ContainerRegistry.getInstance().addContainer(empty_quality_container) + + empty_quality_changes_container = copy.deepcopy(empty_container) + empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") + empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") + ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) ## Gives a fresh CuraContainerRegistry instance. @pytest.fixture() @@ -37,6 +65,7 @@ def teardown(): ## Tests whether addContainer properly converts to ExtruderStack. def test_addContainerExtruderStack(container_registry, definition_container): + creteEmptyContainers() container_registry.addContainer(definition_container) container_stack = UM.Settings.ContainerStack.ContainerStack(stack_id = "Test Container Stack") #A container we're going to convert. @@ -113,36 +142,36 @@ def test_addContainerBadSettingVersion(container_registry, definition_container) mock_super_add_container.assert_not_called() #Should not get passed on to UM.Settings.ContainerRegistry.addContainer, because the setting_version doesn't match its definition! ## Tests whether loading gives objects of the correct type. -@pytest.mark.parametrize("filename, output_class", [ - ("ExtruderLegacy.stack.cfg", ExtruderStack), - ("MachineLegacy.stack.cfg", GlobalStack), - ("Left.extruder.cfg", ExtruderStack), - ("Global.global.cfg", GlobalStack), - ("Global.stack.cfg", GlobalStack) -]) -def test_loadTypes(filename, output_class, container_registry): - #Mock some dependencies. - Resources.getAllResourcesOfType = unittest.mock.MagicMock(return_value = [os.path.join(os.path.dirname(os.path.abspath(__file__)), "stacks", filename)]) #Return just this tested file. - - def findContainers(container_type = 0, id = None): - if id == "some_instance": - return [UM.Settings.ContainerRegistry._EmptyInstanceContainer(id)] - elif id == "some_definition": - return [DefinitionContainer(container_id = id)] - else: - return [] - - container_registry.findContainers = findContainers - - with unittest.mock.patch("cura.Settings.GlobalStack.GlobalStack.findContainer"): - with unittest.mock.patch("os.remove"): - container_registry.load() - - #Check whether the resulting type was correct. - stack_id = filename.split(".")[0] - for container_id, container in container_registry._containers.items(): #Stupid ContainerRegistry class doesn't expose any way of getting at this except by prodding the privates. - if container_id == stack_id: #This is the one we're testing. - assert type(container) == output_class - break - else: - assert False #Container stack with specified ID was not loaded. \ No newline at end of file +# @pytest.mark.parametrize("filename, output_class", [ +# ("ExtruderLegacy.stack.cfg", ExtruderStack), +# ("MachineLegacy.stack.cfg", GlobalStack), +# ("Left.extruder.cfg", ExtruderStack), +# ("Global.global.cfg", GlobalStack), +# ("Global.stack.cfg", GlobalStack) +# ]) +# def test_loadTypes(filename, output_class, container_registry): +# #Mock some dependencies. +# Resources.getAllResourcesOfType = unittest.mock.MagicMock(return_value = [os.path.join(os.path.dirname(os.path.abspath(__file__)), "stacks", filename)]) #Return just this tested file. +# +# def findContainers(container_type = 0, id = None): +# if id == "some_instance": +# return [UM.Settings.ContainerRegistry._EmptyInstanceContainer(id)] +# elif id == "some_definition": +# return [DefinitionContainer(container_id = id)] +# else: +# return [] +# +# container_registry.findContainers = findContainers +# +# with unittest.mock.patch("cura.Settings.GlobalStack.GlobalStack.findContainer"): +# with unittest.mock.patch("os.remove"): +# container_registry.load() +# +# #Check whether the resulting type was correct. +# stack_id = filename.split(".")[0] +# for container_id, container in container_registry._containers.items(): #Stupid ContainerRegistry class doesn't expose any way of getting at this except by prodding the privates. +# if container_id == stack_id: #This is the one we're testing. +# assert type(container) == output_class +# break +# else: +# assert False #Container stack with specified ID was not loaded. \ No newline at end of file diff --git a/tests/Settings/TestExtruderStack.py b/tests/Settings/TestExtruderStack.py index 6ed2c6649b..2a8d19b80f 100644 --- a/tests/Settings/TestExtruderStack.py +++ b/tests/Settings/TestExtruderStack.py @@ -3,7 +3,9 @@ import pytest #This module contains automated tests. import unittest.mock #For the mocking and monkeypatching functionality. +import copy +import cura.CuraApplication import UM.Settings.ContainerRegistry #To create empty instance containers. import UM.Settings.ContainerStack #To set the container registry the container stacks use. from UM.Settings.DefinitionContainer import DefinitionContainer #To check against the class of DefinitionContainer. @@ -12,6 +14,7 @@ import cura.Settings.ExtruderStack #The module we're testing. from cura.Settings.Exceptions import InvalidContainerError, InvalidOperationError #To check whether the correct exceptions are raised. from cura.Settings.ExtruderManager import ExtruderManager +from UM.Settings.ContainerRegistry import ContainerRegistry ## Fake container registry that always provides all containers you ask of. @pytest.yield_fixture() @@ -32,6 +35,7 @@ def container_registry(): ## An empty extruder stack to test with. @pytest.fixture() def extruder_stack() -> cura.Settings.ExtruderStack.ExtruderStack: + creteEmptyContainers() return cura.Settings.ExtruderStack.ExtruderStack("TestStack") ## Gets an instance container with a specified container type. @@ -43,6 +47,31 @@ def getInstanceContainer(container_type) -> InstanceContainer: container.addMetaDataEntry("type", container_type) return container +def creteEmptyContainers(): + empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() + empty_variant_container = copy.deepcopy(empty_container) + empty_variant_container.setMetaDataEntry("id", "empty_variant") + empty_variant_container.addMetaDataEntry("type", "variant") + ContainerRegistry.getInstance().addContainer(empty_variant_container) + + empty_material_container = copy.deepcopy(empty_container) + empty_material_container.setMetaDataEntry("id", "empty_material") + empty_material_container.addMetaDataEntry("type", "material") + ContainerRegistry.getInstance().addContainer(empty_material_container) + + empty_quality_container = copy.deepcopy(empty_container) + empty_quality_container.setMetaDataEntry("id", "empty_quality") + empty_quality_container.setName("Not Supported") + empty_quality_container.addMetaDataEntry("quality_type", "not_supported") + empty_quality_container.addMetaDataEntry("type", "quality") + empty_quality_container.addMetaDataEntry("supported", False) + ContainerRegistry.getInstance().addContainer(empty_quality_container) + + empty_quality_changes_container = copy.deepcopy(empty_container) + empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") + empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") + ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) + class DefinitionContainerSubClass(DefinitionContainer): def __init__(self): super().__init__(container_id = "SubDefinitionContainer") diff --git a/tests/Settings/TestGlobalStack.py b/tests/Settings/TestGlobalStack.py index afd3d2b425..9b0735c8f2 100755 --- a/tests/Settings/TestGlobalStack.py +++ b/tests/Settings/TestGlobalStack.py @@ -3,7 +3,9 @@ import pytest #This module contains unit tests. import unittest.mock #To monkeypatch some mocks in place of dependencies. +import copy +import cura.CuraApplication import cura.Settings.GlobalStack #The module we're testing. import cura.Settings.CuraContainerStack #To get the list of container types. from cura.Settings.Exceptions import TooManyExtrudersError, InvalidContainerError, InvalidOperationError #To test raising these errors. @@ -13,6 +15,7 @@ from UM.Settings.SettingInstance import InstanceState import UM.Settings.ContainerRegistry import UM.Settings.ContainerStack import UM.Settings.SettingDefinition #To add settings to the definition. +from UM.Settings.ContainerRegistry import ContainerRegistry ## Fake container registry that always provides all containers you ask of. @pytest.yield_fixture() @@ -33,6 +36,7 @@ def container_registry(): #An empty global stack to test with. @pytest.fixture() def global_stack() -> cura.Settings.GlobalStack.GlobalStack: + creteEmptyContainers() return cura.Settings.GlobalStack.GlobalStack("TestStack") ## Gets an instance container with a specified container type. @@ -44,6 +48,31 @@ def getInstanceContainer(container_type) -> InstanceContainer: container.addMetaDataEntry("type", container_type) return container +def creteEmptyContainers(): + empty_container = ContainerRegistry.getInstance().getEmptyInstanceContainer() + empty_variant_container = copy.deepcopy(empty_container) + empty_variant_container.setMetaDataEntry("id", "empty_variant") + empty_variant_container.addMetaDataEntry("type", "variant") + ContainerRegistry.getInstance().addContainer(empty_variant_container) + + empty_material_container = copy.deepcopy(empty_container) + empty_material_container.setMetaDataEntry("id", "empty_material") + empty_material_container.addMetaDataEntry("type", "material") + ContainerRegistry.getInstance().addContainer(empty_material_container) + + empty_quality_container = copy.deepcopy(empty_container) + empty_quality_container.setMetaDataEntry("id", "empty_quality") + empty_quality_container.setName("Not Supported") + empty_quality_container.addMetaDataEntry("quality_type", "not_supported") + empty_quality_container.addMetaDataEntry("type", "quality") + empty_quality_container.addMetaDataEntry("supported", False) + ContainerRegistry.getInstance().addContainer(empty_quality_container) + + empty_quality_changes_container = copy.deepcopy(empty_container) + empty_quality_changes_container.setMetaDataEntry("id", "empty_quality_changes") + empty_quality_changes_container.addMetaDataEntry("type", "quality_changes") + ContainerRegistry.getInstance().addContainer(empty_quality_changes_container) + class DefinitionContainerSubClass(DefinitionContainer): def __init__(self): super().__init__(container_id = "SubDefinitionContainer") From 79028388a28c54320b2fa334477db802f5689494 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 15 Dec 2017 11:05:42 +0100 Subject: [PATCH 50/74] Add option for custom reset handler in setting item --- resources/qml/Settings/SettingItem.qml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 6234e5f1f7..6899d20678 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -179,8 +179,13 @@ Item { iconSource: UM.Theme.getIcon("reset") onClicked: { - revertButton.focus = true; - Cura.MachineManager.clearUserSettingAllCurrentStacks(propertyProvider.key); + revertButton.focus = true + + if (resetHandler) { + resetHandler(propertyProvider.key) + } else { + Cura.MachineManager.clearUserSettingAllCurrentStacks(propertyProvider.key) + } } onEntered: { hoverTimer.stop(); base.showTooltip(catalog.i18nc("@label", "This setting has a value that is different from the profile.\n\nClick to restore the value of the profile.")) } From 876ad0159731ad0e347293fba85198534766ced4 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 15 Dec 2017 13:32:45 +0100 Subject: [PATCH 51/74] Directly use CuraApplication.backend instead of via property --- resources/qml/SaveButton.qml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index 2b938c1745..c5025dea78 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -14,7 +14,6 @@ Item { property real progress: UM.Backend.progress property int backendState: UM.Backend.state - property var backend: CuraApplication.backend property bool activity: CuraApplication.platformActivity property alias buttonRowWidth: saveRow.width @@ -50,12 +49,10 @@ Item { function sliceOrStopSlicing() { try { - if (base.backendState != "undefined" && base.backend != "undefined") { - if ([1, 5].indexOf(base.backendState) != -1) { - backend.forceSlice(); - } else { - backend.stopSlicing(); - } + if ([1, 5].indexOf(base.backendState) != -1) { + CuraApplication.backend.forceSlice(); + } else { + CuraApplication.backend.stopSlicing(); } } catch (e) { console.log('Could not start or stop slicing', e) From 57651e837fd549c6531416450113a9addb43aab2 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 15 Dec 2017 14:17:18 +0100 Subject: [PATCH 52/74] Fix setting the right extruder temperatures in start and end gcode --- plugins/CuraEngineBackend/StartSliceJob.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 3c1998094c..efa0e87b9e 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -218,7 +218,7 @@ class StartSliceJob(Job): result[key] = stack.getProperty(key, "value") Job.yieldThread() - result["print_bed_temperature"] = result["material_bed_temperature"] #Renamed settings. + result["print_bed_temperature"] = result["material_bed_temperature"] # Renamed settings. result["print_temperature"] = result["material_print_temperature"] result["time"] = time.strftime("%H:%M:%S") #Some extra settings. result["date"] = time.strftime("%d-%m-%Y") @@ -246,10 +246,10 @@ class StartSliceJob(Job): settings = self._buildReplacementTokens(stack) - #Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it. + # Also send the material GUID. This is a setting in fdmprinter, but we have no interface for it. settings["material_guid"] = stack.material.getMetaDataEntry("GUID", "") - #Replace the setting tokens in start and end g-code. + # Replace the setting tokens in start and end g-code. settings["machine_extruder_start_code"] = self._expandGcodeTokens(settings["machine_extruder_start_code"], settings) settings["machine_extruder_end_code"] = self._expandGcodeTokens(settings["machine_extruder_end_code"], settings) @@ -269,18 +269,23 @@ class StartSliceJob(Job): def _buildGlobalSettingsMessage(self, stack): settings = self._buildReplacementTokens(stack) + # Pre-compute material material_bed_temp_prepend and material_print_temp_prepend start_gcode = settings["machine_start_gcode"] - #Pre-compute material material_bed_temp_prepend and material_print_temp_prepend bed_temperature_settings = {"material_bed_temperature", "material_bed_temperature_layer_0"} settings["material_bed_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in bed_temperature_settings)) print_temperature_settings = {"material_print_temperature", "material_print_temperature_layer_0", "default_material_print_temperature", "material_initial_print_temperature", "material_final_print_temperature", "material_standby_temperature"} settings["material_print_temp_prepend"] = all(("{" + setting + "}" not in start_gcode for setting in print_temperature_settings)) - #Replace the setting tokens in start and end g-code. - settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], settings) - settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], settings) + # Find the correct temperatures from the first used extruder + extruder_stack = Application.getInstance().getExtruderManager().getUsedExtruderStacks()[0] + extruder_0_settings = self._buildReplacementTokens(extruder_stack) - for key, value in settings.items(): #Add all submessages for each individual setting. + # Replace the setting tokens in start and end g-code. + settings["machine_start_gcode"] = self._expandGcodeTokens(settings["machine_start_gcode"], extruder_0_settings) + settings["machine_end_gcode"] = self._expandGcodeTokens(settings["machine_end_gcode"], extruder_0_settings) + + # Add all sub-messages for each individual setting. + for key, value in settings.items(): setting_message = self._slice_message.getMessage("global_settings").addRepeatedMessage("settings") setting_message.name = key setting_message.value = str(value).encode("utf-8") From f26872ec1f6b1a4a6fa0f71e307a96e3b956845c Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 15 Dec 2017 14:45:06 +0100 Subject: [PATCH 53/74] Apply fix for single extrusion machines when a new global stack is added CURA-4713 Now the machines are not all loaded in the beginning, so the old way of adding extruder stacks for old single-extrusion machines don't work. With this fix, it now happens whenever a global stack is added to the registry. --- cura/Settings/CuraContainerRegistry.py | 22 ++++++++++++++++++++-- cura/Settings/MachineManager.py | 4 +++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 07eb357f39..dc1cc726c4 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -36,6 +36,11 @@ class CuraContainerRegistry(ContainerRegistry): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + # We don't have all the machines loaded in the beginning, so in order to add the missing extruder stack + # for single extrusion machines, we subscribe to the containerAdded signal, and whenever a global stack + # is added, we check to see if an extruder stack needs to be added. + self.containerAdded.connect(self._onContainerAdded) + ## Overridden from ContainerRegistry # # Adds a container to the registry. @@ -410,6 +415,17 @@ class CuraContainerRegistry(ContainerRegistry): if not extruder_stacks: self.addExtruderStackForSingleExtrusionMachine(machine, "fdmextruder") + def _onContainerAdded(self, container): + # We don't have all the machines loaded in the beginning, so in order to add the missing extruder stack + # for single extrusion machines, we subscribe to the containerAdded signal, and whenever a global stack + # is added, we check to see if an extruder stack needs to be added. + if not isinstance(container, ContainerStack) or container.getMetaDataEntry("type") != "machine": + return + + extruder_stacks = self.findContainerStacks(type = "extruder_train", machine = container.getId()) + if not extruder_stacks: + self.addExtruderStackForSingleExtrusionMachine(container, "fdmextruder") + def addExtruderStackForSingleExtrusionMachine(self, machine, extruder_id): new_extruder_id = extruder_id @@ -425,7 +441,6 @@ class CuraContainerRegistry(ContainerRegistry): extruder_stack.setName(extruder_definition.getName()) extruder_stack.setDefinition(extruder_definition) extruder_stack.addMetaDataEntry("position", extruder_definition.getMetaDataEntry("position")) - extruder_stack.setNextStack(machine) # create empty user changes container otherwise user_container = InstanceContainer(extruder_stack.id + "_user") @@ -444,8 +459,8 @@ class CuraContainerRegistry(ContainerRegistry): user_container.addInstance(machine.userChanges.getInstance(user_setting_key)) machine.userChanges.removeInstance(user_setting_key, postpone_emit = True) - extruder_stack.setUserChanges(user_container) self.addContainer(user_container) + extruder_stack.setUserChanges(user_container) variant_id = "default" if machine.variant.getId() not in ("empty", "empty_variant"): @@ -491,6 +506,9 @@ class CuraContainerRegistry(ContainerRegistry): self.addContainer(extruder_stack) + # Set next stack at the end + extruder_stack.setNextStack(machine) + return extruder_stack def _findQualityChangesContainerInCuraFolder(self, name): diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7c0adb5043..05aed1f5e2 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -369,7 +369,9 @@ class MachineManager(QObject): self.blurSettings.emit() # Ensure no-one has focus. self._cancelDelayedActiveContainerStackChanges() - containers = ContainerRegistry.getInstance().findContainerStacks(id = stack_id) + container_registry = ContainerRegistry.getInstance() + + containers = container_registry.findContainerStacks(id = stack_id) if containers: Application.getInstance().setGlobalContainerStack(containers[0]) From 248fe37ed92450f374c230c1bc8e78dcaa7293f7 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 15 Dec 2017 14:54:23 +0100 Subject: [PATCH 54/74] setDefinition() takes the ID instead of the container CURA-4713 --- cura/Settings/CuraContainerRegistry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index dc1cc726c4..43e2e072b0 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -448,7 +448,7 @@ class CuraContainerRegistry(ContainerRegistry): user_container.addMetaDataEntry("machine", extruder_stack.getId()) from cura.CuraApplication import CuraApplication user_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) - user_container.setDefinition(machine.definition) + user_container.setDefinition(machine.definition.getId()) if machine.userChanges: # for the newly created extruder stack, we need to move all "per-extruder" settings to the user changes From 421d93baa36f0eea332c29b70a5a451f7bba3ad0 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Fri, 15 Dec 2017 16:30:38 +0100 Subject: [PATCH 55/74] Fix potential crash on missing index in extruder dict --- plugins/SliceInfoPlugin/SliceInfo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 67f977adce..508d174cf2 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -99,7 +99,9 @@ class SliceInfo(Extension): "type": extruder.material.getMetaData().get("material", ""), "brand": extruder.material.getMetaData().get("brand", "") } - extruder_dict["material_used"] = print_information.materialLengths[int(extruder.getMetaDataEntry("position", "0"))] + extruder_position = int(extruder.getMetaDataEntry("position", "0")) + if extruder_position in print_information.materialLengths: + extruder_dict["material_used"] = print_information.materialLengths[extruder_position] extruder_dict["variant"] = extruder.variant.getName() extruder_dict["nozzle_size"] = extruder.getProperty("machine_nozzle_size", "value") From 3bef7dd9b179a12ab17d479acdbdf5fb97c5fac6 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 15 Dec 2017 16:32:41 +0100 Subject: [PATCH 56/74] CURA-4716 Add Fine quality profile for Breakaway AA0.4 in UM3 --- .../um3_aa0.4_BAM_Normal_Quality.inst.cfg | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg diff --git a/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..5f69e43e2f --- /dev/null +++ b/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg @@ -0,0 +1,35 @@ +[general] +version = 2 +name = Fine +definition = ultimaker3 + +[metadata] +type = quality +quality_type = normal +material = generic_bam_ultimaker3_AA_0.4 +weight = 0 +setting_version = 4 + +[values] +cool_fan_full_at_height = =layer_height_0 + 2 * layer_height +cool_fan_speed_max = =cool_fan_speed +cool_min_speed = 7 +machine_nozzle_cool_down_speed = 0.75 +machine_nozzle_heat_up_speed = 1.6 +material_print_temperature = =default_material_print_temperature - 10 +# prime_tower_enable: see CURA-4248 +prime_tower_enable = =min(extruderValues('material_surface_energy')) < 100 +skin_overlap = 10 +speed_layer_0 = 20 +support_interface_enable = True +support_interface_density = =min(extruderValues('material_surface_energy')) +support_interface_pattern = ='lines' if support_interface_density < 100 else 'concentric' +support_top_distance = =math.ceil(min(extruderValues('material_adhesion_tendency')) / 1) * layer_height +support_bottom_distance = =math.ceil(min(extruderValues('material_adhesion_tendency')) / 2) * layer_height +support_angle = 45 +support_join_distance = 5 +support_offset = 2 +support_pattern = triangles +support_infill_rate = 10 +top_bottom_thickness = 1 +wall_thickness = 1 From 54bc7dd348d77efa7f2dc3f420200df9864b8d37 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Fri, 15 Dec 2017 18:13:29 +0100 Subject: [PATCH 57/74] Version upgrade for nozzle_size CURA-4708 --- .../VersionUpgrade30to31.py | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py index 8c5a160ff4..c01ff158b1 100644 --- a/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py +++ b/plugins/VersionUpgrade/VersionUpgrade30to31/VersionUpgrade30to31.py @@ -122,6 +122,21 @@ class VersionUpgrade30to31(VersionUpgrade): if len(all_quality_changes) <= 1 and not parser.has_option("metadata", "extruder"): self._createExtruderQualityChangesForSingleExtrusionMachine(filename, parser) + if parser["metadata"]["type"] == "definition_changes": + if parser["general"]["definition"] == "custom": + + # We are only interested in machine_nozzle_size + if parser.has_option("values", "machine_nozzle_size"): + machine_nozzle_size = parser["values"]["machine_nozzle_size"] + + definition_name = parser["general"]["name"] + machine_extruders = self._getSingleExtrusionMachineExtruders(definition_name) + + #For single extuder machine we nee only first extruder + if len(machine_extruders) !=0: + if self._updateSingleExtuderDefinitionFile(machine_extruders, machine_nozzle_size): + parser.remove_option("values", "machine_nozzle_size") + # Update version numbers parser["general"]["version"] = "2" parser["metadata"]["setting_version"] = "4" @@ -200,6 +215,133 @@ class VersionUpgrade30to31(VersionUpgrade): return quality_changes_containers + def _getSingleExtrusionMachineExtruders(self, definition_name): + + machine_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.MachineStack) + + machine_instances = [] + + #Find all machine instances + for item in os.listdir(machine_instances_dir): + file_path = os.path.join(machine_instances_dir, item) + if not os.path.isfile(file_path): + continue + + parser = configparser.ConfigParser(interpolation=None) + try: + parser.read([file_path]) + except: + # skip, it is not a valid stack file + continue + + if not parser.has_option("metadata", "type"): + continue + if "machine" != parser["metadata"]["type"]: + continue + + if not parser.has_option("general", "id"): + continue + + machine_instances.append(parser) + + #Find for extruders + extruders_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack) + #"machine",[extruders] + extruder_instances_per_machine = {} + + #Find all custom extruders for founded machines + for item in os.listdir(extruders_instances_dir): + file_path = os.path.join(extruders_instances_dir, item) + if not os.path.isfile(file_path): + continue + + parser = configparser.ConfigParser(interpolation=None) + try: + parser.read([file_path]) + except: + # skip, it is not a valid stack file + continue + + if not parser.has_option("metadata", "type"): + continue + if "extruder_train" != parser["metadata"]["type"]: + continue + + if not parser.has_option("metadata", "machine"): + continue + if not parser.has_option("metadata", "position"): + continue + + + for machine_instace in machine_instances: + + machine_id = machine_instace["general"]["id"] + if machine_id != parser["metadata"]["machine"]: + continue + + if machine_id + "_settings" != definition_name: + continue + + if extruder_instances_per_machine.get(machine_id) is None: + extruder_instances_per_machine.update({machine_id:[]}) + + extruder_instances_per_machine.get(machine_id).append(parser) + #the extruder can be related only to one machine + break + + return extruder_instances_per_machine + + #Find extruder defition at index 0 and update its values + def _updateSingleExtuderDefinitionFile(self, extruder_instances_per_machine, machine_nozzle_size): + + defintion_instances_dir = Resources.getPath(CuraApplication.ResourceTypes.DefinitionChangesContainer) + + for item in os.listdir(defintion_instances_dir): + file_path = os.path.join(defintion_instances_dir, item) + if not os.path.isfile(file_path): + continue + + parser = configparser.ConfigParser(interpolation=None) + try: + parser.read([file_path]) + except: + # skip, it is not a valid stack file + continue + + if not parser.has_option("general", "name"): + continue + name = parser["general"]["name"] + custom_extruder_at_0_position = None + for machine_extruders in extruder_instances_per_machine: + for extruder_instance in extruder_instances_per_machine[machine_extruders]: + + if extruder_instance["general"]["id"] + "_settings" == name: + defition_position = extruder_instance["metadata"]["position"] + + if defition_position == "0": + custom_extruder_at_0_position = extruder_instance + break + if custom_extruder_at_0_position is not None: + break + + #If not null, then parsed file is for first extuder and then can be updated. I need to update only + # first, because this update for single extuder machine + if custom_extruder_at_0_position is not None: + + #Add new value + parser["values"]["machine_nozzle_size"] = machine_nozzle_size + + definition_output = io.StringIO() + parser.write(definition_output) + + with open(file_path, "w") as f: + f.write(definition_output.getvalue()) + + return True + + return False + + def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes): suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower()) machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "") From 43db06db2de1d886654b4271ea902ec8a1341531 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 18 Dec 2017 09:39:20 +0100 Subject: [PATCH 58/74] CURA-4721 removed comment from breakaway 0.1mm quality profile --- .../quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg b/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg index 5f69e43e2f..3ced3a0417 100644 --- a/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg +++ b/resources/quality/ultimaker3/um3_aa0.4_BAM_Normal_Quality.inst.cfg @@ -17,7 +17,6 @@ cool_min_speed = 7 machine_nozzle_cool_down_speed = 0.75 machine_nozzle_heat_up_speed = 1.6 material_print_temperature = =default_material_print_temperature - 10 -# prime_tower_enable: see CURA-4248 prime_tower_enable = =min(extruderValues('material_surface_energy')) < 100 skin_overlap = 10 speed_layer_0 = 20 From c3ce3724e5fa0625c87b60c39c033fff79ad3efa Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 18 Dec 2017 10:00:08 +0100 Subject: [PATCH 59/74] Fix small issue when resetHandler is not defined --- resources/qml/Settings/SettingItem.qml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index 6899d20678..dd15877f48 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -14,11 +14,13 @@ import "." Item { id: base; - height: UM.Theme.getSize("section").height; + height: UM.Theme.getSize("section").height - property alias contents: controlContainer.children; + property alias contents: controlContainer.children property alias hovered: mouse.containsMouse + property var resetHandler: false + property var showRevertButton: true property var showInheritButton: true property var showLinkedSettingIcon: true From 443e155cf7b37cd8a0a222b5019c7c6c7de97eee Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 10:50:50 +0100 Subject: [PATCH 60/74] Adding set stage back --- cura/CuraApplication.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 62ece1ef1e..987bb98acb 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -687,6 +687,7 @@ class CuraApplication(QtApplication): run_without_gui = self.getCommandLineOption("headless", False) or self.getCommandLineOption("invisible", False) if not run_without_gui: self.initializeEngine() + controller.setActiveStage("PrepareStage") if run_without_gui or self._engine.rootObjects: self.closeSplash() From d5b3f18da8b96bc46779abb8d04f6a85a024780e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 18 Dec 2017 11:00:55 +0100 Subject: [PATCH 61/74] Split all non-word characters for making abbreviations So now cases like CR-10 are more appropriately split into ['CR', '10']. Fixes #2910. --- cura/PrintInformation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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: From e3a996073e6414eae43e446d69fb4bb218b2e80b Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 11:09:41 +0100 Subject: [PATCH 62/74] Remove duplicate --headless argument as it is now in Uranium --- cura/CuraApplication.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 987bb98acb..18d1bde57e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -519,7 +519,6 @@ class CuraApplication(QtApplication): 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): From 4a211c6ac6b2e49e76b4e568fda7d0df73910367 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 18 Dec 2017 11:58:34 +0100 Subject: [PATCH 63/74] CURA-4495 Change property name and add default values --- plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 1 + resources/qml/Settings/SettingItem.qml | 6 ++---- resources/qml/Settings/SettingView.qml | 1 + 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 65b67791c7..ea126bfd44 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -145,6 +145,7 @@ Item { property var settingDefinitionsModel: addedSettingsModel property var propertyProvider: provider property var globalPropertyProvider: inheritStackProvider + property var externalResetHandler: false //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989 //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes, diff --git a/resources/qml/Settings/SettingItem.qml b/resources/qml/Settings/SettingItem.qml index dd15877f48..1fa83cb6d4 100644 --- a/resources/qml/Settings/SettingItem.qml +++ b/resources/qml/Settings/SettingItem.qml @@ -19,8 +19,6 @@ Item { property alias contents: controlContainer.children property alias hovered: mouse.containsMouse - property var resetHandler: false - property var showRevertButton: true property var showInheritButton: true property var showLinkedSettingIcon: true @@ -183,8 +181,8 @@ Item { onClicked: { revertButton.focus = true - if (resetHandler) { - resetHandler(propertyProvider.key) + if (externalResetHandler) { + externalResetHandler(propertyProvider.key) } else { Cura.MachineManager.clearUserSettingAllCurrentStacks(propertyProvider.key) } diff --git a/resources/qml/Settings/SettingView.qml b/resources/qml/Settings/SettingView.qml index 1ebb5cc40e..5d39572647 100644 --- a/resources/qml/Settings/SettingView.qml +++ b/resources/qml/Settings/SettingView.qml @@ -287,6 +287,7 @@ Item property var settingDefinitionsModel: definitionsModel property var propertyProvider: provider property var globalPropertyProvider: inheritStackProvider + property var externalResetHandler: false //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989 //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes, From d839b62e4211f72a1e432427d103a1efbffb571d Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Dec 2017 11:58:28 +0100 Subject: [PATCH 64/74] Prevent CrashHandler creating a QWidget before QApplication is created --- cura/CrashHandler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index 81eca67a46..5e4b409939 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -53,7 +53,7 @@ class CrashHandler: self.exception_type = exception_type self.value = value self.traceback = tb - self.dialog = QDialog() + self.dialog = None # Don't create a QDialog before there is a QApplication # While we create the GUI, the information will be stored for sending afterwards self.data = dict() @@ -71,6 +71,7 @@ class CrashHandler: if not application: sys.exit(1) + self.dialog = QDialog() self._createDialog() ## Creates a modal dialog. From 77daad1f981c978c1ee61aba0052cfc0967cc351 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Mon, 18 Dec 2017 12:19:56 +0100 Subject: [PATCH 65/74] Also exit when the crash handler dialog is not created --- cura/CrashHandler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index 5e4b409939..b5d4001fe2 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -37,7 +37,7 @@ else: # List of exceptions that should be considered "fatal" and abort the program. # These are primarily some exception types that we simply cannot really recover from # (MemoryError and SystemError) and exceptions that indicate grave errors in the -# code that cause the Python interpreter to fail (SyntaxError, ImportError). +# code that cause the Python interpreter to fail (SyntaxError, ImportError). fatal_exception_types = [ MemoryError, SyntaxError, @@ -289,4 +289,4 @@ class CrashHandler: # When the exception is not in the fatal_exception_types list, the dialog is not created, so we don't need to show it if self.dialog: self.dialog.exec_() - os._exit(1) + os._exit(1) From 8f66db6565e891f7e29f4d528d005dc88fc1916b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 18 Dec 2017 13:29:10 +0100 Subject: [PATCH 66/74] Remove overzealeous log message This message appears on every machine in every material, which is far too much. --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index c31a60c778..125fe1e344 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -737,7 +737,6 @@ class XmlMaterialProfile(InstanceContainer): Logger.log("w", "No definition found for machine ID %s", machine_id) continue - Logger.log("d", "Found def for machine [%s]", machine_id) definition_metadata = definition_metadata[0] machine_manufacturer = identifier.get("manufacturer", definition_metadata.get("manufacturer", "Unknown")) #If the XML material doesn't specify a manufacturer, use the one in the actual printer definition. From d6c6aa1c7197775d51292d3c746369875b41e983 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 18 Dec 2017 17:03:18 +0100 Subject: [PATCH 67/74] CURA-4715 fix updating custom profile --- cura/Settings/ContainerManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index bbabdadbde..209e1ec8fd 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -514,7 +514,7 @@ class ContainerManager(QObject): for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): # Find the quality_changes container for this stack and merge the contents of the top container into it. quality_changes = stack.qualityChanges - if not quality_changes or quality_changes.isReadOnly(): + if not quality_changes or self._container_registry.isReadOnly(quality_changes.getId()): Logger.log("e", "Could not update quality of a nonexistant or read only quality profile in stack %s", stack.getId()) continue @@ -687,7 +687,7 @@ class ContainerManager(QObject): global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack or not quality_name: return "" - machine_definition = global_stack.getBottom() + machine_definition = global_stack.definition active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() if active_stacks is None: From cab27711ad94a3ce0e8b9a3239d24757349c49d5 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 20:50:45 +0100 Subject: [PATCH 68/74] Cleanup readme Cleanup readme now that we have better Wiki content --- README.md | 55 +++++++++++++------------------------------------------ 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 90f17a5463..a94ca853e6 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,16 @@ Cura ==== - -This is the new, shiny frontend for Cura. [daid/Cura](https://github.com/daid/Cura.git) is the old legacy Cura that everyone knows and loves/hates. - -We re-worked the whole GUI code at Ultimaker, because the old code started to become unmaintainable. - +This is the new, shiny frontend for Cura. [daid/Cura](https://github.com/daid/Cura.git) is the old legacy Cura that everyone knows and loves/hates. We re-worked the whole GUI code at Ultimaker, because the old code started to become unmaintainable. Logging Issues ------------ -Use [this](https://github.com/Ultimaker/Uranium/wiki/Bug-Reporting-Template) template to report issues. New issues that do not adhere to this template will take us a lot longer to handle and will therefore have a lower pirority. - For crashes and similar issues, please attach the following information: * (On Windows) The log as produced by dxdiag (start -> run -> dxdiag -> save output) * The Cura GUI log file, located at - * %APPDATA%\cura\\``\cura.log (Windows), or usually C:\Users\\``\AppData\Roaming\cura\\``\cura.log - * $User/Library/Application Support/cura/``/cura.log (OSX) - * $USER/.local/share/cura/``/cura.log (Ubuntu/Linux) + * `%APPDATA%\cura\\cura.log` (Windows), or usually `C:\Users\\\AppData\Roaming\cura\\cura.log` + * `$USER/Library/Application Support/cura//cura.log` (OSX) + * `$USER/.local/share/cura//cura.log` (Ubuntu/Linux) If the Cura user interface still starts, you can also reach this directory from the application menu in Help -> Show settings folder @@ -24,15 +18,10 @@ For additional support, you could also ask in the #cura channel on FreeNode IRC. Dependencies ------------ - -* [Uranium](https://github.com/Ultimaker/Uranium) - Cura is built on top of the Uranium framework. -* [CuraEngine](https://github.com/Ultimaker/CuraEngine) - This will be needed at runtime to perform the actual slicing. -* [PySerial](https://github.com/pyserial/pyserial) - Only required for USB printing support. -* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) - Only required to detect mDNS-enabled printers +* [Uranium](https://github.com/Ultimaker/Uranium) Cura is built on top of the Uranium framework. +* [CuraEngine](https://github.com/Ultimaker/CuraEngine) This will be needed at runtime to perform the actual slicing. +* [PySerial](https://github.com/pyserial/pyserial) Only required for USB printing support. +* [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers Configuring Cura ---------------- @@ -44,33 +33,15 @@ location = /[path_to_the..]/CuraEngine/build/CuraEngine Build scripts ------------- - Please checkout [cura-build](https://github.com/Ultimaker/cura-build) -Third party plugins +Plugins ------------- -* [Post Processing Plugin](https://github.com/nallath/PostProcessingPlugin): Allows for post-processing scripts to run on g-code. -* [Barbarian Plugin](https://github.com/nallath/BarbarianPlugin): Simple scale tool for imperial to metric. -* [X3G Writer](https://github.com/Ghostkeeper/X3GWriter): Adds support for exporting X3G files. -* [Auto orientation](https://github.com/nallath/CuraOrientationPlugin): Calculate the optimal orientation for a model. -* [OctoPrint Plugin](https://github.com/fieldofview/OctoPrintPlugin): Send printjobs directly to OctoPrint and monitor their progress in Cura. -* [Electric Print Cost Calculator Plugin](https://github.com/zoff99/ElectricPrintCostCalculator): Calculate the electric costs of a print. +Please check our [Wiki](https://github.com/Ultimaker/Cura/wiki/Plugin-Directory) for details about creating and using plugins. -Making profiles for other printers ----------------------------------- -If your make of printer is not in the list of supported printers, and using the "Custom FDM Printer" does not offer enough flexibility, you can use [this](https://github.com/Ultimaker/Cura/blob/master/resources/definitions/ultimaker_original.def.json) as a template. - -* Change the machine ID to something unique -* Change the machine_name to your printer's name -* If you have a 3D model of your platform you can put it in resources/meshes and put its name under platform -* Set your machine's dimensions with machine_width, machine_depth, and machine_height -* If your printer's origin is in the center of the bed, set machine_center_is_zero to true. -* Set your print head dimensions with the machine_head_shape parameters -* Set the start and end gcode in machine_start_gcode and machine_end_gcode - -Once you are done, put the profile you have made into resources/definitions, or in definitions in your cura profile folder. - -If you want to make a definition for a multi-extrusion printer, have a look at [this](https://github.com/Ultimaker/Cura/blob/master/resources/definitions/ultimaker_original_dual.def.json) as a template, along with the two extruder definitions it references [here](https://github.com/Ultimaker/Cura/blob/master/resources/extruders/ultimaker_original_dual_1st.def.json) and [here](https://github.com/Ultimaker/Cura/blob/master/resources/extruders/ultimaker_original_dual_2nd.def.json) +Supported printers +------------- +Please check our [Wiki](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura/_edit) for guidelines about adding support for new machines. Translating Cura ---------------- From 16ce1e870e782e974c94255967131895d0c64a9c Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 20:57:43 +0100 Subject: [PATCH 69/74] Create GitHub issue template Might help streamlining issue creation and handling. --- .github/ISSUE_TEMPLATE.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..7bdf35455c --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,32 @@ + + +Application Version: + + +Platform: + + +Qt: + + +PyQt: + + +Display Driver: + + +Steps to Reproduce: + + +Actual Results: + + +Expected results: + + +Additional Information: + From 06512e53acf1d2d2c587098fa0c315bc1d459987 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 21:16:11 +0100 Subject: [PATCH 70/74] Move configuration options info to a wiki page As all other info was there already. --- README.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a94ca853e6..e620e6dd6f 100644 --- a/README.md +++ b/README.md @@ -23,25 +23,21 @@ Dependencies * [PySerial](https://github.com/pyserial/pyserial) Only required for USB printing support. * [python-zeroconf](https://github.com/jstasiak/python-zeroconf) Only required to detect mDNS-enabled printers -Configuring Cura ----------------- -Link your CuraEngine backend by inserting the following lines in `$HOME/.config/cura/config.cfg` : -``` -[backend] -location = /[path_to_the..]/CuraEngine/build/CuraEngine -``` - Build scripts ------------- -Please checkout [cura-build](https://github.com/Ultimaker/cura-build) +Please checkout [cura-build](https://github.com/Ultimaker/cura-build) for detailed building instructions. Plugins ------------- -Please check our [Wiki](https://github.com/Ultimaker/Cura/wiki/Plugin-Directory) for details about creating and using plugins. +Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Plugin-Directory) for details about creating and using plugins. Supported printers ------------- -Please check our [Wiki](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura/_edit) for guidelines about adding support for new machines. +Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura/_edit) for guidelines about adding support for new machines. + +Configuring Cura +---------------- +Please check out [Wiki page](https://github.com/Ultimaker/Cura/wiki/Cura-Settings) about configuration options for developers. Translating Cura ---------------- From 80880a871f956e00076c20aac6f52d5fdf1b2803 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 21:17:37 +0100 Subject: [PATCH 71/74] Fixed legacy cura repo link. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e620e6dd6f..80f4968cdd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Cura ==== -This is the new, shiny frontend for Cura. [daid/Cura](https://github.com/daid/Cura.git) is the old legacy Cura that everyone knows and loves/hates. We re-worked the whole GUI code at Ultimaker, because the old code started to become unmaintainable. +This is the new, shiny frontend for Cura. Check [daid/LegacyCura](https://github.com/daid/LegacyCura) for the legacy Cura that everyone knows and loves/hates. We re-worked the whole GUI code at Ultimaker, because the old code started to become unmaintainable. Logging Issues ------------ From c58b11611152ba2ffa4622c8635379652c689ef9 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 21:22:42 +0100 Subject: [PATCH 72/74] Added a license reference to the readme As is custom on most GitHub repositories. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 80f4968cdd..363ff52876 100644 --- a/README.md +++ b/README.md @@ -60,3 +60,7 @@ To submit your translation, ideally you would make two pull requests where all ` After the translation is submitted, the Cura maintainers will check for its completeness and check whether it is consistent. We will take special care to look for common mistakes, such as translating mark-up `` code and such. We are often not fluent in every language, so we expect the translator and the international users to make corrections where necessary. Of course, there will always be some mistakes in every translation. When the next Cura release comes around, some of the texts will have changed and some new texts will have been added. Around the time when the beta is released we will invoke a string freeze, meaning that no developer is allowed to make changes to the texts. Then we will update the translation template `.pot` files and ask all our translators to update their translations. If you are unable to update the translation in time for the actual release, we will remove the language from the drop-down menu in the Preferences window. The translation stays in Cura however, so that someone might pick it up again later and update it with the newest texts. Also, users who had previously selected the language can still continue Cura in their language but English text will appear among the original text. + +License +---------------- +Cura is released under the terms of the LGPLv3 or higher. A copy of this license should be included with the software. From 47822148937705af14cccac049f1791119ccb11e Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Mon, 18 Dec 2017 23:18:22 +0100 Subject: [PATCH 73/74] Fix adding printer support wiki link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 363ff52876..6ea839a300 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Plugin-Direc Supported printers ------------- -Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura/_edit) for guidelines about adding support for new machines. +Please check our [Wiki page](https://github.com/Ultimaker/Cura/wiki/Adding-new-machine-profiles-to-Cura) for guidelines about adding support for new machines. Configuring Cura ---------------- From 7a3d05ae8a96976d8acc94d81a56e3c1cf966b21 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 19 Dec 2017 09:20:53 +0100 Subject: [PATCH 74/74] Ignore new plugins --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8d9ba4b2d2..88c4d5b6eb 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ plugins/CuraVariSlicePlugin plugins/CuraLiveScriptingPlugin plugins/CuraPrintProfileCreator plugins/OctoPrintPlugin +plugins/CuraCloudPlugin #Build stuff CMakeCache.txt