mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 14:37:29 -06:00
Add more info dialog
CURA-5204
This commit is contained in:
parent
0fbb067508
commit
40eedbcf70
6 changed files with 337 additions and 9 deletions
9
cura/CuraAppSignals.py
Normal file
9
cura/CuraAppSignals.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
|
||||
|
||||
class CuraAppSignals(QObject):
|
||||
|
||||
showMoreInfoOnAnonymousDataCollection = pyqtSignal()
|
||||
|
||||
def __init__(self, parent = None):
|
||||
super().__init__(parent)
|
|
@ -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
|
||||
|
|
158
plugins/SliceInfoPlugin/MoreInfoWindow.qml
Normal file
158
plugins/SliceInfoPlugin/MoreInfoWindow.qml
Normal file
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"):
|
||||
|
|
101
plugins/SliceInfoPlugin/example_data.json
Normal file
101
plugins/SliceInfoPlugin/example_data.json
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue