Browse Source

WIP: Add printers via network

Lipu Fei 6 years ago
parent
commit
940a833e73

+ 10 - 0
cura/CuraApplication.py

@@ -114,6 +114,8 @@ from cura.Settings.CuraFormulaFunctions import CuraFormulaFunctions
 
 from cura.ObjectsModel import ObjectsModel
 
+from cura.Machines.Models.DiscoveredPrintersModel import DiscoveredPrinterModel
+
 from cura.PrinterOutputDevice import PrinterOutputDevice
 from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage
 
@@ -210,6 +212,8 @@ class CuraApplication(QtApplication):
         self._cura_scene_controller = None
         self._machine_error_checker = None
 
+        self._discovered_printer_model = DiscoveredPrinterModel(self)
+
         self._welcome_pages_model = WelcomePagesModel(self)
 
         self._quality_profile_drop_down_menu_model = None
@@ -846,6 +850,10 @@ class CuraApplication(QtApplication):
         # Hide the splash screen
         self.closeSplash()
 
+    @pyqtSlot(result = QObject)
+    def getDiscoveredPrinterModel(self, *args) -> "DiscoveredPrinterModel":
+        return self._discovered_printer_model
+
     @pyqtSlot(result = QObject)
     def getSettingVisibilityPresetsModel(self, *args) -> SettingVisibilityPresetsModel:
         return self._setting_visibility_presets_model
@@ -1003,6 +1011,8 @@ class CuraApplication(QtApplication):
         qmlRegisterType(QualityManagementModel, "Cura", 1, 0, "QualityManagementModel")
         qmlRegisterType(MachineManagementModel, "Cura", 1, 0, "MachineManagementModel")
 
+        qmlRegisterType(DiscoveredPrinterModel, "Cura", 1, 0, "DiscoveredPrinterModel")
+
         qmlRegisterSingletonType(QualityProfilesDropDownMenuModel, "Cura", 1, 0,
                                  "QualityProfilesDropDownMenuModel", self.getQualityProfilesDropDownMenuModel)
         qmlRegisterSingletonType(CustomQualityProfilesDropDownMenuModel, "Cura", 1, 0,

+ 104 - 0
cura/Machines/Models/DiscoveredPrintersModel.py

@@ -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()

+ 1 - 30
cura/Settings/MachineManager.py

@@ -4,7 +4,7 @@
 import time
 import re
 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.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@@ -49,8 +49,6 @@ if TYPE_CHECKING:
     from cura.Machines.QualityChangesGroup import QualityChangesGroup
     from cura.Machines.QualityGroup import QualityGroup
 
-DiscoveredPrinter = NamedTuple("DiscoveredPrinter", [("key", str), ("name", str), ("create_callback", Callable[[str], None]), ("machine_type", "str")])
-
 
 class MachineManager(QObject):
     def __init__(self, application: "CuraApplication", parent: Optional["QObject"] = None) -> None:
@@ -136,9 +134,6 @@ class MachineManager(QObject):
         self.globalContainerChanged.connect(self.printerConnectedStatusChanged)
         self.outputDevicesChanged.connect(self.printerConnectedStatusChanged)
 
-        # This will contain all discovered network printers
-        self._discovered_printers = {}  # type: Dict[str, DiscoveredPrinter]
-
     activeQualityGroupChanged = pyqtSignal()
     activeQualityChangesGroupChanged = pyqtSignal()
 
@@ -178,30 +173,6 @@ class MachineManager(QObject):
 
         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)
     def currentConfiguration(self) -> ConfigurationModel:
         return self._current_printer_configuration

+ 3 - 0
plugins/UM3NetworkPrinting/src/ClusterUM3OutputDevice.py

@@ -624,6 +624,9 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
         printer.updateName(data["friendly_name"])
         printer.updateKey(data["uuid"])
         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
         if "build_plate" in data and machine_definition.getMetaDataEntry("has_variant_buildplates", False):

+ 2 - 2
plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py

@@ -298,7 +298,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
                 except TypeError:
                     # Disconnect already happened.
                     pass
-            self._application.getMachineManager().removeDiscoveredPrinter(device.getId())
+            self._application.getDiscoveredPrinterModel().removeDiscoveredPrinter(device.getId())
             self.discoveredDevicesChanged.emit()
 
     def _onAddDevice(self, name, address, properties):
@@ -323,7 +323,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
             device = ClusterUM3OutputDevice.ClusterUM3OutputDevice(name, address, properties)
         else:
             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.discoveredDevicesChanged.emit()
 

+ 1 - 7
resources/qml/PrinterSelector/MachineSelectorButton.qml

@@ -24,7 +24,7 @@ Button
 
     function updatePrinterTypesList()
     {
-        printerTypesList = (checked && (outputDevice != null)) ? outputDevice.uniquePrinterTypes : []
+        printerTypesList = (outputDevice != null) ? outputDevice.uniquePrinterTypes : []
     }
 
     contentItem: Item
@@ -82,12 +82,6 @@ Button
         border.color: machineSelectorButton.checked ? UM.Theme.getColor("primary") : "transparent"
     }
 
-    onClicked:
-    {
-        toggleContent()
-        Cura.MachineManager.setActiveMachine(model.id)
-    }
-
     Connections
     {
         target: outputDevice

+ 6 - 0
resources/qml/PrinterSelector/MachineSelectorList.qml

@@ -42,5 +42,11 @@ ListView
             }
             return result
         }
+
+        onClicked:
+        {
+            toggleContent()
+            Cura.MachineManager.setActiveMachine(model.id)
+        }
     }
 }

+ 17 - 6
resources/qml/WelcomePages/AddPrinterBySelectionContent.qml

@@ -57,10 +57,11 @@ Item
 
             ScrollView
             {
-                ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
+                id: networkPrinterScrollView
+                ScrollBar.horizontal.policy: ScrollBar.AsNeeded
                 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)
 
                 clip: true
@@ -69,15 +70,17 @@ Item
                 {
                     id: networkPrinterListView
                     anchors.fill: parent
-                    model: Cura.GlobalStacksModel {} // TODO: change this to the network printers
+                    model: CuraApplication.getDiscoveredPrinterModel().discovered_printers
+                    visible: len(model) > 0
 
                     delegate: MachineSelectorButton
                     {
-                        text: model.name
+                        text: modelData.device.name
+
                         anchors.left: parent.left
                         anchors.right: parent.right
                         anchors.rightMargin: 10
-                        outputDevice: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null
+                        outputDevice: modelData.device
 
                         checked: ListView.view.currentIndex == index
                         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
         {

+ 1 - 1
tests/TestMachineManager.py

@@ -61,4 +61,4 @@ def test_discoveredMachine(machine_manager):
 
     # Just in case, nothing should happen.
     machine_manager.addMachineFromDiscoveredPrinter("test")
-    assert mocked_callback.call_count == 1
+    assert mocked_callback.call_count == 1