diff --git a/revpicommander/avahisearch.py b/revpicommander/avahisearch.py index da1f50d..1aad1a0 100644 --- a/revpicommander/avahisearch.py +++ b/revpicommander/avahisearch.py @@ -31,7 +31,7 @@ class AvahiSearchThread(QtCore.QThread): r"(?P([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})" ) - def _update_arp(self): + def _update_arp(self) -> None: """Find mac address in arp table.""" if osname == "posix": with open("/proc/net/arp") as fh: @@ -40,7 +40,7 @@ class AvahiSearchThread(QtCore.QThread): if ip_mac: self.__dict_arp[ip_mac.group("ip")] = ip_mac.group("mac") - def get_mac(self, ip: str): + def get_mac(self, ip: str) -> dict: """ Get mac address of ip, if known. @@ -49,12 +49,12 @@ class AvahiSearchThread(QtCore.QThread): """ return self.__dict_arp.get(ip, "") - def remove_service(self, zeroconf: Zeroconf, conf_type: str, name: str): + def remove_service(self, zeroconf: Zeroconf, conf_type: str, name: str) -> None: """Revolution Pi disappeared.""" pi.logger.debug("AvahiSearchThread.remove_service") self.removed.emit(name, conf_type) - def add_service(self, zeroconf: Zeroconf, conf_type: str, name: str): + def add_service(self, zeroconf: Zeroconf, conf_type: str, name: str) -> None: """New Revolution Pi found.""" pi.logger.debug("AvahiSearchThread.add_service") info = zeroconf.get_service_info(conf_type, name) @@ -64,7 +64,7 @@ class AvahiSearchThread(QtCore.QThread): for ip in info.parsed_addresses(IPVersion.V4Only): self.added.emit(name, info.server, info.port, conf_type, ip) - def run(self): + def run(self) -> None: pi.logger.debug("Started zero conf discovery.") zeroconf = Zeroconf() revpi_browser = ServiceBrowser(zeroconf, "_revpipyload._tcp.local.", self) @@ -80,16 +80,36 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): def __init__(self, parent=None): super(AvahiSearch, self).__init__(parent) self.setupUi(self) - self.setFixedSize(self.size()) self.connect_index = -1 + self.known_hosts = {} self.th_zero_conf = AvahiSearchThread(self) self.tb_revpi.setColumnWidth(0, 250) self.btn_connect.setEnabled(False) self.btn_save.setEnabled(False) - def _restart_search(self): + self.restoreGeometry(helper.settings.value("avahisearch/geo", b'')) + column_sizes = helper.settings.value("avahisearch/column_sizes", [], type=list) + if len(column_sizes) == self.tb_revpi.columnCount(): + for i in range(self.tb_revpi.columnCount()): + self.tb_revpi.setColumnWidth(i, int(column_sizes[i])) + + def _load_known_hosts(self) -> None: + """Load existing connections to show hostname of existing ip addresses""" + self.known_hosts.clear() + + for i in range(helper.settings.beginReadArray("connections")): + helper.settings.setArrayIndex(i) + + name = helper.settings.value("name", type=str) + folder = helper.settings.value("folder", type=str) + address = helper.settings.value("address", type=str) + self.known_hosts[address] = "{0}/{1}".format(folder, name) if folder else name + + helper.settings.endArray() + + def _restart_search(self) -> None: """Clean up an restart search thread.""" while self.tb_revpi.rowCount() > 0: self.tb_revpi.removeRow(0) @@ -100,17 +120,17 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): self.th_zero_conf.removed.connect(self.on_avahi_removed) self.th_zero_conf.start() - def _save_connection(self, row: int, no_warn=False): + def _save_connection(self, row: int, no_warn=False) -> int: """ Save the connection from given row to settings. :param row: Row with connection data :param no_warn: If True, no message boxes will appear - :return: Array index of connection (found or saved) + :return: Array index of connection (found or saved) or -1 """ item = self.tb_revpi.item(row, 0) if not item: - return + return -1 folder_name = self.tr("Auto discovered") selected_name = item.text() @@ -155,14 +175,22 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): return i + 1 + def closeEvent(self, a0: QtGui.QCloseEvent) -> None: + helper.settings.setValue("avahisearch/geo", self.saveGeometry()) + helper.settings.setValue("avahisearch/column_sizes", [ + self.tb_revpi.columnWidth(i) + for i in range(self.tb_revpi.columnCount()) + ]) + def exec(self) -> int: + self._load_known_hosts() self._restart_search() rc = super(AvahiSearch, self).exec() self.th_zero_conf.requestInterruption() return rc @QtCore.pyqtSlot(str, str, int, str, str) - def on_avahi_added(self, name: str, server: str, port: int, conf_type: str, ip: str): + def on_avahi_added(self, name: str, server: str, port: int, conf_type: str, ip: str) -> None: """New Revolution Pi found.""" index = -1 for i in range(self.tb_revpi.rowCount()): @@ -185,14 +213,17 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): item_ip = self.tb_revpi.item(index, 1) item_name.setIcon(QtGui.QIcon(":/main/ico/cpu.ico")) - item_name.setText(server[:-1]) + if ip in self.known_hosts: + item_name.setText("{0} ({1})".format(server[:-1], self.known_hosts[ip])) + else: + item_name.setText(server[:-1]) item_name.setData(WidgetData.object_name, name) item_name.setData(WidgetData.address, ip) item_name.setData(WidgetData.port, port) item_ip.setText(ip) @QtCore.pyqtSlot(str, str) - def on_avahi_removed(self, name: str, conf_type: str): + def on_avahi_removed(self, name: str, conf_type: str) -> None: """Revolution Pi disappeared.""" for i in range(self.tb_revpi.rowCount()): if self.tb_revpi.item(i, 0).data(WidgetData.object_name) == name: @@ -200,20 +231,20 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): break @QtCore.pyqtSlot(int, int) - def on_tb_revpi_cellDoubleClicked(self, row: int, column: int): + def on_tb_revpi_cellDoubleClicked(self, row: int, column: int) -> None: """Connect to double clicked Revolution Pi.""" pi.logger.debug("AvahiSearch.on_tb_revpi_cellDoubleClicked") self.connect_index = self._save_connection(row, no_warn=True) self.accept() @QtCore.pyqtSlot(int, int, int, int) - def on_tb_revpi_currentCellChanged(self, row: int, column: int, last_row: int, last_column: int): + def on_tb_revpi_currentCellChanged(self, row: int, column: int, last_row: int, last_column: int) -> None: """Manage state of buttons.""" self.btn_connect.setEnabled(row >= 0) self.btn_save.setEnabled(row >= 0) @QtCore.pyqtSlot() - def on_btn_connect_pressed(self): + def on_btn_connect_pressed(self) -> None: """Connect to selected Revolution Pi.""" pi.logger.debug("AvahiSearch.on_btn_connect_pressed") if self.tb_revpi.currentRow() == -1: @@ -222,7 +253,7 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): self.accept() @QtCore.pyqtSlot() - def on_btn_save_pressed(self): + def on_btn_save_pressed(self) -> None: """Save selected Revolution Pi.""" pi.logger.debug("AvahiSearch.on_btn_save_pressed") if self.tb_revpi.currentRow() == -1: @@ -230,6 +261,6 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): self.connect_index = self._save_connection(self.tb_revpi.currentRow()) @QtCore.pyqtSlot() - def on_btn_restart_pressed(self): + def on_btn_restart_pressed(self) -> None: """Clean up an restart search thread.""" self._restart_search() diff --git a/revpicommander/revpicommander.py b/revpicommander/revpicommander.py index 9d541be..18ebadf 100755 --- a/revpicommander/revpicommander.py +++ b/revpicommander/revpicommander.py @@ -94,6 +94,19 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander): # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # region # REGION: Connection management + def _pyload_connect(self, settings_index: int) -> None: + if not helper.cm.pyload_connect(settings_index): + QtWidgets.QMessageBox.critical( + self, self.tr("Error"), self.tr( + "Can not connect to RevPi XML-RPC Service! \n\n" + "This could have the following reasons: The RevPi is not " + "online, the XML-RPC service is not running / bind to " + "localhost or the ACL permission is not set for your " + "IP!!!\n\nRun 'sudo revpipyload_secure_installation' on " + "Revolution Pi to setup this function!" + ) + ) + @QtCore.pyqtSlot(str) def on_cm_connection_error_observed(self, message: str): """ @@ -199,7 +212,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander): """Search for Revolution Pi with zero conf.""" if self.diag_search.exec() == QtWidgets.QDialog.Accepted: if self.diag_search.connect_index >= 0: - helper.cm.pyload_connect(self.diag_search.connect_index) + self._pyload_connect(self.diag_search.connect_index) self._load_men_connections() @@ -358,17 +371,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander): @QtCore.pyqtSlot(QtWidgets.QAction) def on_men_connections_triggered(self, action: QtWidgets.QAction): """A connection is selected in the men_connections menu.""" - if not helper.cm.pyload_connect(action.data()): - QtWidgets.QMessageBox.critical( - self, self.tr("Error"), self.tr( - "Can not connect to RevPi XML-RPC Service! \n\n" - "This could have the following reasons: The RevPi is not " - "online, the XML-RPC service is not running / bind to " - "localhost or the ACL permission is not set for your " - "IP!!!\n\nRun 'sudo revpipyload_secure_installation' on " - "Revolution Pi to setup this function!" - ) - ) + self._pyload_connect(action.data()) @QtCore.pyqtSlot() def on_act_webpage_triggered(self):