From bff3a5bb23c90eb24ccae46606baac97ce1809ee Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 3 Oct 2017 13:16:04 +0200 Subject: [PATCH 1/8] Naming of new machines now uses correct ordering again CURA-4408 --- cura/Settings/CuraStackBuilder.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/cura/Settings/CuraStackBuilder.py b/cura/Settings/CuraStackBuilder.py index 7a48b1657e..09815da319 100644 --- a/cura/Settings/CuraStackBuilder.py +++ b/cura/Settings/CuraStackBuilder.py @@ -29,7 +29,8 @@ class CuraStackBuilder: return None machine_definition = definitions[0] - generated_name = registry.createUniqueName("machine", "", machine_definition.name, machine_definition.name) + + generated_name = registry.createUniqueName("machine", "", name, machine_definition.name) # Make sure the new name does not collide with any definition or (quality) profile # createUniqueName() only looks at other stacks, but not at definitions or quality profiles # Note that we don't go for uniqueName() immediately because that function matches with ignore_case set to true @@ -44,13 +45,7 @@ class CuraStackBuilder: variant = "default", ) - # after creating a global stack can be set custom defined name - if name != generated_name: - name = registry.createUniqueName("machine", "", name, machine_definition.name) - if registry.findContainers(id = name): - name = registry.uniqueName(name) - - new_global_stack.setName(name) + new_global_stack.setName(generated_name) for extruder_definition in registry.findDefinitionContainers(machine = machine_definition.id): position = extruder_definition.getMetaDataEntry("position", None) From 6dcb542e641271703607a62be91adea622ed1e08 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 3 Oct 2017 13:46:38 +0200 Subject: [PATCH 2/8] Fixed issue where "create new" of quality changes in combination with machine caused issues CURA-4409 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 6de4ddc998..422aa9f248 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -600,7 +600,9 @@ class ThreeMFWorkspaceReader(WorkspaceReader): if self._resolve_strategies["machine"] == "new": # The machine is going to get a spiffy new name, so ensure that the id's of user settings match. old_extruder_id = instance_container.getMetaDataEntry("extruder", None) - if old_extruder_id: + # Note that in case of a quality_changes extruder means the definition id of the extruder stack + # For the user settings, it means the actual extruder stack id it's assigned to. + if old_extruder_id and old_extruder_id in extruder_stack_id_map: new_extruder_id = extruder_stack_id_map[old_extruder_id] instance_container.setMetaDataEntry("extruder", new_extruder_id) From dcb630a24ede945b45675c6faab9783deda92229 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 3 Oct 2017 14:02:07 +0200 Subject: [PATCH 3/8] Move text back to label and remove unused font --- resources/qml/SaveButton.qml | 2 +- resources/qml/Sidebar.qml | 2 +- resources/qml/SidebarHeader.qml | 2 +- resources/qml/SidebarSimple.qml | 4 ++-- resources/qml/SidebarTooltip.qml | 2 +- resources/themes/cura-light/theme.json | 4 ---- 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/resources/qml/SaveButton.qml b/resources/qml/SaveButton.qml index b613b1217e..7423fc2368 100644 --- a/resources/qml/SaveButton.qml +++ b/resources/qml/SaveButton.qml @@ -43,7 +43,7 @@ Item { } } - Text { + Label { id: statusLabel width: parent.width - 2 * UM.Theme.getSize("sidebar_margin").width anchors.top: parent.top diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 4fdeac752f..99948fc4fc 100755 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -114,7 +114,7 @@ Rectangle } } - Text { + Label { id: settingsModeLabel text: !hideSettings ? catalog.i18nc("@label:listbox", "Print Setup") : catalog.i18nc("@label:listbox","Print Setup disabled\nG-code files cannot be modified"); anchors.left: parent.left diff --git a/resources/qml/SidebarHeader.qml b/resources/qml/SidebarHeader.qml index d20feca8d6..9269984a2a 100644 --- a/resources/qml/SidebarHeader.qml +++ b/resources/qml/SidebarHeader.qml @@ -363,7 +363,7 @@ Column visible: !Cura.MachineManager.isCurrentSetupSupported } - Text { + Label { id: materialInfoLabel wrapMode: Text.WordWrap text: catalog.i18nc("@label", "Check material compatibility") diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index f8c3173c11..d1521b74d3 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -385,7 +385,7 @@ Item anchors.top: infillCellLeft.top anchors.topMargin: UM.Theme.getSize("sidebar_margin").height - Text { + Label { id: selectedInfillRateText //anchors.top: parent.top @@ -563,7 +563,7 @@ Item } } - Text { + Label { id: gradualInfillLabel anchors.left: enableGradualInfillCheckBox.right anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width / 2 diff --git a/resources/qml/SidebarTooltip.qml b/resources/qml/SidebarTooltip.qml index 057bd63203..60d01dd6f6 100644 --- a/resources/qml/SidebarTooltip.qml +++ b/resources/qml/SidebarTooltip.qml @@ -43,7 +43,7 @@ UM.PointingRectangle { base.opacity = 0; } - Text { + Label { id: label; anchors { top: parent.top; diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 96ccd469b6..b41ea96846 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -17,10 +17,6 @@ "size": 1.15, "family": "Open Sans" }, - "default_little_big": { - "size": 1.17, - "family": "Open Sans" - }, "default_bold": { "size": 1.15, "bold": true, From b0fa87231ca0cbfec877a5348586182dadc66016 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 3 Oct 2017 17:33:24 +0200 Subject: [PATCH 4/8] CURA-4390 add new menu item for plugins --- cura/CuraApplication.py | 3 ++- plugins/PluginBrowser/PluginBrowser.py | 5 ++-- resources/qml/Actions.qml | 17 +++++++++++++ resources/qml/Cura.qml | 35 +++++++++++++++++++++++++- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 9e016561d5..133bcef536 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -220,7 +220,8 @@ class CuraApplication(QtApplication): "LocalFileOutputDevice", "TranslateTool", "FileLogger", - "XmlMaterialProfile" + "XmlMaterialProfile", + ]) self._physics = None self._volume = None diff --git a/plugins/PluginBrowser/PluginBrowser.py b/plugins/PluginBrowser/PluginBrowser.py index 7a3b52b99f..0037d4bc59 100644 --- a/plugins/PluginBrowser/PluginBrowser.py +++ b/plugins/PluginBrowser/PluginBrowser.py @@ -23,9 +23,9 @@ i18n_catalog = i18nCatalog("cura") class PluginBrowser(QObject, Extension): - def __init__(self, parent = None): + def __init__(self, parent=None): super().__init__(parent) - self.addMenuItem(i18n_catalog.i18nc("@menuitem", "Browse plugins"), self.browsePlugins) + self._api_version = 1 self._api_url = "http://software.ultimaker.com/cura/v%s/" % self._api_version @@ -92,6 +92,7 @@ class PluginBrowser(QObject, Extension): def isDownloading(self): return self._is_downloading + @pyqtSlot() def browsePlugins(self): self._createNetworkManager() self.requestPluginList() diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 68a3baa768..cc27520a02 100755 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -61,6 +61,9 @@ Item property alias configureSettingVisibility: configureSettingVisibilityAction + property alias browsePlugins: browsePluginsAction + property alias configurePlugins: configurePluginsAction + UM.I18nCatalog{id: catalog; name:"cura"} Action @@ -362,4 +365,18 @@ Item text: catalog.i18nc("@action:menu", "Configure setting visibility..."); iconName: "configure" } + + Action + { + id: browsePluginsAction + text: catalog.i18nc("@action:menu", "Browse plugins...") + iconName: "plugins_browse" + } + + Action + { + id: configurePluginsAction + text: catalog.i18nc("@action:menu", "Installed plugins..."); + iconName: "plugins_configure" + } } diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 9fecf23ca9..ca32a6eaab 100755 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -207,7 +207,7 @@ UM.MainWindow id: sub_menu title: model.name; visible: actions != null - enabled:actions != null + enabled: actions != null Instantiator { model: actions @@ -226,6 +226,15 @@ UM.MainWindow } } + Menu + { + id: plugin_menu + title: catalog.i18nc("@title:menu menubar:toplevel", "P&lugins") + + MenuItem { action: Cura.Actions.browsePlugins } + MenuItem { action: Cura.Actions.configurePlugins } + } + Menu { title: catalog.i18nc("@title:menu menubar:toplevel","P&references"); @@ -543,6 +552,30 @@ UM.MainWindow } } + // show the installed plugins page in the preferences dialog + Connections + { + target: Cura.Actions.configurePlugins + onTriggered: + { + preferences.visible = true + preferences.setPage(5) + } + } + + UM.ExtensionModel { + id: curaExtensions + } + + // show the plugin browser dialog + Connections + { + target: Cura.Actions.browsePlugins + onTriggered: { + curaExtensions.callExtensionMethod("Plugin Browser", "browsePlugins") + } + } + Timer { id: createProfileTimer From 3328184fbcbe62c0b1b1a81fcf4b967918a44eb7 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 4 Oct 2017 11:06:20 +0200 Subject: [PATCH 5/8] CURA-4398 block print over network when another upload is already in progress --- .../NetworkPrinterOutputDevice.py | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 9377fba6b9..19b03121ff 100755 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -49,7 +49,8 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self._api_prefix = api_prefix self._gcode = None - self._print_finished = True # _print_finsihed == False means we're halfway in a print + self._print_finished = True # _print_finished == False means we're halfway in a print + self._write_finished = True # _write_finished == False means we're currently sending a G-code file self._use_gzip = True # Should we use g-zip compression before sending the data? @@ -649,7 +650,16 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # \param filter_by_machine Whether to filter MIME types by machine. This # is ignored. # \param kwargs Keyword arguments. - def requestWrite(self, nodes, file_name = None, filter_by_machine = False, file_handler = None, **kwargs): + def requestWrite(self, nodes, file_name=None, filter_by_machine=False, file_handler=None, **kwargs): + + # Check if we're already writing + if not self._write_finished: + self._error_message = Message( + i18n_catalog.i18nc("@info:status", + "Sending new jobs (temporarily) blocked, still sending the previous print job.")) + self._error_message.show() + return + if self._printer_state not in ["idle", ""]: self._error_message = Message( i18n_catalog.i18nc("@info:status", "Unable to start a new print job, printer is busy. Current printer status is %s.") % self._printer_state, @@ -749,6 +759,9 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): ) return + # Indicate we're starting a new write action, is set back to True in the startPrint() method + self._write_finished = False + self.startPrint() def _configurationMismatchMessageCallback(self, button): @@ -908,6 +921,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): ## Post request + data self._post_reply = self._manager.post(self._post_request, self._post_multi_part) self._post_reply.uploadProgress.connect(self._onUploadProgress) + self._post_reply.finished.connect(self._onUploadFinished) # used to unblock new write actions except IOError: self._progress_message.hide() @@ -1218,6 +1232,10 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self._progress_message.setProgress(0) self._progress_message.hide() + ## Allow new write actions (uploads) again when uploading is finished. + def _onUploadFinished(self): + self._write_finished = True + ## Let the user decide if the hotends and/or material should be synced with the printer def materialHotendChangedMessage(self, callback): Application.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Sync with your printer"), From ea9d389f9980e2b754e86f17211f66bada2aebcc Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 4 Oct 2017 12:05:02 +0200 Subject: [PATCH 6/8] CURA-4390 make plugin browser a required plugin --- cura/CuraApplication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 133bcef536..ab348ae471 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -221,7 +221,7 @@ class CuraApplication(QtApplication): "TranslateTool", "FileLogger", "XmlMaterialProfile", - + "PluginBrowser" ]) self._physics = None self._volume = None From 104926c6ed1648ec20b4308fdacad4e99c14c8b3 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 4 Oct 2017 13:14:07 +0200 Subject: [PATCH 7/8] Updating when new definition changes should be created when loading project - CURA-4413 --- plugins/3MFReader/ThreeMFWorkspaceReader.py | 6 ++++-- plugins/3MFReader/WorkspaceDialog.py | 12 +++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/3MFReader/ThreeMFWorkspaceReader.py b/plugins/3MFReader/ThreeMFWorkspaceReader.py index 422aa9f248..7e185c8d9f 100755 --- a/plugins/3MFReader/ThreeMFWorkspaceReader.py +++ b/plugins/3MFReader/ThreeMFWorkspaceReader.py @@ -222,10 +222,12 @@ class ThreeMFWorkspaceReader(WorkspaceReader): elif container_type == "definition_changes": definition_name = instance_container.getName() num_settings_overriden_by_definition_changes += len(instance_container._instances) + # Check if definition changes already exists. definition_changes = self._container_registry.findInstanceContainers(id = container_id) - containers_found_dict["definition_changes"] = True # Check if there is any difference the loaded settings from the project file and the settings in Cura. if definition_changes: + containers_found_dict["definition_changes"] = True + # Check if there really is a conflict by comparing the values if definition_changes[0] != instance_container: definition_changes_conflict = True elif container_type == "quality": @@ -357,7 +359,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader): # - new: create a new container # - override: override the existing container # - None: There is no conflict, which means containers with the same IDs may or may not be there already. - # If there is an existing container, there is no conflict between the them, and default to "override" + # If there is an existing container, there is no conflict between them, and default to "override" # If there is no existing container, default to "new" # # Default values diff --git a/plugins/3MFReader/WorkspaceDialog.py b/plugins/3MFReader/WorkspaceDialog.py index d80fc8b8b5..fc46a3daec 100644 --- a/plugins/3MFReader/WorkspaceDialog.py +++ b/plugins/3MFReader/WorkspaceDialog.py @@ -233,13 +233,15 @@ class WorkspaceDialog(QObject): self._result["quality_changes"] = None if "definition_changes" in self._result and not self._has_definition_changes_conflict: self._result["definition_changes"] = None - - # If the machine needs to be re-created, the definition_changes should also be re-created. - if "machine" in self._result and self._result["machine"] == "new" and self._result["definition_changes"] is None: - self._result["definition_changes"] = "new" - if "material" in self._result and not self._has_material_conflict: self._result["material"] = None + + # If the machine needs to be re-created, the definition_changes should also be re-created. + # If the machine strategy is None, it means that there is no name conflict with existing ones. In this case + # new definitions changes are created + if "machine" in self._result and self._result["machine"] == "new" or self._result["machine"] is None and self._result["definition_changes"] is None: + self._result["definition_changes"] = "new" + return self._result def _createViewFromQML(self): From 3f1ec174ba01756f1db99ac396c5e2d5523d8e16 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 4 Oct 2017 13:34:24 +0200 Subject: [PATCH 8/8] CURA-4414 replace all Text elements for Label, make sure no half pixel anchors exist --- resources/qml/SidebarSimple.qml | 36 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index d1521b74d3..03d3e2cd10 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -154,7 +154,7 @@ Item } } - Text + Label { id: qualityRowTitle text: catalog.i18nc("@label", "Layer Height") @@ -171,11 +171,11 @@ Item { model: qualityModel - Text + Label { anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2 + anchors.topMargin: parseInt(UM.Theme.getSize("sidebar_margin").height / 2) color: (Cura.MachineManager.activeMachine != null && Cura.ProfilesModel.getItem(index).available) ? UM.Theme.getColor("quality_slider_available") : UM.Theme.getColor("quality_slider_unavailable") text: { @@ -194,13 +194,13 @@ Item // Make sure the text aligns correctly with each tick if (qualityModel.totalTicks == 0) { // If there is only one tick, align it centrally - return ((base.width * 0.55) - width) / 2 + return parseInt(((base.width * 0.55) - width) / 2) } else if (index == 0) { return (base.width * 0.55 / qualityModel.totalTicks) * index } else if (index == qualityModel.totalTicks) { return (base.width * 0.55 / qualityModel.totalTicks) * index - width } else { - return (base.width * 0.55 / qualityModel.totalTicks) * index - (width / 2) + return parseInt((base.width * 0.55 / qualityModel.totalTicks) * index - (width / 2)) } } } @@ -310,7 +310,7 @@ Item } } - Text + Label { id: speedLabel anchors.top: speedSlider.bottom @@ -322,7 +322,7 @@ Item color: UM.Theme.getColor("text") } - Text + Label { anchors.bottom: speedLabel.bottom anchors.left: speedSlider.left @@ -333,7 +333,7 @@ Item horizontalAlignment: Text.AlignLeft } - Text + Label { anchors.bottom: speedLabel.bottom anchors.right: speedSlider.right @@ -360,7 +360,7 @@ Item width: UM.Theme.getSize("sidebar").width * .45 - UM.Theme.getSize("sidebar_margin").width - Text + Label { id: infillLabel text: catalog.i18nc("@label", "Infill") @@ -482,7 +482,7 @@ Item anchors.right: parent.right anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2 + anchors.topMargin: parseInt(UM.Theme.getSize("sidebar_margin").height / 2) // we loop over all density icons and only show the one that has the current density and steps Repeater @@ -533,7 +533,7 @@ Item property alias _hovered: enableGradualInfillMouseArea.containsMouse anchors.top: infillSlider.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height / 2 // closer to slider since it belongs to the same category + anchors.topMargin: parseInt(UM.Theme.getSize("sidebar_margin").height / 2) // closer to slider since it belongs to the same category anchors.left: infillCellRight.left style: UM.Theme.styles.checkbox @@ -566,7 +566,7 @@ Item Label { id: gradualInfillLabel anchors.left: enableGradualInfillCheckBox.right - anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width / 2 + anchors.leftMargin: parseInt(UM.Theme.getSize("sidebar_margin").width / 2) text: catalog.i18nc("@label", "Enable gradual") font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") @@ -621,13 +621,13 @@ Item // // Enable support // - Text + Label { id: enableSupportLabel visible: enableSupportCheckBox.visible anchors.top: infillCellRight.bottom - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 1.5 + anchors.topMargin: parseInt(UM.Theme.getSize("sidebar_margin").height * 1.5) anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("sidebar_margin").width anchors.verticalCenter: enableSupportCheckBox.verticalCenter @@ -674,7 +674,7 @@ Item } } - Text + Label { id: supportExtruderLabel visible: supportExtruderCombobox.visible @@ -750,7 +750,7 @@ Item } - Text + Label { id: adhesionHelperLabel visible: adhesionCheckBox.visible @@ -836,12 +836,12 @@ Item { id: tipsCell anchors.top: adhesionCheckBox.visible ? adhesionCheckBox.bottom : (enableSupportCheckBox.visible ? supportExtruderCombobox.bottom : infillCellRight.bottom) - anchors.topMargin: UM.Theme.getSize("sidebar_margin").height * 2 + anchors.topMargin: parseInt(UM.Theme.getSize("sidebar_margin").height * 2) anchors.left: parent.left width: parent.width height: tipsText.contentHeight * tipsText.lineCount - Text + Label { id: tipsText anchors.left: parent.left