class CuraSnapmakerSenderPlugin(Extension, OutputDevicePlugin, QObject):
    autodiscoverychanged = pyqtSignal()
    machineschanged = pyqtSignal()

    def __init__(self, parent=None) -> None:
        #Logger.log("d","Initializing CuraSnapmakerSenderPlugin")
        Extension.__init__(self)
        QObject.__init__(self)

        self.setMenuName(
            i18n_catalog.i18nc("@item:inmenu", "CuraSnapmakerSender"))
        self.addMenuItem(i18n_catalog.i18nc("@item:inmenu", "Settings"),
                         self.showSettings)
        self._view = None
        self.setPluginId("CuraSnapmakerSender")
        Application.getInstance().mainWindowChanged.connect(self.afterInit)
        Application.getInstance().applicationShuttingDown.connect(self.stop)
        self._settingsWindow = None
        self.settings = dict()
        self.settings["AutoDiscover"] = True
        self.settings["machines"] = list()
        self._active_added_Printers = list()
        self._active_discovered_Printers = list()
        self._tokenregistry = dict()
        self._stop_discovery_running = threading.Event()
        self._stop_discovery_running.clear()
        self._discoveryThread = None
        self._stop_discovery_event = threading.Event()

    @pyqtSlot()
    def autodiscoverchanged_exec(self):
        #Logger.log("d","autodiscoverchanged_exec" + str(self.settings["AutoDiscover"]) + " " + str(self._discoveryThread.is_alive()))
        if (self.settings["AutoDiscover"]
                and not self._discoveryThread.is_alive()):
            #Logger.log("d","Auto-Discovery Enabled")
            self._discoveryThread = threading.Thread(
                target=self.timedDiscovering)
            self._discoveryThread.start()
        elif (not self.settings["AutoDiscover"]
              and self._discoveryThread.is_alive()):
            #Logger.log("d","Auto-Discovery Disabled")
            self._stop_discovery_event.set()

    @pyqtProperty(bool)
    def autodiscover(self):
        #Logger.log("d","autodicover read")
        return self.settings["AutoDiscover"]

    @autodiscover.setter
    def autodiscover(self, autodiscover):
        #Logger.log("d","autodicover write")
        self.settings["AutoDiscover"] = autodiscover
        self.autodiscoverychanged.emit()
        #self._autodiscover = autodiscover

    @pyqtProperty(ListModel)
    def machines(self) -> ListModel:

        return self._manualprinters

    @machines.setter
    def machines(self, machines):
        self._manualprinters = machines
        self.machineschanged.emit()
        #Logger.log("d","machines set : "+ str(machines))

    def stop(self):
        self._stop_discovery_event.set()
        #Logger.log("d","Stopping everything from CuraSnapmakerSender")
        for printer_remove in self._active_added_Printers:
            self.removePrinter(printer_remove)
        for printer_remove in self._active_discovered_Printers:
            self.removePrinter(printer_remove)
        self.saveSettings()
        self.SaveTokenRegistry()

    def afterInit(self):
        #Logger.log("d","Log Something")
        self.loadTokenRegistry()
        self.loadSettings()
        self.autodiscoverychanged.connect(self.autodiscoverchanged_exec)
        if (self.settings["AutoDiscover"]):
            #Logger.log("d","Auto-Discovery Enabled")
            self._discoveryThread = threading.Thread(
                target=self.timedDiscovering)
            self._discoveryThread.start()
        self._manualprinters = ListModel()
        self._manualprinters.addRoleName(Qt.UserRole + 1, "name")
        self._manualprinters.addRoleName(Qt.UserRole + 2, "address")
        for x in self.settings["machines"]:
            printer = x
            self._manualprinters.appendItem(printer)

        #Logger.log("d","Getting Item result : "+str(self._manualprinters.getItem(0)))
        self.managePrinters()

    def loadTokenRegistry(self):
        path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
        path = os.path.join(path, 'tokens.cfg')
        if os.path.exists(path):
            self._tokenregistry = json.load(open(path, 'r'))
        else:
            with open(path, 'w') as file:
                json.dump(self._tokenregistry, file)
        Logger.debug("TokenRegistryLoaded")

    def SaveTokenRegistry(self):
        path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
        path = os.path.join(path, 'tokens.cfg')
        with open(path, 'w') as file:
            json.dump(self._tokenregistry, file)
        Logger.debug("TokensSaved")

    def loadSettings(self):
        path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
        path = os.path.join(path, 'settings.cfg')
        if os.path.exists(path):
            self.settings = json.load(open(path, 'r'))
        else:
            with open(path, 'w') as file:
                json.dump(self.settings, file)
        Logger.debug("SettingsLoaded")

    @pyqtSlot()
    def saveSettings(self):
        path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
        arr = list()
        for x in self._manualprinters.items:
            arr.append(x)
        #Logger.log("d",arr)
        self.settings["machines"] = arr
        path = os.path.join(path, 'settings.cfg')
        with open(path, 'w') as file:
            json.dump(self.settings, file)  #
        #Logger.log("d","SettingsSaved")

    def timedDiscovering(self):
        #Logger.log("d","Discovery thread started")
        while not self._stop_discovery_event.is_set():
            if not self.settings["AutoDiscover"]:
                #Logger.log("d","Discovery thread stopped")
                break
            self.discoverAndManagePrinters()
            self._stop_discovery_event.wait(5)
        self._stop_discovery_event.clear()
        #Logger.log("d","Discovery thread stopped")

    def discoverAndManagePrinters(self):
        old_printers = [x for x in self._active_discovered_Printers]
        printers_dict = discover_Snapmaker()
        printers = [x for x in printers_dict]
        for printer in printers:
            try:
                in_list = False
                for old_printer in old_printers:
                    if old_printer == printer:
                        #Logger.log("d","Already in list " + str(printer))
                        old_printers.remove(old_printer)
                        in_list = True
                if not in_list:
                    raise ValueError
            except ValueError:
                if not self.addPrinter(printer):
                    printers.remove(printer)
        for printer_remove in old_printers:
            self.removePrinter(printer_remove)
        self._active_discovered_Printers = [x for x in printers]

    @pyqtSlot()
    def managePrinters(self):
        #Logger.log("d","Managing manually added printers")
        old_printers = [x for x in self._active_added_Printers]
        printers = self._manualprinters.items
        for printer in printers:
            try:
                in_list = False
                for old_printer in old_printers:
                    if old_printer == printer:
                        #Logger.log("d","Already in list " + str(printer))
                        old_printers.remove(old_printer)
                        in_list = True
                if not in_list:
                    raise ValueError
            except ValueError:
                if not self.addPrinter(
                        printer
                ):  #manually added printers take priority, so throw the already added printer from discovery out
                    self.removePrinter(printer)
                    in_list = False
                    for old_printer in self._active_discovered_Printers:
                        if old_printer["address"] == printer["address"]:
                            #Logger.log("d","Already in list " + str(printer))
                            self._active_discovered_Printers.remove(
                                old_printer)
                            in_list = True
                    if not self.addPrinter(
                            printer):  #and add the manual version
                        #raise Exception("Problem with manually added printer")
                        self._manualprinters.removeItem(
                            self._manualprinters.find('address',
                                                      printer['address']))
                #Logger.log("d","Added manually " + str(printer))
        for printer_remove in old_printers:
            #Logger.log("d","Removed " + str(printer_remove))
            self.removePrinter(printer_remove)
        self._active_added_Printers = [x for x in printers]

    def addPrinter(self, printer):
        #Logger.log("d","Adding "+printer['name']+printer['address']+ " OutputDevice")
        token = ''
        if printer['address'] in self._tokenregistry:
            token = self._tokenregistry[printer['address']]
        if self.getOutputDeviceManager().getOutputDevice(printer['address']):
            return False  #already added
        else:
            self.getOutputDeviceManager().addOutputDevice(
                CuraSnapmakerSenderOutputDevice(printer['address'],
                                                printer['name'],
                                                token=token))
            return True

    def removePrinter(self, printer_remove: Dict):

        printer = self.getOutputDeviceManager().getOutputDevice(
            printer_remove['address'])
        # STore the token in the tokenregistry, maybe we can reuse it
        try:
            self._tokenregistry[printer_remove['address']] = printer._token
        except AttributeError:
            pass
        printer.tearDown()
        self.getOutputDeviceManager().removeOutputDevice(printer.getId())
        #Logger.log("d","Removing "+printer_remove['name']+printer_remove['address']+ " OutputDevice")

    def showSettings(self):
        if not self._settingsWindow:
            self._settingsWindow = self._createSettingsDialogue()
        self._settingsWindow.show()

    def _createSettingsDialogue(self) -> QQuickWindow:
        qml_file_path = os.path.join(
            PluginRegistry.getInstance().getPluginPath(self.getPluginId()),
            "CuraSnapmakerSenderSettings.qml")
        component = Application.getInstance().createQmlComponent(
            qml_file_path, {"manager": self})
        return component

    @pyqtSlot()
    def _appendEmptyPrinter(self):
        self.machines.appendItem({
            'name':
            'MySnapmaker' + str(self.machines.count + 1),
            'address':
            '192.168.0.' + str(self.machines.count + 1)
        })

    @pyqtSlot(int)
    def _removePrinterfromList(self, index: int):
        self.machines.removeItem(index)
Exemple #2
0
class TestListModel(TestCase):

    list_model = None  # type: ListModel

    test_data = [{
        "name": "yay",
        "data": 12
    }, {
        "name": "omg",
        "data": 13
    }, {
        "name": "zomg",
        "data": 14
    }]
    NameRole = Qt.UserRole + 1
    DataRole = Qt.UserRole + 2

    def setUp(self):
        self.list_model = ListModel()
        self.list_model.addRoleName(self.NameRole, "name")
        self.list_model.addRoleName(self.DataRole, "data")

        self.list_model.setItems(deepcopy(self.test_data))

    def test_getItem(self):
        assert self.list_model.getItem(0) == {"name": "yay", "data": 12}
        assert self.list_model.getItem(9001) == {}

    def test_items(self):
        assert self.list_model.items == self.test_data

    def test_insertItem(self):
        self.list_model.insertItem(0, {"name": "zomg!", "data": "yay"})
        assert self.list_model.getItem(0) == {"name": "zomg!", "data": "yay"}
        # Check if the previously first item is now the second one.
        assert self.list_model.getItem(1) == {"name": "yay", "data": 12}

    def test_removeItem(self):
        self.list_model.removeItem(1)
        assert self.list_model.getItem(1) == {"name": "zomg", "data": 14}

    def test_clear(self):
        assert self.list_model.count == 3
        self.list_model.clear()
        assert self.list_model.count == 0

    def test_appendItem(self):
        self.list_model.appendItem({"name": "!", "data": 9001})
        assert self.list_model.count == 4
        assert self.list_model.getItem(3) == {"name": "!", "data": 9001}

    def test_setProperty(self):
        self.list_model.setProperty(0, "name", "new_data")
        assert self.list_model.getItem(0)["name"] == "new_data"

    def test_find(self):
        assert self.list_model.find("name", "omg") == 1
        assert self.list_model.find("data", 13) == 1
        assert self.list_model.find("name", "zomg") == 2

        assert self.list_model.find("name", "UNKNOWN") == -1

    def test_setItems(self):
        self.list_model.setItems([{"name": "zomg!", "data": "yay"}])
        assert self.list_model.items == [{"name": "zomg!", "data": "yay"}]

    def test_sort(self):
        self.list_model.sort(lambda i: -i["data"])

        assert self.list_model.getItem(0) == {"name": "zomg", "data": 14}
        assert self.list_model.getItem(2) == {"name": "yay", "data": 12}