mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-14 10:17:52 -06:00
WIP: Add printers via network
This commit is contained in:
parent
a55808b24a
commit
940a833e73
9 changed files with 145 additions and 46 deletions
|
@ -114,6 +114,8 @@ from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
|
||||||
|
|
||||||
from cura.ObjectsModel import ObjectsModel
|
from cura.ObjectsModel import ObjectsModel
|
||||||
|
|
||||||
|
from cura.Machines.Models.DiscoveredPrintersModel import DiscoveredPrinterModel
|
||||||
|
|
||||||
from cura.PrinterOutputDevice import PrinterOutputDevice
|
from cura.PrinterOutputDevice import PrinterOutputDevice
|
||||||
from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
|
from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
|
||||||
|
|
||||||
|
@ -210,6 +212,8 @@ class CuraApplication(QtApplication):
|
||||||
self._cura_scene_controller = None
|
self._cura_scene_controller = None
|
||||||
self._machine_error_checker = None
|
self._machine_error_checker = None
|
||||||
|
|
||||||
|
self._discovered_printer_model = DiscoveredPrinterModel(self)
|
||||||
|
|
||||||
self._welcome_pages_model = WelcomePagesModel(self)
|
self._welcome_pages_model = WelcomePagesModel(self)
|
||||||
|
|
||||||
self._quality_profile_drop_down_menu_model = None
|
self._quality_profile_drop_down_menu_model = None
|
||||||
|
@ -846,6 +850,10 @@ class CuraApplication(QtApplication):
|
||||||
# Hide the splash screen
|
# Hide the splash screen
|
||||||
self.closeSplash()
|
self.closeSplash()
|
||||||
|
|
||||||
|
@pyqtSlot(result = QObject)
|
||||||
|
def getDiscoveredPrinterModel(self, *args) -> "DiscoveredPrinterModel":
|
||||||
|
return self._discovered_printer_model
|
||||||
|
|
||||||
@pyqtSlot(result = QObject)
|
@pyqtSlot(result = QObject)
|
||||||
def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel:
|
def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel:
|
||||||
return self._setting_visibility_presets_model
|
return self._setting_visibility_presets_model
|
||||||
|
@ -1003,6 +1011,8 @@ class CuraApplication(QtApplication):
|
||||||
qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
|
qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
|
||||||
qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")
|
qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")
|
||||||
|
|
||||||
|
qmlRegisterType(DiscoveredPrinterModel, "Cura", 1, 0, "DiscoveredPrinterModel")
|
||||||
|
|
||||||
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
|
qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
|
||||||
"QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
|
"QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
|
||||||
qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0,
|
qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0,
|
||||||
|
|
104
cura/Machines/Models/DiscoveredPrintersModel.py
Normal file
104
cura/Machines/Models/DiscoveredPrintersModel.py
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
from typing import Callable, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
from PyQt5.QtCore import pyqtSlot, pyqtProperty, pyqtSignal, QObject
|
||||||
|
|
||||||
|
from UM.Logger import Logger
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from PyQt5.QtCore import QObject
|
||||||
|
|
||||||
|
|
||||||
|
class DiscoveredPrinter(QObject):
|
||||||
|
|
||||||
|
def __init__(self, ip_address: str, key: str, name: str, create_callback: Callable[[str], None], machine_type: str,
|
||||||
|
device, parent = None) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
self._ip_address = ip_address
|
||||||
|
self._key = key
|
||||||
|
self._name = name
|
||||||
|
self._create_callback = create_callback
|
||||||
|
self._machine_type = machine_type
|
||||||
|
self._device = device
|
||||||
|
|
||||||
|
nameChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = nameChanged)
|
||||||
|
def name(self) -> str:
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
def setName(self, name: str) -> None:
|
||||||
|
if self._name != name:
|
||||||
|
self._name = name
|
||||||
|
self.nameChanged.emit()
|
||||||
|
|
||||||
|
machineTypeChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@pyqtProperty(str, notify = machineTypeChanged)
|
||||||
|
def machine_type(self) -> str:
|
||||||
|
return self._machine_type
|
||||||
|
|
||||||
|
def setMachineType(self, machine_type: str) -> None:
|
||||||
|
if self._machine_type != machine_type:
|
||||||
|
self._machine_type = machine_type
|
||||||
|
self.machineTypeChanged.emit()
|
||||||
|
|
||||||
|
@pyqtProperty(QObject, constant = True)
|
||||||
|
def device(self):
|
||||||
|
return self._device
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Discovered printers are all the printers that were found on the network, which provide a more convenient way
|
||||||
|
# to add networked printers (Plugin finds a bunch of printers, user can select one from the list, plugin can then
|
||||||
|
# add that printer to Cura as the active one).
|
||||||
|
#
|
||||||
|
class DiscoveredPrinterModel(QObject):
|
||||||
|
|
||||||
|
def __init__(self, parent: Optional["QObject"]) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self._discovered_printer_dict = dict()
|
||||||
|
|
||||||
|
discoveredPrintersChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@pyqtProperty(list, notify = discoveredPrintersChanged)
|
||||||
|
def discovered_printers(self) -> "list":
|
||||||
|
item_list = list(x for x in self._discovered_printer_dict.values())
|
||||||
|
item_list.sort(key = lambda x: x.name)
|
||||||
|
return item_list
|
||||||
|
|
||||||
|
def addDiscoveredPrinter(self, ip_address: str, key: str, name: str, create_callback: Callable[[str], None],
|
||||||
|
machine_type: str, device) -> None:
|
||||||
|
if ip_address in self._discovered_printer_dict:
|
||||||
|
Logger.log("e", "+++++++++++++ printer with ip [%s] has already been added", ip_address)
|
||||||
|
return
|
||||||
|
|
||||||
|
discovered_printer = DiscoveredPrinter(ip_address, key, name, create_callback, machine_type, device, parent = self)
|
||||||
|
self._discovered_printer_dict[ip_address] = discovered_printer
|
||||||
|
self.discoveredPrintersChanged.emit()
|
||||||
|
|
||||||
|
def updateDiscoveredPrinter(self, ip_address: str,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
machine_type: Optional[str] = None) -> None:
|
||||||
|
if ip_address not in self._discovered_printer_dict:
|
||||||
|
Logger.log("e", "+++++++++++++ printer with ip [%s] is not known", ip_address)
|
||||||
|
return
|
||||||
|
|
||||||
|
item = self._discovered_printer_dict[ip_address]
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
item.setName(name)
|
||||||
|
if machine_type is not None:
|
||||||
|
item.setMachineType(machine_type)
|
||||||
|
|
||||||
|
def removeDiscoveredPrinter(self, ip_address: str) -> None:
|
||||||
|
if ip_address not in self._discovered_printer_dict:
|
||||||
|
Logger.log("i", "Key [%s] does not exist in the discovered printers list.", ip_address)
|
||||||
|
return
|
||||||
|
|
||||||
|
del self._discovered_printer_dict[ip_address]
|
||||||
|
self.discoveredPrintersChanged.emit()
|
||||||
|
|
||||||
|
@pyqtSlot("QVariant")
|
||||||
|
def createMachineFromDiscoveredPrinter(self, discovered_printer: "DiscoveredPrinter") -> None:
|
||||||
|
discovered_printer.create_callback()
|
|
@ -4,7 +4,7 @@
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from typing import Any, List, Dict, TYPE_CHECKING, Optional, cast, NamedTuple, Callable
|
from typing import Any, List, Dict, TYPE_CHECKING, Optional, cast
|
||||||
|
|
||||||
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||||
|
@ -49,8 +49,6 @@ if TYPE_CHECKING:
|
||||||
from cura.Machines.QualityChangesGroup import QualityChangesGroup
|
from cura.Machines.QualityChangesGroup import QualityChangesGroup
|
||||||
from cura.Machines.QualityGroup import QualityGroup
|
from cura.Machines.QualityGroup import QualityGroup
|
||||||
|
|
||||||
DiscoveredPrinter = NamedTuple("DiscoveredPrinter", [("key", str), ("name", str), ("create_callback", Callable[[str], None]), ("machine_type", "str")])
|
|
||||||
|
|
||||||
|
|
||||||
class MachineManager(QObject):
|
class MachineManager(QObject):
|
||||||
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
|
def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
|
||||||
|
@ -136,9 +134,6 @@ class MachineManager(QObject):
|
||||||
self.globalContainerChanged.connect(self.printerConnectedStatusChanged)
|
self.globalContainerChanged.connect(self.printerConnectedStatusChanged)
|
||||||
self.outputDevicesChanged.connect(self.printerConnectedStatusChanged)
|
self.outputDevicesChanged.connect(self.printerConnectedStatusChanged)
|
||||||
|
|
||||||
# This will contain all discovered network printers
|
|
||||||
self._discovered_printers = {} # type: Dict[str, DiscoveredPrinter]
|
|
||||||
|
|
||||||
activeQualityGroupChanged = pyqtSignal()
|
activeQualityGroupChanged = pyqtSignal()
|
||||||
activeQualityChangesGroupChanged = pyqtSignal()
|
activeQualityChangesGroupChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@ -178,30 +173,6 @@ class MachineManager(QObject):
|
||||||
|
|
||||||
self.outputDevicesChanged.emit()
|
self.outputDevicesChanged.emit()
|
||||||
|
|
||||||
# Discovered printers are all the printers that were found on the network, which provide a more convenient way
|
|
||||||
# to add networked printers (Plugin finds a bunch of printers, user can select one from the list, plugin can then
|
|
||||||
# add that printer to Cura as the active one).
|
|
||||||
def addDiscoveredPrinter(self, key: str, name: str, create_callback: Callable[[str], None], machine_type: str) -> None:
|
|
||||||
if key not in self._discovered_printers:
|
|
||||||
self._discovered_printers[key] = DiscoveredPrinter(key, name, create_callback, machine_type)
|
|
||||||
self.discoveredPrintersChanged.emit()
|
|
||||||
else:
|
|
||||||
Logger.log("e", "Printer with the key %s was already in the discovered printer list", key)
|
|
||||||
|
|
||||||
def removeDiscoveredPrinter(self, key: str) -> None:
|
|
||||||
if key in self._discovered_printers:
|
|
||||||
del self._discovered_printers[key]
|
|
||||||
self.discoveredPrintersChanged.emit()
|
|
||||||
|
|
||||||
@pyqtProperty("QVariantList", notify = discoveredPrintersChanged)
|
|
||||||
def discoveredPrinters(self):
|
|
||||||
return list(self._discovered_printers.values())
|
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def addMachineFromDiscoveredPrinter(self, key: str) -> None:
|
|
||||||
if key in self._discovered_printers:
|
|
||||||
self._discovered_printers[key].create_callback(key)
|
|
||||||
|
|
||||||
@pyqtProperty(QObject, notify = currentConfigurationChanged)
|
@pyqtProperty(QObject, notify = currentConfigurationChanged)
|
||||||
def currentConfiguration(self) -> ConfigurationModel:
|
def currentConfiguration(self) -> ConfigurationModel:
|
||||||
return self._current_printer_configuration
|
return self._current_printer_configuration
|
||||||
|
|
|
@ -624,6 +624,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
||||||
printer.updateName(data["friendly_name"])
|
printer.updateName(data["friendly_name"])
|
||||||
printer.updateKey(data["uuid"])
|
printer.updateKey(data["uuid"])
|
||||||
printer.updateType(data["machine_variant"])
|
printer.updateType(data["machine_variant"])
|
||||||
|
self._application.getDiscoveredPrinterModel().updateDiscoveredPrinter(data["ip_address"],
|
||||||
|
name = data["friendly_name"],
|
||||||
|
machine_type = data["machine_variant"])
|
||||||
|
|
||||||
# Do not store the build plate information that comes from connect if the current printer has not build plate information
|
# Do not store the build plate information that comes from connect if the current printer has not build plate information
|
||||||
if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):
|
if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):
|
||||||
|
|
|
@ -298,7 +298,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Disconnect already happened.
|
# Disconnect already happened.
|
||||||
pass
|
pass
|
||||||
self._application.getMachineManager().removeDiscoveredPrinter(device.getId())
|
self._application.getDiscoveredPrinterModel().removeDiscoveredPrinter(device.getId())
|
||||||
self.discoveredDevicesChanged.emit()
|
self.discoveredDevicesChanged.emit()
|
||||||
|
|
||||||
def _onAddDevice(self, name, address, properties):
|
def _onAddDevice(self, name, address, properties):
|
||||||
|
@ -323,7 +323,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
||||||
device = ClusterUM3OutputDevice.ClusterUM3OutputDevice(name, address, properties)
|
device = ClusterUM3OutputDevice.ClusterUM3OutputDevice(name, address, properties)
|
||||||
else:
|
else:
|
||||||
device = LegacyUM3OutputDevice.LegacyUM3OutputDevice(name, address, properties)
|
device = LegacyUM3OutputDevice.LegacyUM3OutputDevice(name, address, properties)
|
||||||
self._application.getMachineManager().addDiscoveredPrinter(device.getId(), name, self._createMachineFromDiscoveredPrinter, properties[b"printer_type"].decode("utf-8"))
|
self._application.getDiscoveredPrinterModel().addDiscoveredPrinter(address, device.getId(), name, self._createMachineFromDiscoveredPrinter, properties[b"printer_type"].decode("utf-8"), device)
|
||||||
self._discovered_devices[device.getId()] = device
|
self._discovered_devices[device.getId()] = device
|
||||||
self.discoveredDevicesChanged.emit()
|
self.discoveredDevicesChanged.emit()
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ Button
|
||||||
|
|
||||||
function updatePrinterTypesList()
|
function updatePrinterTypesList()
|
||||||
{
|
{
|
||||||
printerTypesList = (checked && (outputDevice != null)) ? outputDevice.uniquePrinterTypes : []
|
printerTypesList = (outputDevice != null) ? outputDevice.uniquePrinterTypes : []
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Item
|
contentItem: Item
|
||||||
|
@ -82,12 +82,6 @@ Button
|
||||||
border.color: machineSelectorButton.checked ? UM.Theme.getColor("primary") : "transparent"
|
border.color: machineSelectorButton.checked ? UM.Theme.getColor("primary") : "transparent"
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked:
|
|
||||||
{
|
|
||||||
toggleContent()
|
|
||||||
Cura.MachineManager.setActiveMachine(model.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections
|
Connections
|
||||||
{
|
{
|
||||||
target: outputDevice
|
target: outputDevice
|
||||||
|
|
|
@ -42,5 +42,11 @@ ListView
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
toggleContent()
|
||||||
|
Cura.MachineManager.setActiveMachine(model.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,11 @@ Item
|
||||||
|
|
||||||
ScrollView
|
ScrollView
|
||||||
{
|
{
|
||||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
id: networkPrinterScrollView
|
||||||
|
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
|
||||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
|
||||||
|
|
||||||
property int maxItemCountAtOnce: 5 // show at max 5 items at once, otherwise you need to scroll.
|
property int maxItemCountAtOnce: 8 // show at max 8 items at once, otherwise you need to scroll.
|
||||||
height: maxItemCountAtOnce * (UM.Theme.getSize("action_button").height)
|
height: maxItemCountAtOnce * (UM.Theme.getSize("action_button").height)
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
|
@ -69,15 +70,17 @@ Item
|
||||||
{
|
{
|
||||||
id: networkPrinterListView
|
id: networkPrinterListView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
model: Cura.GlobalStacksModel {} // TODO: change this to the network printers
|
model: CuraApplication.getDiscoveredPrinterModel().discovered_printers
|
||||||
|
visible: len(model) > 0
|
||||||
|
|
||||||
delegate: MachineSelectorButton
|
delegate: MachineSelectorButton
|
||||||
{
|
{
|
||||||
text: model.name
|
text: modelData.device.name
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 10
|
anchors.rightMargin: 10
|
||||||
outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
|
outputDevice: modelData.device
|
||||||
|
|
||||||
checked: ListView.view.currentIndex == index
|
checked: ListView.view.currentIndex == index
|
||||||
onClicked:
|
onClicked:
|
||||||
|
@ -86,6 +89,14 @@ Item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label
|
||||||
|
{
|
||||||
|
id: noNetworkPrinterLabel
|
||||||
|
text: catalog.i18nc("@label", "There is no printer found over your network.")
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
visible: !networkPrinterListView.visible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +120,7 @@ Item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
contentComponent: localPrinterListComponent
|
//contentComponent: localPrinterListComponent
|
||||||
|
|
||||||
Component
|
Component
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue