From 0fbb067508c2282d5ebee0d6e61989858d8a3d28 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 10 Apr 2018 09:40:35 +0200 Subject: [PATCH 01/12] Clean up code in SliceInfo CURA-5204 - Remove some unused imports - Do not depend on ExtruderManager --- plugins/SliceInfoPlugin/SliceInfo.py | 59 +++++++++++++--------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index d618f63b53..6991283bf5 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -1,8 +1,9 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from cura.CuraApplication import CuraApplication -from cura.Settings.ExtruderManager import ExtruderManager +import json +import platform +import time from UM.Extension import Extension from UM.Application import Application @@ -11,18 +12,10 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Message import Message from UM.i18n import i18nCatalog from UM.Logger import Logger - -import time - from UM.Qt.Duration import DurationFormat from .SliceInfoJob import SliceInfoJob -import platform -import math -import urllib.request -import urllib.parse -import json catalog = i18nCatalog("cura") @@ -57,7 +50,7 @@ class SliceInfo(Extension): def messageActionTriggered(self, message_id, action_id): Preferences.getInstance().setValue("info/asked_send_slice_info", True) if action_id == "Disable": - Preferences.getInstance().addPreference("info/send_slice_info", False) + Application.getInstance().showPreferences() self.send_slice_info_message.hide() def _onWriteStarted(self, output_device): @@ -66,13 +59,16 @@ class SliceInfo(Extension): Logger.log("d", "'info/send_slice_info' is turned off.") return # Do nothing, user does not want to send data - global_container_stack = Application.getInstance().getGlobalContainerStack() - print_information = Application.getInstance().getPrintInformation() + application = Application.getInstance() + machine_manager = application.getMachineManager() + print_information = application.getPrintInformation() + + global_stack = machine_manager.activeMachine data = dict() # The data that we're going to submit. data["time_stamp"] = time.time() data["schema_version"] = 0 - data["cura_version"] = Application.getInstance().getVersion() + data["cura_version"] = application.getVersion() active_mode = Preferences.getInstance().getValue("cura/active_mode") if active_mode == 0: @@ -80,7 +76,7 @@ class SliceInfo(Extension): else: data["active_mode"] = "custom" - definition_changes = global_container_stack.definitionChanges + definition_changes = global_stack.definitionChanges machine_settings_changed_by_user = False if definition_changes.getId() != "empty": # Now a definition_changes container will always be created for a stack, @@ -92,16 +88,17 @@ class SliceInfo(Extension): data["language"] = Preferences.getInstance().getValue("general/language") data["os"] = {"type": platform.system(), "version": platform.version()} - data["active_machine"] = {"definition_id": global_container_stack.definition.getId(), "manufacturer": global_container_stack.definition.getMetaData().get("manufacturer","")} + data["active_machine"] = {"definition_id": global_stack.definition.getId(), + "manufacturer": global_stack.definition.getMetaDataEntry("manufacturer", "")} # add extruder specific data to slice info data["extruders"] = [] - extruders = list(ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId())) + extruders = list(global_stack.extruders.values()) extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position")) for extruder in extruders: extruder_dict = dict() - extruder_dict["active"] = ExtruderManager.getInstance().getActiveExtruderStack() == extruder + extruder_dict["active"] = machine_manager.activeStack == extruder extruder_dict["material"] = {"GUID": extruder.material.getMetaData().get("GUID", ""), "type": extruder.material.getMetaData().get("material", ""), "brand": extruder.material.getMetaData().get("brand", "") @@ -123,11 +120,11 @@ class SliceInfo(Extension): extruder_dict["extruder_settings"] = extruder_settings data["extruders"].append(extruder_dict) - data["quality_profile"] = global_container_stack.quality.getMetaData().get("quality_type") + data["quality_profile"] = global_stack.quality.getMetaData().get("quality_type") data["models"] = [] # Listing all files placed on the build plate - for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()): + for node in DepthFirstIterator(application.getController().getScene().getRoot()): if node.callDecoration("isSliceable"): model = dict() model["hash"] = node.getMeshData().getHash() @@ -173,28 +170,28 @@ class SliceInfo(Extension): "total": int(print_information.currentPrintTime.getDisplayString(DurationFormat.Format.Seconds))} print_settings = dict() - print_settings["layer_height"] = global_container_stack.getProperty("layer_height", "value") + print_settings["layer_height"] = global_stack.getProperty("layer_height", "value") # Support settings - print_settings["support_enabled"] = global_container_stack.getProperty("support_enable", "value") - print_settings["support_extruder_nr"] = int(global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr")) + print_settings["support_enabled"] = global_stack.getProperty("support_enable", "value") + print_settings["support_extruder_nr"] = int(global_stack.getExtruderPositionValueWithDefault("support_extruder_nr")) # Platform adhesion settings - print_settings["adhesion_type"] = global_container_stack.getProperty("adhesion_type", "value") + print_settings["adhesion_type"] = global_stack.getProperty("adhesion_type", "value") # Shell settings - print_settings["wall_line_count"] = global_container_stack.getProperty("wall_line_count", "value") - print_settings["retraction_enable"] = global_container_stack.getProperty("retraction_enable", "value") + print_settings["wall_line_count"] = global_stack.getProperty("wall_line_count", "value") + print_settings["retraction_enable"] = global_stack.getProperty("retraction_enable", "value") # Prime tower settings - print_settings["prime_tower_enable"] = global_container_stack.getProperty("prime_tower_enable", "value") + print_settings["prime_tower_enable"] = global_stack.getProperty("prime_tower_enable", "value") # Infill settings - print_settings["infill_sparse_density"] = global_container_stack.getProperty("infill_sparse_density", "value") - print_settings["infill_pattern"] = global_container_stack.getProperty("infill_pattern", "value") - print_settings["gradual_infill_steps"] = global_container_stack.getProperty("gradual_infill_steps", "value") + print_settings["infill_sparse_density"] = global_stack.getProperty("infill_sparse_density", "value") + print_settings["infill_pattern"] = global_stack.getProperty("infill_pattern", "value") + print_settings["gradual_infill_steps"] = global_stack.getProperty("gradual_infill_steps", "value") - print_settings["print_sequence"] = global_container_stack.getProperty("print_sequence", "value") + print_settings["print_sequence"] = global_stack.getProperty("print_sequence", "value") data["print_settings"] = print_settings From 40eedbcf70e48b7b66598f6b6f8f7eb480cd3b9a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 10 Apr 2018 11:59:25 +0200 Subject: [PATCH 02/12] Add more info dialog CURA-5204 --- cura/CuraAppSignals.py | 9 ++ cura/CuraApplication.py | 7 + plugins/SliceInfoPlugin/MoreInfoWindow.qml | 158 +++++++++++++++++++++ plugins/SliceInfoPlugin/SliceInfo.py | 53 +++++-- plugins/SliceInfoPlugin/example_data.json | 101 +++++++++++++ resources/qml/Preferences/GeneralPage.qml | 18 ++- 6 files changed, 337 insertions(+), 9 deletions(-) create mode 100644 cura/CuraAppSignals.py create mode 100644 plugins/SliceInfoPlugin/MoreInfoWindow.qml create mode 100644 plugins/SliceInfoPlugin/example_data.json diff --git a/cura/CuraAppSignals.py b/cura/CuraAppSignals.py new file mode 100644 index 0000000000..b3cf97bb8b --- /dev/null +++ b/cura/CuraAppSignals.py @@ -0,0 +1,9 @@ +from PyQt5.QtCore import pyqtSignal, QObject + + +class CuraAppSignals(QObject): + + showMoreInfoOnAnonymousDataCollection = pyqtSignal() + + def __init__(self, parent = None): + super().__init__(parent) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index be44f020f2..38ee645a0d 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -74,6 +74,7 @@ from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.Machines.VariantManager import VariantManager +from .CuraAppSignals import CuraAppSignals from . import PlatformPhysics from . import BuildVolume from . import CameraAnimation @@ -645,6 +646,8 @@ class CuraApplication(QtApplication): def run(self): self.preRun() + self._app_signals = CuraAppSignals(self) + container_registry = ContainerRegistry.getInstance() Logger.log("i", "Initializing variant manager") @@ -780,6 +783,10 @@ class CuraApplication(QtApplication): def hasGui(self): return self._use_gui + @pyqtSlot(result = QObject) + def getCuraAppSignals(self, *args) -> CuraAppSignals: + return self._app_signals + @pyqtSlot(result = QObject) def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel: return self._setting_visibility_presets_model diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml new file mode 100644 index 0000000000..d453c18c7c --- /dev/null +++ b/plugins/SliceInfoPlugin/MoreInfoWindow.qml @@ -0,0 +1,158 @@ +// Copyright (c) 2018 Ultimaker B.V. +// PluginBrowser is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Window 2.2 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import UM 1.3 as UM +import Cura 1.0 as Cura + + +UM.Dialog +{ + id: baseDialog + title: catalog.i18nc("@title:window", "More information on anonymous data collection") + visible: false + + minimumWidth: 500 * screenScaleFactor + minimumHeight: 400 * screenScaleFactor + width: minimumWidth + height: minimumHeight + + property bool allowSendData: false // for saving the user's choice + + onAccepted: manager.setSendSliceInfo(allowSendData) + + onVisibilityChanged: + { + if (visible) + { + baseDialog.allowSendData = UM.Preferences.getValue("info/send_slice_info"); + if (baseDialog.allowSendData) + { + allowSendButton.checked = true; + } + else + { + dontSendButton.checked = true; + } + } + } + + Item + { + Connections + { + target: CuraApplication.getCuraAppSignals() + onShowMoreInfoOnAnonymousDataCollection: + { + baseDialog.show(); + } + } + + id: textRow + anchors + { + top: parent.top + bottom: radioButtonsRow.top + bottomMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + } + + Label + { + id: headerText + anchors + { + top: parent.top + left: parent.left + right: parent.right + } + + text: catalog.i18nc("@text:window", "Cura sends anonymous data so we can improve the print quality and user experience. Below is an example of all the data we send.") + wrapMode: Text.WordWrap + } + + TextArea + { + id: exampleData + anchors + { + top: headerText.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: parent.bottom + bottomMargin: UM.Theme.getSize("default_margin").height + left: parent.left + right: parent.right + } + + text: manager.getExampleData() + readOnly: true + textFormat: TextEdit.PlainText + } + } + + Column + { + id: radioButtonsRow + width: parent.width + anchors.bottom: buttonRow.top + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + + ExclusiveGroup { id: group } + + RadioButton + { + id: dontSendButton + text: catalog.i18nc("@text:window", "I don't want to send these settings") + exclusiveGroup: group + onClicked: + { + baseDialog.allowSendData = !checked; + } + } + RadioButton + { + id: allowSendButton + text: catalog.i18nc("@text:window", "Allow sending these settings to improve Cura") + exclusiveGroup: group + onClicked: + { + baseDialog.allowSendData = checked; + } + } + } + + Item + { + id: buttonRow + anchors.bottom: parent.bottom + width: parent.width + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + + UM.I18nCatalog { id: catalog; name: "cura" } + + Button + { + anchors.right: parent.right + text: catalog.i18nc("@action:button", "Ok") + onClicked: { + baseDialog.accepted() + baseDialog.hide() + } + } + + Button + { + anchors.left: parent.left + text: catalog.i18nc("@action:button", "Cancel") + onClicked: { + baseDialog.rejected() + baseDialog.hide() + } + } + } +} diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 6991283bf5..5f1c2a25bc 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -1,10 +1,13 @@ -# Copyright (c) 2015 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import json +import os import platform import time +from PyQt5.QtCore import pyqtSlot, QObject + from UM.Extension import Extension from UM.Application import Application from UM.Preferences import Preferences @@ -12,6 +15,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Message import Message from UM.i18n import i18nCatalog from UM.Logger import Logger +from UM.PluginRegistry import PluginRegistry from UM.Qt.Duration import DurationFormat from .SliceInfoJob import SliceInfoJob @@ -23,15 +27,19 @@ catalog = i18nCatalog("cura") ## This Extension runs in the background and sends several bits of information to the Ultimaker servers. # The data is only sent when the user in question gave permission to do so. All data is anonymous and # no model files are being sent (Just a SHA256 hash of the model). -class SliceInfo(Extension): +class SliceInfo(QObject, Extension): info_url = "https://stats.ultimaker.com/api/cura" - def __init__(self): - super().__init__() + def __init__(self, parent = None): + QObject.__init__(self, parent) + Extension.__init__(self) Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._onWriteStarted) Preferences.getInstance().addPreference("info/send_slice_info", True) Preferences.getInstance().addPreference("info/asked_send_slice_info", False) + self._more_info_dialog = None + self._example_data_content = None + if not Preferences.getInstance().getValue("info/asked_send_slice_info"): self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymized usage statistics."), lifetime = 0, @@ -40,19 +48,48 @@ class SliceInfo(Extension): self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None, description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing.")) - self.send_slice_info_message.addAction("Disable", name = catalog.i18nc("@action:button", "Disable"), icon = None, - description = catalog.i18nc("@action:tooltip", "Don't allow Cura to send anonymized usage statistics. You can enable it again in the preferences."), button_style = Message.ActionButtonStyle.LINK) + self.send_slice_info_message.addAction("MoreInfo", name = catalog.i18nc("@action:button", "More info"), icon = None, + description = catalog.i18nc("@action:tooltip", "See more information on what data Cura sends."), button_style = Message.ActionButtonStyle.LINK) self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered) self.send_slice_info_message.show() + Application.getInstance().initializationFinished.connect(self._onAppInitialized) + + def _onAppInitialized(self): + if self._more_info_dialog is None: + self._more_info_dialog = self._createDialog("MoreInfoWindow.qml") + ## Perform action based on user input. # Note that clicking "Disable" won't actually disable the data sending, but rather take the user to preferences where they can disable it. def messageActionTriggered(self, message_id, action_id): Preferences.getInstance().setValue("info/asked_send_slice_info", True) - if action_id == "Disable": - Application.getInstance().showPreferences() + if action_id == "MoreInfo": + self._showMoreInfoDialog() self.send_slice_info_message.hide() + def _showMoreInfoDialog(self): + if self._more_info_dialog is None: + self._more_info_dialog = self._createDialog("MoreInfoWindow.qml") + self._more_info_dialog.open() + + def _createDialog(self, qml_name): + Logger.log("d", "Creating dialog [%s]", qml_name) + file_path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), qml_name) + dialog = Application.getInstance().createQmlComponent(file_path, {"manager": self}) + return dialog + + @pyqtSlot(result = str) + def getExampleData(self) -> str: + if self._example_data_content is None: + file_path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "example_data.json") + with open(file_path, "r", encoding = "utf-8") as f: + self._example_data_content = f.read() + return self._example_data_content + + @pyqtSlot(bool) + def setSendSliceInfo(self, enabled: bool): + Preferences.getInstance().setValue("info/send_slice_info", enabled) + def _onWriteStarted(self, output_device): try: if not Preferences.getInstance().getValue("info/send_slice_info"): diff --git a/plugins/SliceInfoPlugin/example_data.json b/plugins/SliceInfoPlugin/example_data.json new file mode 100644 index 0000000000..61cafbb27e --- /dev/null +++ b/plugins/SliceInfoPlugin/example_data.json @@ -0,0 +1,101 @@ +{ + "extruders": [ + { + "material": { + "GUID": "506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9", + "brand": "Generic", + "type": "PLA" + }, + "active": true, + "material_used": 4.82, + "nozzle_size": 0.4, + "variant": "AA 0.4", + "extruder_settings": { + "infill_pattern": "triangles", + "wall_line_count": 4, + "retraction_enable": true, + "infill_sparse_density": 0.0, + "gradual_infill_steps": 0.0, + "default_material_print_temperature": 200, + "material_print_temperature": 200 + } + }, + { + "material": { + "GUID": "86a89ceb-4159-47f6-ab97-e9953803d70f", + "brand": "Generic", + "type": "PVA" + }, + "active": false, + "material_used": 0.0, + "nozzle_size": 0.4, + "variant": "BB 0.4", + "extruder_settings": { + "infill_pattern": "triangles", + "wall_line_count": 3, + "retraction_enable": true, + "infill_sparse_density": 20, + "gradual_infill_steps": 0, + "default_material_print_temperature": 215, + "material_print_temperature": 215 + } + } + ], + "active_mode": "custom", + "schema_version": 0, + "print_times": { + "support": 0, + "infill": 0, + "total": 44548, + "travel": 5063 + }, + "machine_settings_changed_by_user": false, + "language": "en", + "cura_version": "2.7.0-master.20170721034526", + "os": { + "version": "10.0.14393", + "type": "Windows" + }, + "time_stamp": 1500629879.3985891, + "quality_profile": "normal", + "print_settings": { + "print_sequence": "all_at_once", + "infill_pattern": "triangles", + "layer_height": 0.1, + "infill_sparse_density": 20, + "wall_line_count": 3, + "retraction_enable": true, + "gradual_infill_steps": 0, + "adhesion_type": "none", + "prime_tower_enable": false, + "support_enabled": false, + "support_extruder_nr": 0 + }, + "models": [ + { + "extruder": 0, + "transformation": { + "data": "[[ 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 8.96267878e-08 -9.99999881e-01 1.00000038e+01] [ 0.00000000e+00 9.99999881e-01 8.96267878e-08 1.77869296e-07] [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]]" + }, + "bounding_box": { + "minimum": { + "x": -80.0, + "y": -4.0903287974458635e-06, + "z": -101.49998861865569 + }, + "maximum": { + "x": 80.0, + "y": 20.000011181962602, + "z": 101.49998897439428 + } + }, + "model_settings": { + }, + "hash": "ca1a12e57ddf990fabc25d9105fc28eea266937c3f907d0e58edf9cc43f28551" + } + ], + "active_machine": { + "definition_id": "ultimaker3", + "manufacturer": "Ultimaker" + } +} diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 1c7b2bcf7c..8e182ad473 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -649,7 +649,7 @@ UM.PreferencesPage UM.TooltipArea { visible: plugins.find("id", "SliceInfoPlugin") > -1 width: childrenRect.width - height: visible ? childrenRect.height : 0 + height: visible ? childrenRect.height * 2 : 0 text: catalog.i18nc("@info:tooltip","Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored.") CheckBox @@ -659,6 +659,22 @@ UM.PreferencesPage checked: boolCheck(UM.Preferences.getValue("info/send_slice_info")) onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked) } + + Button + { + id: showMoreInfo + anchors + { + top: sendDataCheckbox.bottom + bottom: parent.bottom + } + + text: catalog.i18nc("@action:button", "Show more information on anonymous data collection") + onClicked: + { + CuraApplication.getCuraAppSignals().showMoreInfoOnAnonymousDataCollection(); + } + } } Item From 586cb0a40553b96320b8f2332293ea5767e25f67 Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 10 Apr 2018 16:04:48 +0200 Subject: [PATCH 03/12] change default setting --- plugins/SliceInfoPlugin/MoreInfoWindow.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml index d453c18c7c..1d79e7a6a1 100644 --- a/plugins/SliceInfoPlugin/MoreInfoWindow.qml +++ b/plugins/SliceInfoPlugin/MoreInfoWindow.qml @@ -21,7 +21,7 @@ UM.Dialog width: minimumWidth height: minimumHeight - property bool allowSendData: false // for saving the user's choice + property bool allowSendData: true // for saving the user's choice onAccepted: manager.setSendSliceInfo(allowSendData) From 4aab395b71bc6f7fd0c5284876c6155576f9807a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 17 Apr 2018 16:06:41 +0200 Subject: [PATCH 04/12] Update example_data.json CURA-5204 --- plugins/SliceInfoPlugin/example_data.json | 136 ++++++++++++---------- 1 file changed, 74 insertions(+), 62 deletions(-) diff --git a/plugins/SliceInfoPlugin/example_data.json b/plugins/SliceInfoPlugin/example_data.json index 61cafbb27e..ec953e0842 100644 --- a/plugins/SliceInfoPlugin/example_data.json +++ b/plugins/SliceInfoPlugin/example_data.json @@ -1,101 +1,113 @@ { + "time_stamp": 1523973715.486928, + "schema_version": 0, + "cura_version": "3.3", + "active_mode": "custom", + "machine_settings_changed_by_user": true, + "language": "en_US", + "os": { + "type": "Linux", + "version": "#43~16.04.1-Ubuntu SMP Wed Mar 14 17:48:43 UTC 2018" + }, + "active_machine": { + "definition_id": "ultimaker3", + "manufacturer": "Ultimaker B.V." + }, "extruders": [ { + "active": true, "material": { "GUID": "506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9", - "brand": "Generic", - "type": "PLA" + "type": "PLA", + "brand": "Generic" }, - "active": true, - "material_used": 4.82, - "nozzle_size": 0.4, + "material_used": 0.84, "variant": "AA 0.4", + "nozzle_size": 0.4, "extruder_settings": { - "infill_pattern": "triangles", - "wall_line_count": 4, + "wall_line_count": 3, "retraction_enable": true, - "infill_sparse_density": 0.0, - "gradual_infill_steps": 0.0, + "infill_sparse_density": 30, + "infill_pattern": "triangles", + "gradual_infill_steps": 0, "default_material_print_temperature": 200, "material_print_temperature": 200 } }, { + "active": false, "material": { "GUID": "86a89ceb-4159-47f6-ab97-e9953803d70f", - "brand": "Generic", - "type": "PVA" + "type": "PVA", + "brand": "Generic" }, - "active": false, - "material_used": 0.0, - "nozzle_size": 0.4, + "material_used": 0.5, "variant": "BB 0.4", + "nozzle_size": 0.4, "extruder_settings": { - "infill_pattern": "triangles", "wall_line_count": 3, "retraction_enable": true, "infill_sparse_density": 20, + "infill_pattern": "triangles", "gradual_infill_steps": 0, "default_material_print_temperature": 215, - "material_print_temperature": 215 + "material_print_temperature": 220 } } ], - "active_mode": "custom", - "schema_version": 0, - "print_times": { - "support": 0, - "infill": 0, - "total": 44548, - "travel": 5063 - }, - "machine_settings_changed_by_user": false, - "language": "en", - "cura_version": "2.7.0-master.20170721034526", - "os": { - "version": "10.0.14393", - "type": "Windows" - }, - "time_stamp": 1500629879.3985891, - "quality_profile": "normal", - "print_settings": { - "print_sequence": "all_at_once", - "infill_pattern": "triangles", - "layer_height": 0.1, - "infill_sparse_density": 20, - "wall_line_count": 3, - "retraction_enable": true, - "gradual_infill_steps": 0, - "adhesion_type": "none", - "prime_tower_enable": false, - "support_enabled": false, - "support_extruder_nr": 0 - }, + "quality_profile": "fast", "models": [ { - "extruder": 0, - "transformation": { - "data": "[[ 1.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00] [ 0.00000000e+00 8.96267878e-08 -9.99999881e-01 1.00000038e+01] [ 0.00000000e+00 9.99999881e-01 8.96267878e-08 1.77869296e-07] [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]]" - }, + "hash": "b72789b9beb5366dff20b1cf501020c3d4d4df7dc2295ecd0fddd0a6436df070", "bounding_box": { "minimum": { - "x": -80.0, - "y": -4.0903287974458635e-06, - "z": -101.49998861865569 + "x": -10.0, + "y": 0.0, + "z": -5.0 }, "maximum": { - "x": 80.0, - "y": 20.000011181962602, - "z": 101.49998897439428 + "x": 9.999999046325684, + "y": 40.0, + "z": 5.0 } }, - "model_settings": { + "transformation": { + "data": "[[ 1. 0. 0. 0.] [ 0. 1. 0. 20.] [ 0. 0. 1. 0.] [ 0. 0. 0. 1.]]" }, - "hash": "ca1a12e57ddf990fabc25d9105fc28eea266937c3f907d0e58edf9cc43f28551" + "extruder": 0, + "model_settings": { + "support_enabled": true, + "support_extruder_nr": 1, + "infill_mesh": false, + "cutting_mesh": false, + "support_mesh": false, + "anti_overhang_mesh": false, + "wall_line_count": 3, + "retraction_enable": true, + "infill_sparse_density": 30, + "infill_pattern": "triangles", + "gradual_infill_steps": 0 + } } ], - "active_machine": { - "definition_id": "ultimaker3", - "manufacturer": "Ultimaker" - } + "print_times": { + "travel": 187, + "support": 825, + "infill": 351, + "total": 7234 + }, + "print_settings": { + "layer_height": 0.15, + "support_enabled": true, + "support_extruder_nr": 1, + "adhesion_type": "brim", + "wall_line_count": 3, + "retraction_enable": true, + "prime_tower_enable": true, + "infill_sparse_density": 20, + "infill_pattern": "triangles", + "gradual_infill_steps": 0, + "print_sequence": "all_at_once" + }, + "output_to": "LocalFileOutputDevice" } From 50153b43a891e1a8817df1c7d87646291b4f18b4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 17 Apr 2018 16:08:02 +0200 Subject: [PATCH 05/12] Fix license banner for MoreInfoWindow.qml CURA-5204 --- plugins/SliceInfoPlugin/MoreInfoWindow.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml index 1d79e7a6a1..c860c92bfb 100644 --- a/plugins/SliceInfoPlugin/MoreInfoWindow.qml +++ b/plugins/SliceInfoPlugin/MoreInfoWindow.qml @@ -1,5 +1,5 @@ // Copyright (c) 2018 Ultimaker B.V. -// PluginBrowser is released under the terms of the LGPLv3 or higher. +// Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 import QtQuick.Window 2.2 From 4d3acddfa4b434165c52e99f2d0d9969b614edbe Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 17 Apr 2018 16:08:41 +0200 Subject: [PATCH 06/12] Update text and fix qml code styles CURA-5024 --- plugins/SliceInfoPlugin/MoreInfoWindow.qml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml index c860c92bfb..bb909418f4 100644 --- a/plugins/SliceInfoPlugin/MoreInfoWindow.qml +++ b/plugins/SliceInfoPlugin/MoreInfoWindow.qml @@ -72,7 +72,7 @@ UM.Dialog right: parent.right } - text: catalog.i18nc("@text:window", "Cura sends anonymous data so we can improve the print quality and user experience. Below is an example of all the data we send.") + text: catalog.i18nc("@text:window", "Cura sends anonymous data to Ultimaker in order to improve the print quality and user experience. Below is an example of all the data that is sent.") wrapMode: Text.WordWrap } @@ -107,7 +107,7 @@ UM.Dialog RadioButton { id: dontSendButton - text: catalog.i18nc("@text:window", "I don't want to send these settings") + text: catalog.i18nc("@text:window", "I don't want to send these data") exclusiveGroup: group onClicked: { @@ -117,7 +117,7 @@ UM.Dialog RadioButton { id: allowSendButton - text: catalog.i18nc("@text:window", "Allow sending these settings to improve Cura") + text: catalog.i18nc("@text:window", "Allow sending these data to Ultimaker and help us improve Cura") exclusiveGroup: group onClicked: { @@ -138,8 +138,9 @@ UM.Dialog Button { anchors.right: parent.right - text: catalog.i18nc("@action:button", "Ok") - onClicked: { + text: catalog.i18nc("@action:button", "OK") + onClicked: + { baseDialog.accepted() baseDialog.hide() } @@ -149,7 +150,8 @@ UM.Dialog { anchors.left: parent.left text: catalog.i18nc("@action:button", "Cancel") - onClicked: { + onClicked: + { baseDialog.rejected() baseDialog.hide() } From 0d5b21932e1d87f696298e4b1d1d43ffac71ff11 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 17 Apr 2018 16:13:11 +0200 Subject: [PATCH 07/12] Use "More information" for button CURA-5204 --- resources/qml/Preferences/GeneralPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 8e182ad473..1ff45bcf93 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -669,7 +669,7 @@ UM.PreferencesPage bottom: parent.bottom } - text: catalog.i18nc("@action:button", "Show more information on anonymous data collection") + text: catalog.i18nc("@action:button", "More information") onClicked: { CuraApplication.getCuraAppSignals().showMoreInfoOnAnonymousDataCollection(); From 35e7be1d417df4ded2e46079999edb3d4bde7c0d Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 17 Apr 2018 16:43:39 +0200 Subject: [PATCH 08/12] Use pyqtSlot to show more info dialog CURA-5204 --- cura/CuraAppSignals.py | 9 --------- cura/CuraApplication.py | 11 ++++------- plugins/SliceInfoPlugin/MoreInfoWindow.qml | 9 --------- plugins/SliceInfoPlugin/SliceInfo.py | 4 ++-- resources/qml/Preferences/GeneralPage.qml | 3 ++- 5 files changed, 8 insertions(+), 28 deletions(-) delete mode 100644 cura/CuraAppSignals.py diff --git a/cura/CuraAppSignals.py b/cura/CuraAppSignals.py deleted file mode 100644 index b3cf97bb8b..0000000000 --- a/cura/CuraAppSignals.py +++ /dev/null @@ -1,9 +0,0 @@ -from PyQt5.QtCore import pyqtSignal, QObject - - -class CuraAppSignals(QObject): - - showMoreInfoOnAnonymousDataCollection = pyqtSignal() - - def __init__(self, parent = None): - super().__init__(parent) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 38ee645a0d..315c23b228 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -74,7 +74,6 @@ from cura.Settings.SimpleModeSettingsManager import SimpleModeSettingsManager from cura.Machines.VariantManager import VariantManager -from .CuraAppSignals import CuraAppSignals from . import PlatformPhysics from . import BuildVolume from . import CameraAnimation @@ -646,8 +645,6 @@ class CuraApplication(QtApplication): def run(self): self.preRun() - self._app_signals = CuraAppSignals(self) - container_registry = ContainerRegistry.getInstance() Logger.log("i", "Initializing variant manager") @@ -783,10 +780,6 @@ class CuraApplication(QtApplication): def hasGui(self): return self._use_gui - @pyqtSlot(result = QObject) - def getCuraAppSignals(self, *args) -> CuraAppSignals: - return self._app_signals - @pyqtSlot(result = QObject) def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel: return self._setting_visibility_presets_model @@ -1739,3 +1732,7 @@ class CuraApplication(QtApplication): node = node.getParent() Selection.add(node) + + @pyqtSlot() + def showMoreInformationDialogForAnonymousDataCollection(self): + self._plugin_registry.getPluginObject("SliceInfoPlugin").showMoreInfoDialog() diff --git a/plugins/SliceInfoPlugin/MoreInfoWindow.qml b/plugins/SliceInfoPlugin/MoreInfoWindow.qml index bb909418f4..985ebe94a2 100644 --- a/plugins/SliceInfoPlugin/MoreInfoWindow.qml +++ b/plugins/SliceInfoPlugin/MoreInfoWindow.qml @@ -43,15 +43,6 @@ UM.Dialog Item { - Connections - { - target: CuraApplication.getCuraAppSignals() - onShowMoreInfoOnAnonymousDataCollection: - { - baseDialog.show(); - } - } - id: textRow anchors { diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 5f1c2a25bc..82e07da464 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -64,10 +64,10 @@ class SliceInfo(QObject, Extension): def messageActionTriggered(self, message_id, action_id): Preferences.getInstance().setValue("info/asked_send_slice_info", True) if action_id == "MoreInfo": - self._showMoreInfoDialog() + self.showMoreInfoDialog() self.send_slice_info_message.hide() - def _showMoreInfoDialog(self): + def showMoreInfoDialog(self): if self._more_info_dialog is None: self._more_info_dialog = self._createDialog("MoreInfoWindow.qml") self._more_info_dialog.open() diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 1ff45bcf93..d68eb8d5aa 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -7,6 +7,7 @@ import QtQuick.Layouts 1.1 import QtQuick.Controls.Styles 1.1 import UM 1.1 as UM +import Cura 1.0 as Cura UM.PreferencesPage { @@ -672,7 +673,7 @@ UM.PreferencesPage text: catalog.i18nc("@action:button", "More information") onClicked: { - CuraApplication.getCuraAppSignals().showMoreInfoOnAnonymousDataCollection(); + CuraApplication.showMoreInformationDialogForAnonymousDataCollection(); } } } From 121d1806be9b3c81f8f0e7220afa9380751a178d Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 20 Apr 2018 11:56:59 +0200 Subject: [PATCH 09/12] Don't show the corresponding element in the general preference panel if the related plugin is not enabled. Contributes to CURA-5204 --- resources/qml/Preferences/GeneralPage.qml | 33 ++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index d68eb8d5aa..89a8f58a82 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -98,16 +98,26 @@ UM.PreferencesPage UM.Preferences.resetPreference("cura/choice_on_open_project") setDefaultOpenProjectOption(UM.Preferences.getValue("cura/choice_on_open_project")) - if (plugins.find("id", "SliceInfoPlugin") > -1) { + if (pluginExistsAndEnabled("SliceInfoPlugin")) { UM.Preferences.resetPreference("info/send_slice_info") sendDataCheckbox.checked = boolCheck(UM.Preferences.getValue("info/send_slice_info")) } - if (plugins.find("id", "UpdateChecker") > -1) { + if (pluginExistsAndEnabled("UpdateChecker")) { UM.Preferences.resetPreference("info/automatic_update_check") checkUpdatesCheckbox.checked = boolCheck(UM.Preferences.getValue("info/automatic_update_check")) } } + function pluginExistsAndEnabled(pluginName) + { + var pluginItem = plugins.find("id", pluginName) + if (pluginItem > -1) + { + return plugins.getItem(pluginItem).enabled + } + return false + } + ScrollView { width: parent.width @@ -633,7 +643,7 @@ UM.PreferencesPage } UM.TooltipArea { - visible: plugins.find("id", "UpdateChecker") > -1 + visible: pluginExistsAndEnabled("UpdateChecker") width: childrenRect.width height: visible ? childrenRect.height : 0 text: catalog.i18nc("@info:tooltip","Should Cura check for updates when the program is started?") @@ -642,34 +652,29 @@ UM.PreferencesPage { id: checkUpdatesCheckbox text: catalog.i18nc("@option:check","Check for updates on start") - checked: boolCheck(UM.Preferences.getValue("info/automatic_update_check")) + checked: parent.visible ? boolCheck(UM.Preferences.getValue("info/automatic_update_check")): false onCheckedChanged: UM.Preferences.setValue("info/automatic_update_check", checked) } } UM.TooltipArea { - visible: plugins.find("id", "SliceInfoPlugin") > -1 + visible: pluginExistsAndEnabled("SliceInfoPlugin") width: childrenRect.width - height: visible ? childrenRect.height * 2 : 0 + height: visible ? childrenRect.height : 0 text: catalog.i18nc("@info:tooltip","Should anonymous data about your print be sent to Ultimaker? Note, no models, IP addresses or other personally identifiable information is sent or stored.") CheckBox { id: sendDataCheckbox text: catalog.i18nc("@option:check","Send (anonymous) print information") - checked: boolCheck(UM.Preferences.getValue("info/send_slice_info")) + checked: parent.visible ? boolCheck(UM.Preferences.getValue("info/send_slice_info")) : false onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked) } Button { id: showMoreInfo - anchors - { - top: sendDataCheckbox.bottom - bottom: parent.bottom - } - + anchors.top: sendDataCheckbox.bottom text: catalog.i18nc("@action:button", "More information") onClicked: { @@ -718,8 +723,6 @@ UM.PreferencesPage onCheckedChanged: UM.Preferences.setValue("cura/not_arrange_objects_on_load", checked) } } - - } } } From 122b5e36cfb0c62b69ba0e48371b19774131aa17 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 20 Apr 2018 13:36:07 +0200 Subject: [PATCH 10/12] CURA-5204 Revert a change since it sets the setting to false if the panel is not visible. --- resources/qml/Preferences/GeneralPage.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 89a8f58a82..26086df93a 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -652,7 +652,7 @@ UM.PreferencesPage { id: checkUpdatesCheckbox text: catalog.i18nc("@option:check","Check for updates on start") - checked: parent.visible ? boolCheck(UM.Preferences.getValue("info/automatic_update_check")): false + checked: boolCheck(UM.Preferences.getValue("info/automatic_update_check")) onCheckedChanged: UM.Preferences.setValue("info/automatic_update_check", checked) } } @@ -667,7 +667,7 @@ UM.PreferencesPage { id: sendDataCheckbox text: catalog.i18nc("@option:check","Send (anonymous) print information") - checked: parent.visible ? boolCheck(UM.Preferences.getValue("info/send_slice_info")) : false + checked: boolCheck(UM.Preferences.getValue("info/send_slice_info")) onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked) } From 576881bfeb1c68350d930b7e9503d9f3b43d1363 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Fri, 20 Apr 2018 14:12:05 +0200 Subject: [PATCH 11/12] CURA-5204 Update the checkbox if the setting has changed in the 'More information' dialog. --- resources/qml/Preferences/GeneralPage.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 26086df93a..1ccd4d3382 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -723,6 +723,14 @@ UM.PreferencesPage onCheckedChanged: UM.Preferences.setValue("cura/not_arrange_objects_on_load", checked) } } + + Connections { + target: UM.Preferences + onPreferenceChanged: + { + sendDataCheckbox.checked = boolCheck(UM.Preferences.getValue("info/send_slice_info")) + } + } } } } From ac2301a8fd994020fd4d2f6082eed937684568a9 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 20 Apr 2018 15:36:32 +0200 Subject: [PATCH 12/12] Fix code style: Brackets on new line And one comma without a space after it. Contributes to issue CURA-5204. --- resources/qml/Preferences/GeneralPage.qml | 52 +++++++++++++++-------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index 1ccd4d3382..f4fa7c1557 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -377,7 +377,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width; height: childrenRect.height; text: catalog.i18nc("@info:tooltip", "Should zooming move in the direction of the mouse?") @@ -391,7 +392,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip", "Should models on the platform be moved so that they no longer intersect?") @@ -404,7 +406,8 @@ UM.PreferencesPage onCheckedChanged: UM.Preferences.setValue("physics/automatic_push_free", checked) } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip", "Should models on the platform be moved down to touch the build plate?") @@ -437,7 +440,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip", "Should layer be forced into compatibility mode?") @@ -464,7 +468,8 @@ UM.PreferencesPage text: catalog.i18nc("@label","Opening and saving files") } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip","Should models be scaled to the build volume if they are too large?") @@ -478,7 +483,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip","An model may appear extremely small if its unit is for example in meters rather than millimeters. Should these models be scaled up?") @@ -492,7 +498,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip", "Should a prefix based on the printer name be added to the print job name automatically?") @@ -506,7 +513,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip", "Should a summary be shown when saving a project file?") @@ -519,7 +527,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip", "Default behavior when opening a project file") @@ -542,7 +551,8 @@ UM.PreferencesPage { id: openProjectOptionModel - Component.onCompleted: { + Component.onCompleted: + { append({ text: catalog.i18nc("@option:openProject", "Always ask"), code: "always_ask" }) append({ text: catalog.i18nc("@option:openProject", "Always open as a project"), code: "open_as_project" }) append({ text: catalog.i18nc("@option:openProject", "Always import models"), code: "open_as_model" }) @@ -602,7 +612,8 @@ UM.PreferencesPage { id: discardOrKeepProfileListModel - Component.onCompleted: { + Component.onCompleted: + { append({ text: catalog.i18nc("@option:discardOrKeep", "Always ask me this"), code: "always_ask" }) append({ text: catalog.i18nc("@option:discardOrKeep", "Discard and never ask again"), code: "always_discard" }) append({ text: catalog.i18nc("@option:discardOrKeep", "Keep and never ask again"), code: "always_keep" }) @@ -642,7 +653,8 @@ UM.PreferencesPage text: catalog.i18nc("@label","Privacy") } - UM.TooltipArea { + UM.TooltipArea + { visible: pluginExistsAndEnabled("UpdateChecker") width: childrenRect.width height: visible ? childrenRect.height : 0 @@ -657,7 +669,8 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { visible: pluginExistsAndEnabled("SliceInfoPlugin") width: childrenRect.width height: visible ? childrenRect.height : 0 @@ -696,7 +709,8 @@ UM.PreferencesPage text: catalog.i18nc("@label","Experimental") } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height text: catalog.i18nc("@info:tooltip","Use multi build plate functionality") @@ -710,21 +724,23 @@ UM.PreferencesPage } } - UM.TooltipArea { + UM.TooltipArea + { width: childrenRect.width height: childrenRect.height - text: catalog.i18nc("@info:tooltip","Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)") + text: catalog.i18nc("@info:tooltip", "Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)") CheckBox { id: arrangeOnLoadCheckbox - text: catalog.i18nc("@option:check","Do not arrange objects on load") + text: catalog.i18nc("@option:check", "Do not arrange objects on load") checked: boolCheck(UM.Preferences.getValue("cura/not_arrange_objects_on_load")) onCheckedChanged: UM.Preferences.setValue("cura/not_arrange_objects_on_load", checked) } } - Connections { + Connections + { target: UM.Preferences onPreferenceChanged: {