From 2df0d96923f3e701f29beda532676cbc28dbd7e9 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Tue, 1 Oct 2019 11:54:53 +0200 Subject: [PATCH 1/8] Consider user preference when opening project files from cli. The logic using just a "skip_project_file_check" boolean was too obscure imho, so used a string value with more explicit values to improve readability CURA-6824 --- cura/CuraApplication.py | 24 ++++++++++++++++--- cura/SingleInstance.py | 2 +- .../AskOpenAsProjectOrModelsDialog.qml | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index c8faae3704..899a00efbd 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1600,8 +1600,11 @@ class CuraApplication(QtApplication): openProjectFile = pyqtSignal(QUrl, arguments = ["project_file"]) # Emitted when a project file is about to open. - @pyqtSlot(QUrl, bool) - def readLocalFile(self, file, skip_project_file_check = False): + @pyqtSlot(QUrl, str) + ## Open a local file + # \param force_project_mode \type{str} Either "open_as_model" or "open_as_project". This parameter is only + # considered if the file is a project file. + def readLocalFile(self, file, force_project_mode = None): if not file.isValid(): return @@ -1612,10 +1615,25 @@ class CuraApplication(QtApplication): self.deleteAll() break - if not skip_project_file_check and self.checkIsValidProjectFile(file): + is_project_file = self.checkIsValidProjectFile(file) + project_mode = force_project_mode + + if project_mode is None: + project_mode = self.getPreferences().getValue("cura/choice_on_open_project") + + if is_project_file and project_mode == "open_as_project": + # open as project immediately without presenting a dialog + workspace_handler = self.getWorkspaceFileHandler() + workspace_handler.readLocalFile(file) + return + + if is_project_file and project_mode == "always_ask": + # present a dialog asking to open as project or import models self.callLater(self.openProjectFile.emit, file) return + # Either the file is a model file or we want to load only models from project. Continue to load models. + if self.getPreferences().getValue("cura/select_models_on_load"): Selection.clear() diff --git a/cura/SingleInstance.py b/cura/SingleInstance.py index cf07b143c6..6fcf0da6cf 100644 --- a/cura/SingleInstance.py +++ b/cura/SingleInstance.py @@ -87,7 +87,7 @@ class SingleInstance: if command == "clear-all": self._application.callLater(lambda: self._application.deleteAll()) - # Command: Load a model file + # Command: Load a model or project file elif command == "open": self._application.callLater(lambda f = payload["filePath"]: self._application._openFile(f)) diff --git a/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml b/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml index f6436f62c5..2566a2d44c 100644 --- a/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml +++ b/resources/qml/Dialogs/AskOpenAsProjectOrModelsDialog.qml @@ -53,7 +53,7 @@ UM.Dialog UM.Preferences.setValue("cura/choice_on_open_project", "open_as_model") } - CuraApplication.readLocalFile(base.fileUrl, true) + CuraApplication.readLocalFile(base.fileUrl, "open_as_model") var meshName = backgroundItem.getMeshName(base.fileUrl.toString()) backgroundItem.hasMesh(decodeURIComponent(meshName)) From 55fe4ee986ec235cb26e6ef9343d0a2023f8a83f Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Wed, 2 Oct 2019 13:30:59 +0200 Subject: [PATCH 2/8] Update documentation and typing CURA-6824 --- cura/CuraApplication.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 899a00efbd..93695b1d63 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1602,9 +1602,9 @@ class CuraApplication(QtApplication): @pyqtSlot(QUrl, str) ## Open a local file - # \param force_project_mode \type{str} Either "open_as_model" or "open_as_project". This parameter is only - # considered if the file is a project file. - def readLocalFile(self, file, force_project_mode = None): + # \param project_mode How to handle project files. Either None(default): Follow user preference, "open_as_model" or + # "open_as_project". This parameter is only considered if the file is a project file. + def readLocalFile(self, file: QUrl, project_mode: Optional[str] = None): if not file.isValid(): return @@ -1616,7 +1616,6 @@ class CuraApplication(QtApplication): break is_project_file = self.checkIsValidProjectFile(file) - project_mode = force_project_mode if project_mode is None: project_mode = self.getPreferences().getValue("cura/choice_on_open_project") From 11d0462c7af77281dd02106c46fb229d24626337 Mon Sep 17 00:00:00 2001 From: Nino van Hooff Date: Mon, 7 Oct 2019 10:44:30 +0200 Subject: [PATCH 3/8] Fix recent files python function calls --- cura/CuraApplication.py | 1 + .../OpenFilesIncludingProjectsDialog.qml | 2 +- resources/qml/Menus/RecentFilesMenu.qml | 36 +------------------ 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 93695b1d63..1fd62994fd 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1601,6 +1601,7 @@ class CuraApplication(QtApplication): openProjectFile = pyqtSignal(QUrl, arguments = ["project_file"]) # Emitted when a project file is about to open. @pyqtSlot(QUrl, str) + @pyqtSlot(QUrl) ## Open a local file # \param project_mode How to handle project files. Either None(default): Follow user preference, "open_as_model" or # "open_as_project". This parameter is only considered if the file is a project file. diff --git a/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml b/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml index 0df914805a..187578f12c 100644 --- a/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml +++ b/resources/qml/Dialogs/OpenFilesIncludingProjectsDialog.qml @@ -42,7 +42,7 @@ UM.Dialog { for (var i in fileUrls) { - CuraApplication.readLocalFile(fileUrls[i], true); + CuraApplication.readLocalFile(fileUrls[i], "open_as_model"); } var meshName = backgroundItem.getMeshName(fileUrls[0].toString()); diff --git a/resources/qml/Menus/RecentFilesMenu.qml b/resources/qml/Menus/RecentFilesMenu.qml index 0f1f67b6fa..b788b5e72e 100644 --- a/resources/qml/Menus/RecentFilesMenu.qml +++ b/resources/qml/Menus/RecentFilesMenu.qml @@ -29,42 +29,8 @@ Menu } onTriggered: { - var toShowDialog = false; - var toOpenAsProject = false; - var toOpenAsModel = false; + CuraApplication.readLocalFile(modelData); - if (CuraApplication.checkIsValidProjectFile(modelData)) { - // check preference - var choice = UM.Preferences.getValue("cura/choice_on_open_project"); - - if (choice == "open_as_project") - { - toOpenAsProject = true; - }else if (choice == "open_as_model"){ - toOpenAsModel = true; - }else{ - toShowDialog = true; - } - } - else { - toOpenAsModel = true; - } - - if (toShowDialog) { - askOpenAsProjectOrModelsDialog.fileUrl = modelData; - askOpenAsProjectOrModelsDialog.show(); - return; - } - - // open file in the prefered way - if (toOpenAsProject) - { - UM.WorkspaceFileHandler.readLocalFile(modelData); - } - else if (toOpenAsModel) - { - CuraApplication.readLocalFile(modelData, true); - } var meshName = backgroundItem.getMeshName(modelData.toString()) backgroundItem.hasMesh(decodeURIComponent(meshName)) } From 497648ffe71f1a96fb7d2f63d0a38f6b88d372d4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 7 Oct 2019 14:06:17 +0200 Subject: [PATCH 4/8] Fix min/max X/Y QML value bindings CURA-6834 --- resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml b/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml index a08fa92c78..fbd2236874 100644 --- a/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml +++ b/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml @@ -64,7 +64,7 @@ NumericTextFieldWithUnit // show the correct value. if (!textField.activeFocus && !textField.acceptableInput) { - valueText = axisValue + valueText = Qt.binding(function() { return machineXMaxField.axisValue }) } } } @@ -94,6 +94,6 @@ NumericTextFieldWithUnit } // Recreate the binding to show the correct value. - valueText = axisValue + valueText = Qt.binding(function() { return axisValue }) } } From 225d1a2ac177328f58b97c248ce526220d006676 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 7 Oct 2019 15:25:49 +0200 Subject: [PATCH 5/8] Allow minimum circumference to be 0 It should just not filter then. --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 122d0e3f5e..ac16b8ec84 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -6220,7 +6220,7 @@ "unit": "mm", "type": "float", "default_value": 1.0, - "minimum_value": "0.001", + "minimum_value": "0", "minimum_value_warning": "0.05", "maximum_value_warning": "1.0", "settable_per_mesh": true, From d1f9245d2623677f8a4d7193e1cf35632c16b582 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 7 Oct 2019 17:17:43 +0200 Subject: [PATCH 6/8] Move Maximum Resolution and Maximum Deviation out of experimental Yes, it does comply to our Definition of Not Experimental. And I asked. --- resources/definitions/fdmprinter.def.json | 52 +++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index ac16b8ec84..d16b068dd8 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5830,6 +5830,32 @@ "enabled": "not (support_enable or support_tree_enable)", "settable_per_mesh": false, "settable_per_extruder": false + }, + "meshfix_maximum_travel_resolution": + { + "label": "Maximum Travel Resolution", + "description": "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate.", + "type": "float", + "unit": "mm", + "default_value": 1.0, + "value": "min(meshfix_maximum_resolution * speed_travel / speed_print, 2 * line_width)", + "minimum_value": "0.001", + "minimum_value_warning": "0.05", + "maximum_value_warning": "10", + "settable_per_mesh": false, + "settable_per_extruder": true + }, + "meshfix_maximum_deviation": + { + "label": "Maximum Deviation", + "description": "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true.", + "type": "float", + "unit": "mm", + "default_value": 0.05, + "minimum_value": "0.001", + "minimum_value_warning": "0.01", + "maximum_value_warning": "0.3", + "settable_per_mesh": true } } }, @@ -6238,32 +6264,6 @@ "maximum_value_warning": "3", "settable_per_mesh": true }, - "meshfix_maximum_travel_resolution": - { - "label": "Maximum Travel Resolution", - "description": "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate.", - "type": "float", - "unit": "mm", - "default_value": 1.0, - "value": "min(meshfix_maximum_resolution * speed_travel / speed_print, 2 * line_width)", - "minimum_value": "0.001", - "minimum_value_warning": "0.05", - "maximum_value_warning": "10", - "settable_per_mesh": false, - "settable_per_extruder": true - }, - "meshfix_maximum_deviation": - { - "label": "Maximum Deviation", - "description": "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller. Maximum Deviation is a limit for Maximum Resolution, so if the two conflict the Maximum Deviation will always be held true.", - "type": "float", - "unit": "mm", - "default_value": 0.05, - "minimum_value": "0.001", - "minimum_value_warning": "0.01", - "maximum_value_warning": "0.3", - "settable_per_mesh": true - }, "support_skip_some_zags": { "label": "Break Up Support In Chunks", From 01345650e7a2c85eac9e7c503d78c0b3c5e58541 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 7 Oct 2019 21:14:02 +0200 Subject: [PATCH 7/8] Use more meaning ID CURA-6834 --- resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml b/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml index fbd2236874..7bb5f5fc76 100644 --- a/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml +++ b/resources/qml/MachineSettings/PrintHeadMinMaxTextField.qml @@ -24,7 +24,7 @@ import Cura 1.1 as Cura // NumericTextFieldWithUnit { - id: machineXMaxField + id: printerHeadMinMaxField UM.I18nCatalog { id: catalog; name: "cura" } containerStackId: Cura.MachineManager.activeMachineId @@ -64,7 +64,7 @@ NumericTextFieldWithUnit // show the correct value. if (!textField.activeFocus && !textField.acceptableInput) { - valueText = Qt.binding(function() { return machineXMaxField.axisValue }) + valueText = Qt.binding(function() { return printerHeadMinMaxField.axisValue }) } } } From 8940097265ded47180d1af1e007c908890e942eb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 7 Oct 2019 21:35:28 +0200 Subject: [PATCH 8/8] Separate black and grey text for quality menu CURA-6846 --- cura/Settings/MachineManager.py | 21 ++++++++++++------- .../Custom/CustomPrintSetup.qml | 18 +++++++++++++--- .../PrintSetupSelectorHeader.qml | 7 ++++++- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 57da690d6d..a4ff8fbbfa 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1592,18 +1592,20 @@ class MachineManager(QObject): if not no_dialog and self.hasUserSettings and self._application.getPreferences().getValue("cura/active_mode") == 1: self._application.discardOrKeepProfileChanges() - # The display name of currently active quality. + # The display name map of currently active quality. + # The display name has 2 parts, a main part and a suffix part. # This display name is: # - For built-in qualities (quality/intent): the quality type name, such as "Fine", "Normal", etc. # - For custom qualities: - - # Examples: # - "my_profile - Fine" (only based on a default quality, no intent involved) # - "my_profile - Engineering - Fine" (based on an intent) - @pyqtProperty(str, notify = activeQualityDisplayNameChanged) - def activeQualityDisplayName(self) -> str: + @pyqtProperty("QVariantMap", notify = activeQualityDisplayNameChanged) + def activeQualityDisplayNameMap(self) -> Dict[str, str]: global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack() if global_stack is None: - return "" + return {"main": "", + "suffix": ""} display_name = global_stack.quality.getName() @@ -1612,13 +1614,18 @@ class MachineManager(QObject): intent_display_name = IntentCategoryModel.name_translation.get(intent_category, catalog.i18nc("@label", "Unknown")) display_name = "{intent_name} - {the_rest}".format(intent_name = intent_display_name, - the_rest = display_name) + the_rest = display_name) + + main_part = display_name + suffix_part = "" # Not a custom quality if global_stack.qualityChanges != empty_quality_changes_container: - display_name = self.activeQualityOrQualityChangesName + " - " + display_name + main_part = self.activeQualityOrQualityChangesName + suffix_part = display_name - return display_name + return {"main": main_part, + "suffix": suffix_part} ## Change the intent category of the current printer. # diff --git a/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml b/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml index a297b0a769..2698089d0c 100644 --- a/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml +++ b/resources/qml/PrintSetupSelector/Custom/CustomPrintSetup.qml @@ -100,18 +100,30 @@ Item function generateActiveQualityText() { - var result = Cura.MachineManager.activeQualityDisplayName + var resultMap = Cura.MachineManager.activeQualityDisplayNameMap + var resultMain = resultMap["main"] + var resultSuffix = resultMap["suffix"] + var result = "" if (Cura.MachineManager.isActiveQualityExperimental) { - result += " (Experimental)" + resultSuffix += " (Experimental)" } if (Cura.MachineManager.isActiveQualitySupported) { if (Cura.MachineManager.activeQualityLayerHeight > 0) { - result += " " + result = resultMain + if (resultSuffix) + { + result += " - " + } + result += "" + if (resultSuffix) + { + result += resultSuffix + } result += " - " result += Cura.MachineManager.activeQualityLayerHeight + "mm" result += "" diff --git a/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml b/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml index bb3a986929..a23b87fdbe 100644 --- a/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml +++ b/resources/qml/PrintSetupSelector/PrintSetupSelectorHeader.qml @@ -20,7 +20,12 @@ RowLayout { if (Cura.MachineManager.activeStack) { - var text = Cura.MachineManager.activeQualityDisplayName + var resultMap = Cura.MachineManager.activeQualityDisplayNameMap + var text = resultMap["main"] + if (resultMap["suffix"]) + { + text += " - " + resultMap["suffix"] + } if (!Cura.MachineManager.hasNotSupportedQuality) {