mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-14 06:15:54 +08:00
Merge pull request #3666 from Ultimaker/CURA-5204_send_anonymous_data
Show information dialogue on what usage data is sent
This commit is contained in:
commit
5333ca5aa8
@ -1727,3 +1727,7 @@ class CuraApplication(QtApplication):
|
||||
node = node.getParent()
|
||||
|
||||
Selection.add(node)
|
||||
|
||||
@pyqtSlot()
|
||||
def showMoreInformationDialogForAnonymousDataCollection(self):
|
||||
self._plugin_registry.getPluginObject("SliceInfoPlugin").showMoreInfoDialog()
|
||||
|
151
plugins/SliceInfoPlugin/MoreInfoWindow.qml
Normal file
151
plugins/SliceInfoPlugin/MoreInfoWindow.qml
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2018 Ultimaker B.V.
|
||||
// Cura 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: true // 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
|
||||
{
|
||||
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 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
|
||||
}
|
||||
|
||||
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 data")
|
||||
exclusiveGroup: group
|
||||
onClicked:
|
||||
{
|
||||
baseDialog.allowSendData = !checked;
|
||||
}
|
||||
}
|
||||
RadioButton
|
||||
{
|
||||
id: allowSendButton
|
||||
text: catalog.i18nc("@text:window", "Allow sending these data to Ultimaker and help us 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,12 @@
|
||||
# Copyright (c) 2015 Ultimaker B.V.
|
||||
# Copyright (c) 2018 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 os
|
||||
import platform
|
||||
import time
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QObject
|
||||
|
||||
from UM.Extension import Extension
|
||||
from UM.Application import Application
|
||||
@ -11,18 +15,11 @@ 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.PluginRegistry import PluginRegistry
|
||||
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")
|
||||
|
||||
@ -30,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,
|
||||
@ -47,32 +48,64 @@ 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":
|
||||
Preferences.getInstance().addPreference("info/send_slice_info", False)
|
||||
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"):
|
||||
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 +113,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 +125,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 +157,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 +207,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
|
||||
|
||||
|
113
plugins/SliceInfoPlugin/example_data.json
Normal file
113
plugins/SliceInfoPlugin/example_data.json
Normal file
@ -0,0 +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",
|
||||
"type": "PLA",
|
||||
"brand": "Generic"
|
||||
},
|
||||
"material_used": 0.84,
|
||||
"variant": "AA 0.4",
|
||||
"nozzle_size": 0.4,
|
||||
"extruder_settings": {
|
||||
"wall_line_count": 3,
|
||||
"retraction_enable": true,
|
||||
"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",
|
||||
"type": "PVA",
|
||||
"brand": "Generic"
|
||||
},
|
||||
"material_used": 0.5,
|
||||
"variant": "BB 0.4",
|
||||
"nozzle_size": 0.4,
|
||||
"extruder_settings": {
|
||||
"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": 220
|
||||
}
|
||||
}
|
||||
],
|
||||
"quality_profile": "fast",
|
||||
"models": [
|
||||
{
|
||||
"hash": "b72789b9beb5366dff20b1cf501020c3d4d4df7dc2295ecd0fddd0a6436df070",
|
||||
"bounding_box": {
|
||||
"minimum": {
|
||||
"x": -10.0,
|
||||
"y": 0.0,
|
||||
"z": -5.0
|
||||
},
|
||||
"maximum": {
|
||||
"x": 9.999999046325684,
|
||||
"y": 40.0,
|
||||
"z": 5.0
|
||||
}
|
||||
},
|
||||
"transformation": {
|
||||
"data": "[[ 1. 0. 0. 0.] [ 0. 1. 0. 20.] [ 0. 0. 1. 0.] [ 0. 0. 0. 1.]]"
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
],
|
||||
"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"
|
||||
}
|
@ -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
|
||||
{
|
||||
@ -97,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
|
||||
@ -366,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?")
|
||||
@ -380,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?")
|
||||
@ -393,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?")
|
||||
@ -426,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?")
|
||||
@ -453,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?")
|
||||
@ -467,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?")
|
||||
@ -481,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?")
|
||||
@ -495,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?")
|
||||
@ -508,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")
|
||||
@ -531,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" })
|
||||
@ -591,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" })
|
||||
@ -631,8 +653,9 @@ UM.PreferencesPage
|
||||
text: catalog.i18nc("@label","Privacy")
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
visible: plugins.find("id", "UpdateChecker") > -1
|
||||
UM.TooltipArea
|
||||
{
|
||||
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?")
|
||||
@ -646,8 +669,9 @@ UM.PreferencesPage
|
||||
}
|
||||
}
|
||||
|
||||
UM.TooltipArea {
|
||||
visible: plugins.find("id", "SliceInfoPlugin") > -1
|
||||
UM.TooltipArea
|
||||
{
|
||||
visible: pluginExistsAndEnabled("SliceInfoPlugin")
|
||||
width: childrenRect.width
|
||||
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.")
|
||||
@ -659,6 +683,17 @@ 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
|
||||
text: catalog.i18nc("@action:button", "More information")
|
||||
onClicked:
|
||||
{
|
||||
CuraApplication.showMoreInformationDialogForAnonymousDataCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
@ -674,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")
|
||||
@ -688,21 +724,29 @@ 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
|
||||
{
|
||||
target: UM.Preferences
|
||||
onPreferenceChanged:
|
||||
{
|
||||
sendDataCheckbox.checked = boolCheck(UM.Preferences.getValue("info/send_slice_info"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user