This commit is contained in:
fieldOfView 2016-09-14 08:52:05 +02:00
commit 6334f74fc6
38 changed files with 125 additions and 47 deletions

View file

@ -2,6 +2,7 @@ from UM.i18n import i18nCatalog
from UM.OutputDevice.OutputDevice import OutputDevice
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtWidgets import QMessageBox
import UM.Settings.ContainerRegistry
from enum import IntEnum # For the connection state tracking.
from UM.Logger import Logger
@ -285,7 +286,7 @@ class PrinterOutputDevice(QObject, OutputDevice):
result.append(i18n_catalog.i18nc("@item:material", "No material loaded"))
continue
containers = self._container_registry.findInstanceContainers(type = "material", guid = material_id)
containers = self._container_registry.findInstanceContainers(type = "material", GUID = material_id)
if containers:
result.append(containers[0].getName())
else:

View file

@ -349,6 +349,9 @@ class ContainerManager(QObject):
except NotImplementedError:
return { "status": "error", "message": "Unable to serialize container"}
if contents is None:
return {"status": "error", "message": "Serialization returned None. Unable to write to file"}
with UM.SaveFile(file_url, "w") as f:
f.write(contents)
@ -586,6 +589,7 @@ class ContainerManager(QObject):
new_container = container.duplicate(self._createUniqueId(stack_id, new_name), new_name)
self._container_registry.addContainer(new_container)
else:
UM.Logger.log("w", "Unable to duplicate profile. It has the wrong type.")
return ""
return new_name
@ -688,7 +692,9 @@ class ContainerManager(QObject):
filter_by_material = False
if global_stack.getMetaDataEntry("has_machine_quality"):
criteria["definition"] = global_stack.getBottom().getId()
definition = global_stack.getBottom()
definition_id = definition.getMetaDataEntry("quality_definition", definition.getId())
criteria["definition"] = definition_id
filter_by_material = global_stack.getMetaDataEntry("has_materials")

View file

@ -227,6 +227,16 @@ class CuraEngineBackend(Backend):
if job.isCancelled() or job.getError() or job.getResult() == StartSliceJob.StartJobResult.Error:
return
if job.getResult() == StartSliceJob.StartJobResult.MaterialIncompatible:
if Application.getInstance().getPlatformActivity:
self._error_message = Message(catalog.i18nc("@info:status",
"The selected material is imcompatible with the selected machine or configuration."))
self._error_message.show()
self.backendStateChange.emit(BackendState.Error)
else:
self.backendStateChange.emit(BackendState.NotStarted)
return
if job.getResult() == StartSliceJob.StartJobResult.SettingError:
if Application.getInstance().getPlatformActivity:
self._error_message = Message(catalog.i18nc("@info:status", "Unable to slice with the current settings. Please check your settings for errors."))

View file

@ -24,6 +24,7 @@ class StartJobResult(IntEnum):
Error = 2
SettingError = 3
NothingToSlice = 4
MaterialIncompatible = 5
## Formatter class that handles token expansion in start/end gcod
@ -86,7 +87,7 @@ class StartSliceJob(Job):
material = extruder_stack.findContainer({"type": "material"})
if material:
if material.getMetaDataEntry("compatible") == False:
self.setResult(StartJobResult.SettingError)
self.setResult(StartJobResult.MaterialIncompatible)
return
# Don't slice if there is a per object setting with an error value.

View file

@ -1,6 +1,8 @@
# Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.
from cura.CuraApplication import CuraApplication
from UM.Extension import Extension
from UM.Application import Application
from UM.Preferences import Preferences
@ -18,6 +20,7 @@ import math
import urllib.request
import urllib.parse
import ssl
import hashlib
catalog = i18nCatalog("cura")
@ -43,9 +46,11 @@ class SliceInfoJob(Job):
if Platform.isOSX():
kwoptions["context"] = ssl._create_unverified_context()
Logger.log("d", "Sending anonymous slice info to [%s]...", self.url)
try:
f = urllib.request.urlopen(self.url, **kwoptions)
Logger.log("i", "Sent anonymous slice info to %s", self.url)
Logger.log("i", "Sent anonymous slice info.")
f.close()
except urllib.error.HTTPError as http_exception:
Logger.log("e", "An HTTP error occurred while trying to send slice information: %s" % http_exception)
@ -56,7 +61,7 @@ class SliceInfoJob(Job):
# 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):
info_url = "https://stats.youmagine.com/curastats/slice"
info_url = "http://stats.youmagine.com/curastats/slice"
def __init__(self):
super().__init__()
@ -80,6 +85,16 @@ class SliceInfo(Extension):
Logger.log("d", "'info/send_slice_info' is turned off.")
return # Do nothing, user does not want to send data
# Listing all files placed on the buildplate
modelhashes = []
for node in DepthFirstIterator(CuraApplication.getInstance().getController().getScene().getRoot()):
if type(node) is not SceneNode or not node.getMeshData():
continue
modelhashes.append(node.getMeshData().getHash())
# Creating md5sums and formatting them as discussed on JIRA
modelhash_formatted = ",".join(modelhashes)
global_container_stack = Application.getInstance().getGlobalContainerStack()
# Get total material used (in mm^3)
@ -89,27 +104,6 @@ class SliceInfo(Extension):
# TODO: Send material per extruder instead of mashing it on a pile
material_used = math.pi * material_radius * material_radius * sum(print_information.materialLengths) #Volume of all materials used
# Get model information (bounding boxes, hashes and transformation matrix)
models_info = []
for node in DepthFirstIterator(Application.getInstance().getController().getScene().getRoot()):
if type(node) is SceneNode and node.getMeshData() and node.getMeshData().getVertices() is not None:
if not getattr(node, "_outside_buildarea", False):
model_info = {}
model_info["hash"] = node.getMeshData().getHash()
model_info["bounding_box"] = {}
model_info["bounding_box"]["minimum"] = {}
model_info["bounding_box"]["minimum"]["x"] = node.getBoundingBox().minimum.x
model_info["bounding_box"]["minimum"]["y"] = node.getBoundingBox().minimum.y
model_info["bounding_box"]["minimum"]["z"] = node.getBoundingBox().minimum.z
model_info["bounding_box"]["maximum"] = {}
model_info["bounding_box"]["maximum"]["x"] = node.getBoundingBox().maximum.x
model_info["bounding_box"]["maximum"]["y"] = node.getBoundingBox().maximum.y
model_info["bounding_box"]["maximum"]["z"] = node.getBoundingBox().maximum.z
model_info["transformation"] = str(node.getWorldTransformation().getData())
models_info.append(model_info)
# Bundle the collected data
submitted_data = {
"processor": platform.processor(),
@ -117,7 +111,7 @@ class SliceInfo(Extension):
"platform": platform.platform(),
"settings": global_container_stack.serialize(), # global_container with references on used containers
"version": Application.getInstance().getVersion(),
"modelhash": "None",
"modelhash": modelhash_formatted,
"printtime": print_information.currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601),
"filament": material_used,
"language": Preferences.getInstance().getValue("general/language"),

View file

@ -91,12 +91,9 @@ class MachineInstance:
if has_machine_qualities: #This machine now has machine-quality profiles.
active_material += "_" + variant_materials #That means that the profile was split into multiple.
current_settings = "" #The profile didn't know the definition ID when it was upgraded, so it will have been invalid. Sorry, your current settings are lost now.
else:
current_settings = self._name + "_current_settings"
containers = [
current_settings,
"", #The current profile doesn't know the definition ID when it was upgraded, only the instance ID, so it will be invalid. Sorry, your current settings are lost now.
active_quality_changes,
active_quality,
active_material,

View file

@ -80,7 +80,7 @@ class Profile:
import VersionUpgrade21to22 # Import here to prevent circular dependencies.
if self._name == "Current settings":
self._filename += "_current_settings" #This resolves a duplicate ID arising from how Cura 2.1 stores its current settings.
return None #Can't upgrade these, because the new current profile needs to specify the definition ID and the old file only had the machine instance, not the definition.
config = configparser.ConfigParser(interpolation = None)

View file

@ -85,9 +85,6 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer):
# base file: global settings + supported machines
# machine / variant combination: only changes for itself.
def serialize(self):
if self._read_only:
return
registry = UM.Settings.ContainerRegistry.getInstance()
base_file = self.getMetaDataEntry("base_file", "")

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "BQ Prusa i3 Hephestos" },
"machine_start_gcode": {
"default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 X0 Y0 ;move to the X/Y origin (Home)\nG28 Z0 ;move to the Z origin (Home)\nG1 Z15.0 F1200 ;move Z to position 15.0 mm\nG92 E0 ;zero the extruded length\nG1 E20 F200 ;extrude 20mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F7200 ;set feedrate to 120 mm/s\n; -- end of START GCODE --"
},

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "BQ Hephestos 2" },
"machine_start_gcode": { "default_value": "; -- START GCODE --\nM104 S{material_print_temperature} ; Heat up extruder while leveling\nM800 ; Custom GCODE to fire start print procedure\nM109 S{material_print_temperature} ; Makes sure the temperature is correct before printing\n; -- end of START GCODE --" },
"machine_end_gcode": { "default_value": "; -- END GCODE --\nM801 ; Custom GCODE to fire end print procedure\n; -- end of END GCODE --" },
"machine_width": { "default_value": 210 },

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "BQ Prusa i3 Hephestos XL" },
"machine_start_gcode": {
"default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 X0 Y0 ;move to the X/Y origin (Home)\nG28 Z0 ;move to the Z origin (Home)\nG1 Z15.0 F1200 ;move Z to position 15.0 mm\nG92 E0 ;zero the extruded length\nG1 E20 F200 ;extrude 20mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F7200 ;set feedrate to 120 mm/s\n; -- end of START GCODE --"
},

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "BQ Witbox" },
"machine_start_gcode": {
"default_value": "; -- START GCODE --\nG21 ;set units to millimetres\nG90 ;set to absolute positioning\nM106 S0 ;set fan speed to zero (turned off)\nG28 X0 Y0 ;move to the X/Y origin (Home)\nG28 Z0 ;move to the Z origin (Home)\nG1 Z15.0 F1200 ;move Z to position 15.0 mm\nG92 E0 ;zero the extruded length\nG1 E20 F200 ;extrude 20mm of feed stock\nG92 E0 ;zero the extruded length again\nG1 F7200 ;set feedrate to 120 mm/s\n; -- end of START GCODE --"
},

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "BQ Witbox 2" },
"machine_start_gcode": {
"default_value": "; -- START GCODE --\nM800 ; Custom GCODE to fire start print procedure\n; -- end of START GCODE --"
},

View file

@ -29,6 +29,16 @@
"icon": "category_machine",
"children":
{
"machine_name":
{
"label": "Machine Type",
"description": "The name of your 3D printer model.",
"default_value": "Unknown",
"type": "str",
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
},
"machine_show_variants":
{
"label": "Show machine variants",
@ -2495,7 +2505,7 @@
"description": "Generate a dense interface between the model and the support. This will create a skin at the top of the support on which the model is printed and at the bottom of the support, where it rests on the model.",
"type": "bool",
"default_value": false,
"global_inherits_stack": "support_extruder_nr",
"global_inherits_stack": "support_interface_extruder_nr",
"enabled": "support_enable",
"settable_per_mesh": true
},
@ -2705,6 +2715,7 @@
"raft": "Raft"
},
"default_value": "brim",
"resolve": "'raft' if 'raft' in extruderValues('adhesion_type') else ('brim' if 'brim' in extruderValues('adhesion_type') else 'skirt')",
"settable_per_mesh": false,
"settable_per_extruder": false
},
@ -3283,7 +3294,7 @@
"type": "extruder",
"default_value": "0",
"value": "support_extruder_nr",
"enabled": "support_enable and machine_extruder_count > 1 and extruderValue(support_interface_extruder_nr, 'support_interface_enable')",
"enabled": "support_enable and machine_extruder_count > 1",
"settable_per_mesh": false,
"settable_per_extruder": false
}
@ -3296,6 +3307,7 @@
"type": "bool",
"enabled": "machine_extruder_count > 1",
"default_value": false,
"resolve": "max(extruderValues('prime_tower_enable'))",
"settable_per_mesh": false,
"settable_per_extruder": false
},

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "German RepRap Neo" },
"machine_width": {
"default_value": 150
},

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "Innovo INVENTOR" },
"machine_width": {
"default_value": 340
},

View file

@ -12,6 +12,7 @@
},
"overrides": {
"machine_name": { "default_value": "Malyan M180" },
"machine_width": {
"default_value": 230
},

View file

@ -13,6 +13,7 @@
},
"overrides": {
"machine_name": { "default_value": "3DMaker Starter" },
"machine_width": {
"default_value": 210
},

View file

@ -12,6 +12,7 @@
"platform": "mankati_fullscale_xt_plus_platform.stl"
},
"overrides": {
"machine_name": { "default_value": "Mankati Fullscale XT Plus" },
"machine_width": { "default_value": 260 },
"machine_depth": { "default_value": 260 },
"machine_height": { "default_value": 300 },

View file

@ -19,6 +19,7 @@
],
"overrides": {
"machine_name": { "default_value": "Mendel90" },
"machine_start_gcode": {
"default_value": "G21 ;metric values\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\nM107 ;start with the fan off\nG1 X90 Y200 F6000 ;go to the middle of the front\nG1 Z0.05 ;close to the bed\nG1 Z0.3 ;lift Z\n"
},

View file

@ -13,6 +13,7 @@
},
"overrides": {
"machine_name": { "default_value": "Printrbot Simple" },
"machine_heated_bed": { "default_value": false },
"machine_width": { "default_value": 150 },
"machine_height": { "default_value": 150 },

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "Prusa i3" },
"machine_heated_bed": {
"default_value": true
},

View file

@ -15,6 +15,7 @@
},
"overrides": {
"machine_name": { "default_value": "Prusa i3 Mk2" },
"machine_heated_bed": { "default_value": true },
"machine_width": { "default_value": 250 },
"machine_height": { "default_value": 200 },

View file

@ -14,6 +14,7 @@
},
"overrides": {
"machine_name": { "default_value": "Prusa i3 xl" },
"machine_heated_bed": {
"default_value": true
},

View file

@ -13,6 +13,7 @@
},
"overrides": {
"machine_name": { "default_value": "RigidBot" },
"machine_width": {
"default_value": 254
},

View file

@ -13,6 +13,7 @@
},
"overrides": {
"machine_name": { "default_value": "RigidBotBig" },
"machine_width": {
"default_value": 400
},

View file

@ -18,6 +18,7 @@
"supported_actions":["UpgradeFirmware"]
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2" },
"machine_start_gcode" : {
"default_value": "",
"value": "\"\" if machine_gcode_flavor == \"UltiGCode\" else \"G21 ;metric values\\nG90 ;absolute positioning\\nM82 ;set extruder to absolute mode\\nM107 ;start with the fan off\\nG1 X10 Y0 F4000;move X/Y to min endstops\\nG28 Z0 ;move Z to bottom endstops\\nG1 Z15.0 F9000 ;move the platform to 15mm\\nG92 E0 ;zero the extruded length\\nG1 F200 E10 ;extrude 10 mm of feed stock\\nG92 E0 ;zero the extruded length again\\nG1 F9000\\n;Put printing message on LCD screen\\nM117 Printing...\""

View file

@ -16,6 +16,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2 Extended" },
"machine_height": {
"default_value": 305
}

View file

@ -16,6 +16,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2 Extended+" },
"machine_height": {
"default_value": 305
}

View file

@ -17,6 +17,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2 Go" },
"machine_width": {
"default_value": 120
},

View file

@ -20,6 +20,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker 2+" },
"speed_infill": {
"value": "speed_print"
},

View file

@ -18,6 +18,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker Original" },
"machine_width": {
"default_value": 205
},

View file

@ -23,6 +23,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker Original" },
"machine_width": {
"default_value": 205
},

View file

@ -17,6 +17,7 @@
},
"overrides": {
"machine_name": { "default_value": "Ultimaker Original+" },
"machine_heated_bed": {
"default_value": true
},

View file

@ -12,6 +12,7 @@
},
"overrides": {
"machine_name": { "default_value": "Uniqbot" },
"machine_heated_bed": {
"default_value": false
},

View file

@ -20,18 +20,40 @@ SettingItem
property bool checked:
{
switch(propertyProvider.properties.value)
// FIXME this needs to go away once 'resolve' is combined with 'value' in our data model.
// Stacklevels
// 0: user -> unsaved change
// 1: quality changes -> saved change
// 2: quality
// 3: material -> user changed material in materials page
// 4: variant
// 5: machine
var value;
if ((propertyProvider.properties.resolve != "None") && (stackLevel != 0) && (stackLevel != 1)) {
// We have a resolve function. Indicates that the setting is not settable per extruder and that
// we have to choose between the resolved value (default) and the global value
// (if user has explicitly set this).
value = propertyProvider.properties.resolve;
} else {
value = propertyProvider.properties.value;
}
switch(value)
{
case "True":
return true
return true;
case "False":
return false
return false;
default:
return propertyProvider.properties.value
return value;
}
}
onClicked: { forceActiveFocus(); propertyProvider.setPropertyValue("value", !checked) }
onClicked:
{
forceActiveFocus();
propertyProvider.setPropertyValue("value", !checked);
}
Rectangle
{

View file

@ -96,8 +96,19 @@ SettingItem
}
function updateCurrentIndex() {
// FIXME this needs to go away once 'resolve' is combined with 'value' in our data model.
var value;
if ((propertyProvider.properties.resolve != "None") && (stackLevel != 0) && (stackLevel != 1)) {
// We have a resolve function. Indicates that the setting is not settable per extruder and that
// we have to choose between the resolved value (default) and the global value
// (if user has explicitly set this).
value = propertyProvider.properties.resolve;
} else {
value = propertyProvider.properties.value;
}
for(var i = 0; i < definition.options.length; ++i) {
if(definition.options[i].key == propertyProvider.properties.value) {
if(definition.options[i].key == value) {
currentIndex = i;
return;
}

View file

@ -234,14 +234,15 @@ Column
property var valueError:
{
var data = Cura.ContainerManager.getContainerMetaDataEntry(Cura.MachineManager.activeMaterialId, "compatible")
if(data == "" || data == "True")
{
return false
}
if(data == "False")
{
return true
}
else
{
return false
}
}
enabled: !extrudersList.visible || base.currentExtruderIndex > -1