Merge branch 'STAR-322_cloud-connection' of github.com:Ultimaker/Cura into STAR-322_cloud-connection

This commit is contained in:
Daniel Schiavini 2018-12-04 16:15:19 +01:00
commit 54744b46a7
11 changed files with 123 additions and 32 deletions

View file

@ -527,6 +527,12 @@ class MachineManager(QObject):
return self._global_container_stack.getMetaDataEntry("um_network_key", "") return self._global_container_stack.getMetaDataEntry("um_network_key", "")
return "" return ""
@pyqtProperty(str, notify=printerConnectedStatusChanged)
def activeMachineCloudKey(self) -> str:
if self._global_container_stack:
return self._global_container_stack.getMetaDataEntry("um_cloud_cluster_id", "")
return ""
@pyqtProperty(str, notify = printerConnectedStatusChanged) @pyqtProperty(str, notify = printerConnectedStatusChanged)
def activeMachineNetworkGroupName(self) -> str: def activeMachineNetworkGroupName(self) -> str:
if self._global_container_stack: if self._global_container_stack:

View file

@ -288,8 +288,10 @@ class CloudOutputDevice(NetworkedPrinterOutputDevice):
for updated_job_id in set(current_jobs).intersection(remote_jobs): for updated_job_id in set(current_jobs).intersection(remote_jobs):
self._updateUM3PrintJobOutputModel(current_jobs[updated_job_id], remote_jobs[updated_job_id]) self._updateUM3PrintJobOutputModel(current_jobs[updated_job_id], remote_jobs[updated_job_id])
# TODO: properly handle removed and updated printers # We only have to update when jobs are added or removed
self.printJobsChanged.emit() # updated jobs push their changes via their outputmodel
if len(removed_job_ids) > 0 or len(new_job_ids) > 0:
self.printJobsChanged.emit()
def _addPrintJob(self, job: CloudClusterPrintJob) -> None: def _addPrintJob(self, job: CloudClusterPrintJob) -> None:
try: try:

View file

@ -1,7 +1,8 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2018 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from threading import Timer from typing import Dict, List, Optional
from typing import Dict, List
from PyQt5.QtCore import QTimer
from UM import i18nCatalog from UM import i18nCatalog
from UM.Logger import Logger from UM.Logger import Logger
@ -9,7 +10,6 @@ from UM.Message import Message
from UM.Signal import Signal from UM.Signal import Signal
from cura.CuraApplication import CuraApplication from cura.CuraApplication import CuraApplication
from plugins.UM3NetworkPrinting.src.Cloud.CloudApiClient import CloudApiClient from plugins.UM3NetworkPrinting.src.Cloud.CloudApiClient import CloudApiClient
from .CloudOutputDevice import CloudOutputDevice from .CloudOutputDevice import CloudOutputDevice
from .Models import CloudCluster, CloudErrorObject from .Models import CloudCluster, CloudErrorObject
@ -39,23 +39,27 @@ class CloudOutputDeviceManager:
self._account = application.getCuraAPI().account self._account = application.getCuraAPI().account
self._account.loginStateChanged.connect(self._getRemoteClusters) self._account.loginStateChanged.connect(self._getRemoteClusters)
self._api = CloudApiClient(self._account, self._onApiError) self._api = CloudApiClient(self._account, self._onApiError)
# When switching machines we check if we have to activate a remote cluster. # When switching machines we check if we have to activate a remote cluster.
application.globalContainerStackChanged.connect(self._connectToActiveMachine) application.globalContainerStackChanged.connect(self._connectToActiveMachine)
self._on_cluster_received = Signal() self._on_cluster_received = Signal()
self._on_cluster_received.connect(self._getRemoteClusters) self._on_cluster_received.connect(self._getRemoteClusters)
self.update_timer = QTimer(CuraApplication.getInstance())
self.update_timer.setInterval(self.CHECK_CLUSTER_INTERVAL * 1000)
self.update_timer.setSingleShot(False)
self.update_timer.timeout.connect(self._on_cluster_received.emit)
## Gets all remote clusters from the API. ## Gets all remote clusters from the API.
def _getRemoteClusters(self) -> None: def _getRemoteClusters(self) -> None:
Logger.log("i", "Retrieving remote clusters") Logger.log("i", "Retrieving remote clusters")
if self._account.isLoggedIn: if self._account.isLoggedIn:
self._api.getClusters(self._onGetRemoteClustersFinished) self._api.getClusters(self._onGetRemoteClustersFinished)
# Only start the polling thread after the user is authenticated # Only start the polling timer after the user is authenticated
# The first call to _getRemoteClusters comes from self._account.loginStateChanged # The first call to _getRemoteClusters comes from self._account.loginStateChanged
timer = Timer(5.0, self._on_cluster_received.emit) self.update_timer.start()
timer.start()
## Callback for when the request for getting the clusters. is finished. ## Callback for when the request for getting the clusters. is finished.
def _onGetRemoteClustersFinished(self, clusters: List[CloudCluster]) -> None: def _onGetRemoteClustersFinished(self, clusters: List[CloudCluster]) -> None:
@ -85,7 +89,7 @@ class CloudOutputDeviceManager:
self._output_device_manager.addOutputDevice(device) self._output_device_manager.addOutputDevice(device)
self._remote_clusters[cluster.cluster_id] = device self._remote_clusters[cluster.cluster_id] = device
device.connect() # TODO: remove this device.connect() # TODO: remove this
self._connectToActiveMachine() self._connectToActiveMachine(cluster.cluster_id, cluster.host_name)
## Remove a CloudOutputDevice ## Remove a CloudOutputDevice
# \param cluster: The cluster that was removed # \param cluster: The cluster that was removed
@ -94,11 +98,16 @@ class CloudOutputDeviceManager:
del self._remote_clusters[cluster.cluster_id] del self._remote_clusters[cluster.cluster_id]
## Callback for when the active machine was changed by the user. ## Callback for when the active machine was changed by the user.
def _connectToActiveMachine(self) -> None: def _connectToActiveMachine(self, cluster_id: Optional[str] = None, host_name: Optional[str] = None) -> None:
active_machine = CuraApplication.getInstance().getGlobalContainerStack() active_machine = CuraApplication.getInstance().getGlobalContainerStack()
if not active_machine: if not active_machine:
return return
# TODO: Remove this once correct pairing has been added (see below).
if cluster_id:
active_machine.setMetaDataEntry("um_cloud_cluster_id", cluster_id)
active_machine.setMetaDataEntry("connect_group_name", host_name)
# Check if the stored cluster_id for the active machine is in our list of remote clusters. # Check if the stored cluster_id for the active machine is in our list of remote clusters.
stored_cluster_id = active_machine.getMetaDataEntry("um_cloud_cluster_id") stored_cluster_id = active_machine.getMetaDataEntry("um_cloud_cluster_id")
if stored_cluster_id in self._remote_clusters.keys(): if stored_cluster_id in self._remote_clusters.keys():

View file

@ -7,7 +7,7 @@
"author": "Samuel Pinches", "author": "Samuel Pinches",
"manufacturer": "Alfawise", "manufacturer": "Alfawise",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"preferred_quality_type": "fine", "preferred_quality_type": "fast",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "alfawise_u20_extruder_0" "0": "alfawise_u20_extruder_0"
@ -53,9 +53,6 @@
"material_bed_temperature": { "material_bed_temperature": {
"default_value": 50 "default_value": 50
}, },
"layer_height": {
"default_value": 0.15
},
"layer_height_0": { "layer_height_0": {
"default_value": 0.2 "default_value": 0.2
}, },

View file

@ -7,7 +7,7 @@
"author": "Samuel Pinches", "author": "Samuel Pinches",
"manufacturer": "JGAurora", "manufacturer": "JGAurora",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"preferred_quality_type": "fine", "preferred_quality_type": "fast",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "jgaurora_a1_extruder_0" "0": "jgaurora_a1_extruder_0"
@ -53,9 +53,6 @@
"material_bed_temperature": { "material_bed_temperature": {
"default_value": 67 "default_value": 67
}, },
"layer_height": {
"default_value": 0.15
},
"layer_height_0": { "layer_height_0": {
"default_value": 0.12 "default_value": 0.12
}, },

View file

@ -9,7 +9,7 @@
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform": "jgaurora_a5.stl", "platform": "jgaurora_a5.stl",
"platform_offset": [-242, -101, 273], "platform_offset": [-242, -101, 273],
"preferred_quality_type": "fine", "preferred_quality_type": "fast",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "jgaurora_a5_extruder_0" "0": "jgaurora_a5_extruder_0"
@ -55,9 +55,6 @@
"material_bed_temperature": { "material_bed_temperature": {
"default_value": 67 "default_value": 67
}, },
"layer_height": {
"default_value": 0.15
},
"layer_height_0": { "layer_height_0": {
"default_value": 0.12 "default_value": 0.12
}, },

View file

@ -7,7 +7,7 @@
"author": "Samuel Pinches", "author": "Samuel Pinches",
"manufacturer": "JGAurora", "manufacturer": "JGAurora",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"preferred_quality_type": "fine", "preferred_quality_type": "fast",
"machine_extruder_trains": "machine_extruder_trains":
{ {
"0": "jgaurora_z_603s_extruder_0" "0": "jgaurora_z_603s_extruder_0"
@ -53,9 +53,6 @@
"material_bed_temperature": { "material_bed_temperature": {
"default_value": 55 "default_value": 55
}, },
"layer_height": {
"default_value": 0.15
},
"layer_height_0": { "layer_height_0": {
"default_value": 0.2 "default_value": 0.2
}, },

View file

@ -0,0 +1,26 @@
// Copyright (c) 2018 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.4
import UM 1.2 as UM
import Cura 1.0 as Cura
Instantiator {
model: UM.ContainerStacksModel {
filter: {"type": "machine", "um_cloud_cluster_id": "*"}
}
MenuItem {
// iconSource: UM.Theme.getIcon("printer_single") TODO: use cloud icon here
text: model.metadata["connect_group_name"]
checkable: true
checked: true // cloud printers are only listed if they are actually online
exclusiveGroup: group;
onTriggered: Cura.MachineManager.setActiveMachine(model.id);
}
onObjectAdded: menu.insertItem(index, object)
onObjectRemoved: menu.removeItem(object)
}

View file

@ -37,6 +37,23 @@ Menu
visible: networkPrinterMenu.count > 0 visible: networkPrinterMenu.count > 0
} }
MenuItem
{
text: catalog.i18nc("@label:category menu label", "Cloud enabled printers")
enabled: false
visible: cloudPrinterMenu.count > 0
}
CloudPrinterMenu
{
id: cloudPrinterMenu
}
MenuSeparator
{
visible: cloudPrinterMenu.count > 0
}
MenuItem MenuItem
{ {
text: catalog.i18nc("@label:category menu label", "Local printers") text: catalog.i18nc("@label:category menu label", "Local printers")

View file

@ -115,15 +115,16 @@ UM.PreferencesPage
currentIndex: currentIndex:
{ {
var idx = -1;
for(var i = 0; i < settingVisibilityPresetsModel.items.length; ++i) for(var i = 0; i < settingVisibilityPresetsModel.items.length; ++i)
{ {
if(settingVisibilityPresetsModel.items[i].presetId == settingVisibilityPresetsModel.activePreset) if(settingVisibilityPresetsModel.items[i].presetId == settingVisibilityPresetsModel.activePreset)
{ {
currentIndex = i; idx = i;
return; break;
} }
} }
return -1 return idx;
} }
onActivated: onActivated:

View file

@ -50,6 +50,46 @@ Column
} }
} }
Label
{
text: catalog.i18nc("@label", "Cloud connected printers")
visible: cloudPrintersModel.items.length > 0
leftPadding: UM.Theme.getSize("default_margin").width
height: visible ? contentHeight + 2 * UM.Theme.getSize("default_margin").height : 0
renderType: Text.NativeRendering
font: UM.Theme.getFont("medium")
color: UM.Theme.getColor("text_medium")
verticalAlignment: Text.AlignVCenter
}
Repeater
{
id: cloudPrinters
model: UM.ContainerStacksModel
{
id: cloudPrintersModel
filter:
{
"type": "machine",
"um_cloud_cluster_id": "*"
}
}
delegate: MachineSelectorButton
{
text: model.metadata["connect_group_name"]
checked: Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
Connections
{
target: Cura.MachineManager
onActiveMachineNetworkGroupNameChanged: checked = Cura.MachineManager.activeMachineNetworkGroupName == model.metadata["connect_group_name"]
}
}
}
Label Label
{ {
text: catalog.i18nc("@label", "Preset printers") text: catalog.i18nc("@label", "Preset printers")
@ -71,7 +111,9 @@ Column
id: virtualPrintersModel id: virtualPrintersModel
filter: filter:
{ {
"type": "machine", "um_network_key": null "type": "machine",
"um_network_key": null,
"um_cloud_cluster_id": null
} }
} }