Merge branch 'master' into WIP_onboarding

This commit is contained in:
Ghostkeeper 2019-04-03 11:53:40 +02:00
commit ae9395aebb
No known key found for this signature in database
GPG key ID: 86BEF881AE2CF276
13 changed files with 69 additions and 104 deletions

View file

@ -42,7 +42,14 @@ class CuraFormulaFunctions:
try: try:
extruder_stack = global_stack.extruders[str(extruder_position)] extruder_stack = global_stack.extruders[str(extruder_position)]
except KeyError: except KeyError:
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available" % (property_key, extruder_position)) if extruder_position != 0:
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. Returning the result form extruder 0 instead" % (property_key, extruder_position))
# This fixes a very specific fringe case; If a profile was created for a custom printer and one of the
# extruder settings has been set to non zero and the profile is loaded for a machine that has only a single extruder
# it would cause all kinds of issues (and eventually a crash).
# See https://github.com/Ultimaker/Cura/issues/5535
return self.getValueInExtruder(0, property_key, context)
Logger.log("w", "Value for %s of extruder %s was requested, but that extruder is not available. " % (property_key, extruder_position))
return None return None
value = extruder_stack.getRawProperty(property_key, "value", context = context) value = extruder_stack.getRawProperty(property_key, "value", context = context)

View file

@ -85,7 +85,15 @@ class GlobalStack(CuraContainerStack):
# Requesting it from the metadata actually gets them as strings (as that's what you get from serializing). # Requesting it from the metadata actually gets them as strings (as that's what you get from serializing).
# But we do want them returned as a list of ints (so the rest of the code can directly compare) # But we do want them returned as a list of ints (so the rest of the code can directly compare)
connection_types = self.getMetaDataEntry("connection_type", "").split(",") connection_types = self.getMetaDataEntry("connection_type", "").split(",")
return [int(connection_type) for connection_type in connection_types if connection_type != ""] result = []
for connection_type in connection_types:
if connection_type != "":
try:
result.append(int(connection_type))
except ValueError:
# We got invalid data, probably a None.
pass
return result
## \sa configuredConnectionTypes ## \sa configuredConnectionTypes
def addConfiguredConnectionType(self, connection_type: int) -> None: def addConfiguredConnectionType(self, connection_type: int) -> None:

View file

@ -14,7 +14,7 @@ Rectangle
Column Column
{ {
height: childrenRect.height + 2 * padding height: childrenRect.height + 2 * padding
spacing: UM.Theme.getSize("toolbox_showcase_spacing").width spacing: UM.Theme.getSize("default_margin").width
width: parent.width width: parent.width
padding: UM.Theme.getSize("wide_margin").height padding: UM.Theme.getSize("wide_margin").height
Label Label

View file

@ -61,7 +61,7 @@ Button
{ {
target: label target: label
font: UM.Theme.getFont("medium_bold") font: UM.Theme.getFont("medium_bold")
color: UM.Theme.getColor("toolbox_header_button_text_active") color: UM.Theme.getColor("action_button_text")
} }
} }
] ]

View file

@ -145,9 +145,17 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
## Checks whether the given network key is found in the cloud's host name ## Checks whether the given network key is found in the cloud's host name
def matchesNetworkKey(self, network_key: str) -> bool: def matchesNetworkKey(self, network_key: str) -> bool:
# A network key looks like "ultimakersystem-aabbccdd0011._ultimaker._tcp.local." # Typically, a network key looks like "ultimakersystem-aabbccdd0011._ultimaker._tcp.local."
# the host name should then be "ultimakersystem-aabbccdd0011" # the host name should then be "ultimakersystem-aabbccdd0011"
return network_key.startswith(self.clusterData.host_name) if network_key.startswith(self.clusterData.host_name):
return True
# However, for manually added printers, the local IP address is used in lieu of a proper
# network key, so check for that as well
if self.clusterData.host_internal_ip is not None and network_key.find(self.clusterData.host_internal_ip):
return True
return False
## Set all the interface elements and texts for this output device. ## Set all the interface elements and texts for this output device.
def _setInterfaceElements(self) -> None: def _setInterfaceElements(self) -> None:

View file

@ -16,13 +16,14 @@ class CloudClusterResponse(BaseCloudModel):
# \param status: The status of the cluster authentication (active or inactive). # \param status: The status of the cluster authentication (active or inactive).
# \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on. # \param host_version: The firmware version of the cluster host. This is where the Stardust client is running on.
def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str,
host_version: Optional[str] = None, **kwargs) -> None: host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, **kwargs) -> None:
self.cluster_id = cluster_id self.cluster_id = cluster_id
self.host_guid = host_guid self.host_guid = host_guid
self.host_name = host_name self.host_name = host_name
self.status = status self.status = status
self.is_online = is_online self.is_online = is_online
self.host_version = host_version self.host_version = host_version
self.host_internal_ip = host_internal_ip
super().__init__(**kwargs) super().__init__(**kwargs)
# Validates the model, raising an exception if the model is invalid. # Validates the model, raising an exception if the model is invalid.

View file

@ -77,13 +77,15 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice):
self.setIconName("print") self.setIconName("print")
if PluginRegistry.getInstance() is not None: self._output_controller = LegacyUM3PrinterOutputController(self)
def _createMonitorViewFromQML(self) -> None:
if self._monitor_view_qml_path is None and PluginRegistry.getInstance() is not None:
self._monitor_view_qml_path = os.path.join( self._monitor_view_qml_path = os.path.join(
PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"), PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
"resources", "qml", "MonitorStage.qml" "resources", "qml", "MonitorStage.qml"
) )
super()._createMonitorViewFromQML()
self._output_controller = LegacyUM3PrinterOutputController(self)
def _onAuthenticationStateChanged(self): def _onAuthenticationStateChanged(self):
# We only accept commands if we are authenticated. # We only accept commands if we are authenticated.

View file

@ -7,6 +7,7 @@ from UM.OutputDevice.OutputDeviceManager import OutputDeviceManager
from cura.UltimakerCloudAuthentication import CuraCloudAPIRoot from cura.UltimakerCloudAuthentication import CuraCloudAPIRoot
from ...src.Cloud import CloudApiClient from ...src.Cloud import CloudApiClient
from ...src.Cloud import CloudOutputDeviceManager from ...src.Cloud import CloudOutputDeviceManager
from ...src.Cloud.Models.CloudClusterResponse import CloudClusterResponse
from .Fixtures import parseFixture, readFixture from .Fixtures import parseFixture, readFixture
from .NetworkManagerMock import NetworkManagerMock, FakeSignal from .NetworkManagerMock import NetworkManagerMock, FakeSignal
@ -55,7 +56,9 @@ class TestCloudOutputDeviceManager(TestCase):
devices = self.device_manager.getOutputDevices() devices = self.device_manager.getOutputDevices()
# TODO: Check active device # TODO: Check active device
response_clusters = self.clusters_response.get("data", []) response_clusters = []
for cluster in self.clusters_response.get("data", []):
response_clusters.append(CloudClusterResponse(**cluster).toDict())
manager_clusters = sorted([device.clusterData.toDict() for device in self.manager._remote_clusters.values()], manager_clusters = sorted([device.clusterData.toDict() for device in self.manager._remote_clusters.values()],
key=lambda cluster: cluster['cluster_id'], reverse=True) key=lambda cluster: cluster['cluster_id'], reverse=True)
self.assertEqual(response_clusters, manager_clusters) self.assertEqual(response_clusters, manager_clusters)
@ -97,7 +100,7 @@ class TestCloudOutputDeviceManager(TestCase):
self.assertTrue(self.device_manager.getOutputDevice(cluster1["cluster_id"]).isConnected()) self.assertTrue(self.device_manager.getOutputDevice(cluster1["cluster_id"]).isConnected())
self.assertIsNone(self.device_manager.getOutputDevice(cluster2["cluster_id"])) self.assertIsNone(self.device_manager.getOutputDevice(cluster2["cluster_id"]))
self.assertEquals([], active_machine_mock.setMetaDataEntry.mock_calls) self.assertEqual([], active_machine_mock.setMetaDataEntry.mock_calls)
def test_device_connects_by_network_key(self): def test_device_connects_by_network_key(self):
active_machine_mock = self.app.getGlobalContainerStack.return_value active_machine_mock = self.app.getGlobalContainerStack.return_value

View file

@ -208,7 +208,7 @@ class TestSendMaterialJob(TestCase):
self.assertEqual(1, device_mock.createFormPart.call_count) self.assertEqual(1, device_mock.createFormPart.call_count)
self.assertEqual(1, device_mock.postFormWithParts.call_count) self.assertEqual(1, device_mock.postFormWithParts.call_count)
self.assertEquals( self.assertEqual(
[call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", "<xml></xml>"), [call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", "<xml></xml>"),
call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)], call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
device_mock.method_calls) device_mock.method_calls)
@ -238,7 +238,7 @@ class TestSendMaterialJob(TestCase):
self.assertEqual(1, device_mock.createFormPart.call_count) self.assertEqual(1, device_mock.createFormPart.call_count)
self.assertEqual(1, device_mock.postFormWithParts.call_count) self.assertEqual(1, device_mock.postFormWithParts.call_count)
self.assertEquals( self.assertEqual(
[call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", "<xml></xml>"), [call.createFormPart("name=\"file\"; filename=\"generic_pla_white.xml.fdm_material\"", "<xml></xml>"),
call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)], call.postFormWithParts(target = "materials/", parts = ["_xXx_"], on_finished = job.sendingFinished)],
device_mock.method_calls) device_mock.method_calls)

View file

@ -4092,7 +4092,7 @@
"description": "Amount of offset applied to all support polygons in each layer. Positive values can smooth out the support areas and result in more sturdy support.", "description": "Amount of offset applied to all support polygons in each layer. Positive values can smooth out the support areas and result in more sturdy support.",
"unit": "mm", "unit": "mm",
"type": "float", "type": "float",
"default_value": 0.2, "default_value": 0,
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"minimum_value_warning": "-1 * machine_nozzle_size", "minimum_value_warning": "-1 * machine_nozzle_size",
"maximum_value_warning": "10 * machine_nozzle_size", "maximum_value_warning": "10 * machine_nozzle_size",

View file

@ -68,6 +68,7 @@ Column
property var printMaterialLengths: PrintInformation.materialLengths property var printMaterialLengths: PrintInformation.materialLengths
property var printMaterialWeights: PrintInformation.materialWeights property var printMaterialWeights: PrintInformation.materialWeights
property var printMaterialCosts: PrintInformation.materialCosts
text: text:
{ {
@ -77,6 +78,7 @@ Column
} }
var totalLengths = 0 var totalLengths = 0
var totalWeights = 0 var totalWeights = 0
var totalCosts = 0.0
if (printMaterialLengths) if (printMaterialLengths)
{ {
for(var index = 0; index < printMaterialLengths.length; index++) for(var index = 0; index < printMaterialLengths.length; index++)
@ -85,9 +87,16 @@ Column
{ {
totalLengths += printMaterialLengths[index] totalLengths += printMaterialLengths[index]
totalWeights += Math.round(printMaterialWeights[index]) totalWeights += Math.round(printMaterialWeights[index])
var cost = printMaterialCosts[index] == undefined ? 0.0 : printMaterialCosts[index]
totalCosts += cost
} }
} }
} }
if(totalCosts > 0)
{
var costString = "%1 %2".arg(UM.Preferences.getValue("cura/currency")).arg(totalCosts.toFixed(2))
return totalWeights + "g · " + totalLengths.toFixed(2) + "m · " + costString
}
return totalWeights + "g · " + totalLengths.toFixed(2) + "m" return totalWeights + "g · " + totalLengths.toFixed(2) + "m"
} }
source: UM.Theme.getIcon("spool") source: UM.Theme.getIcon("spool")

View file

@ -103,15 +103,11 @@ QtObject
// This property will be back-propagated when the width of the label is calculated // This property will be back-propagated when the width of the label is calculated
property var buttonWidth: 0 property var buttonWidth: 0
background: Item background: Rectangle
{ {
id: backgroundRectangle
implicitHeight: control.height implicitHeight: control.height
implicitWidth: buttonWidth implicitWidth: buttonWidth
Rectangle
{
id: buttonFace
implicitHeight: parent.height
implicitWidth: parent.width
radius: UM.Theme.getSize("action_button_radius").width radius: UM.Theme.getSize("action_button_radius").width
color: color:
@ -129,7 +125,7 @@ QtObject
return UM.Theme.getColor("main_window_header_button_background_inactive") return UM.Theme.getColor("main_window_header_button_background_inactive")
} }
} }
}
} }
label: Item label: Item
@ -168,6 +164,8 @@ QtObject
buttonWidth = width buttonWidth = width
} }
} }
} }
} }
@ -398,73 +396,6 @@ QtObject
} }
} }
// Combobox with items with colored rectangles
property Component combobox_color: Component
{
ComboBoxStyle
{
background: Rectangle
{
color: !enabled ? UM.Theme.getColor("setting_control_disabled") : control._hovered ? UM.Theme.getColor("setting_control_highlight") : UM.Theme.getColor("setting_control")
border.width: UM.Theme.getSize("default_lining").width
border.color: !enabled ? UM.Theme.getColor("setting_control_disabled_border") : control._hovered ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border")
radius: UM.Theme.getSize("setting_control_radius").width
}
label: Item
{
Label
{
anchors.left: parent.left
anchors.leftMargin: UM.Theme.getSize("default_lining").width
anchors.right: swatch.left
anchors.rightMargin: UM.Theme.getSize("default_lining").width
anchors.verticalCenter: parent.verticalCenter
text: control.currentText
font: UM.Theme.getFont("default")
color: !enabled ? UM.Theme.getColor("setting_control_disabled_text") : UM.Theme.getColor("setting_control_text")
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
UM.RecolorImage
{
id: swatch
height: Math.round(control.height / 2)
width: height
anchors.right: downArrow.left
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: UM.Theme.getSize("default_margin").width
sourceSize.width: width
sourceSize.height: height
source: UM.Theme.getIcon("extruder_button")
color: (control.color_override !== "") ? control.color_override : control.color
}
UM.RecolorImage
{
id: downArrow
anchors.right: parent.right
anchors.rightMargin: UM.Theme.getSize("default_lining").width * 2
anchors.verticalCenter: parent.verticalCenter
source: UM.Theme.getIcon("arrow_bottom")
width: UM.Theme.getSize("standard_arrow").width
height: UM.Theme.getSize("standard_arrow").height
sourceSize.width: width + 5 * screenScaleFactor
sourceSize.height: width + 5 * screenScaleFactor
color: UM.Theme.getColor("setting_control_button")
}
}
}
}
property Component checkbox: Component property Component checkbox: Component
{ {
CheckBoxStyle CheckBoxStyle

View file

@ -393,7 +393,6 @@
"printer_config_matched": [50, 130, 255, 255], "printer_config_matched": [50, 130, 255, 255],
"printer_config_mismatch": [127, 127, 127, 255], "printer_config_mismatch": [127, 127, 127, 255],
"toolbox_header_button_text_active": [0, 0, 0, 255],
"toolbox_header_button_text_inactive": [0, 0, 0, 255], "toolbox_header_button_text_inactive": [0, 0, 0, 255],
"favorites_header_bar": [245, 245, 245, 255], "favorites_header_bar": [245, 245, 245, 255],
@ -592,10 +591,8 @@
"toolbox_thumbnail_large": [12.0, 10.0], "toolbox_thumbnail_large": [12.0, 10.0],
"toolbox_footer": [1.0, 4.5], "toolbox_footer": [1.0, 4.5],
"toolbox_footer_button": [8.0, 2.5], "toolbox_footer_button": [8.0, 2.5],
"toolbox_showcase_spacing": [1.0, 1.0],
"toolbox_header_tab": [8.0, 4.0], "toolbox_header_tab": [8.0, 4.0],
"toolbox_detail_header": [1.0, 14.0], "toolbox_detail_header": [1.0, 14.0],
"toolbox_detail_tile": [1.0, 8.0],
"toolbox_back_column": [6.0, 1.0], "toolbox_back_column": [6.0, 1.0],
"toolbox_back_button": [6.0, 2.0], "toolbox_back_button": [6.0, 2.0],
"toolbox_installed_tile": [1.0, 8.0], "toolbox_installed_tile": [1.0, 8.0],
@ -603,7 +600,6 @@
"toolbox_heading_label": [1.0, 3.8], "toolbox_heading_label": [1.0, 3.8],
"toolbox_header": [1.0, 4.0], "toolbox_header": [1.0, 4.0],
"toolbox_header_highlight": [0.25, 0.25], "toolbox_header_highlight": [0.25, 0.25],
"toolbox_progress_bar": [8.0, 0.5],
"toolbox_chart_row": [1.0, 2.0], "toolbox_chart_row": [1.0, 2.0],
"toolbox_action_button": [8.0, 2.5], "toolbox_action_button": [8.0, 2.5],
"toolbox_loader": [2.0, 2.0], "toolbox_loader": [2.0, 2.0],