Improved RevPi search window

Show names of already saved connections in parentheses
Show connection error message if we can not connect to RevPi
Save and restore geometry and column width
This commit is contained in:
2021-06-13 21:30:59 +02:00
parent 1354568eb6
commit f215b3bbc1
2 changed files with 64 additions and 30 deletions

View File

@@ -31,7 +31,7 @@ class AvahiSearchThread(QtCore.QThread):
r"(?P<mac>([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()

View File

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