diff --git a/include/ui/avahisearch_ui.py b/include/ui/avahisearch_ui.py index 2392632..7bdd55b 100644 --- a/include/ui/avahisearch_ui.py +++ b/include/ui/avahisearch_ui.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'avahisearch.ui' # -# Created by: PyQt5 UI code generator 5.14.1 +# Created by: PyQt5 UI code generator 5.15.7 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets @@ -64,9 +65,15 @@ class Ui_diag_search(object): self.btn_box.setStandardButtons(QtWidgets.QDialogButtonBox.Close) self.btn_box.setObjectName("btn_box") self.gridLayout.addWidget(self.btn_box, 3, 0, 1, 2) + self.act_copy_host = QtWidgets.QAction(diag_search) + self.act_copy_host.setObjectName("act_copy_host") + self.act_copy_ip = QtWidgets.QAction(diag_search) + self.act_copy_ip.setObjectName("act_copy_ip") + self.act_open_pictory = QtWidgets.QAction(diag_search) + self.act_open_pictory.setObjectName("act_open_pictory") self.retranslateUi(diag_search) - self.btn_box.rejected.connect(diag_search.reject) + self.btn_box.rejected.connect(diag_search.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(diag_search) def retranslateUi(self, diag_search): @@ -81,6 +88,9 @@ class Ui_diag_search(object): item.setText(_translate("diag_search", "IP address")) self.btn_connect.setText(_translate("diag_search", "&Connect to Revolution Pi")) self.btn_save.setText(_translate("diag_search", "&Save connection")) + self.act_copy_host.setText(_translate("diag_search", "Copy host name")) + self.act_copy_ip.setText(_translate("diag_search", "Copy IP address")) + self.act_open_pictory.setText(_translate("diag_search", "Open piCtory")) from . import ressources_rc diff --git a/include/ui_dev/avahisearch.ui b/include/ui_dev/avahisearch.ui index bf70a5c..b5e9cdb 100644 --- a/include/ui_dev/avahisearch.ui +++ b/include/ui_dev/avahisearch.ui @@ -120,6 +120,21 @@ + + + Copy host name + + + + + Copy IP address + + + + + Open piCtory + + diff --git a/revpicommander/avahisearch.py b/revpicommander/avahisearch.py index 70ba111..ebfaff0 100644 --- a/revpicommander/avahisearch.py +++ b/revpicommander/avahisearch.py @@ -4,8 +4,10 @@ __author__ = "Sven Sager" __copyright__ = "Copyright (C) 2020 Sven Sager" __license__ = "GPLv3" +import webbrowser from os import name as osname from re import compile +from sys import platform from PyQt5 import QtCore, QtGui, QtWidgets from zeroconf import IPVersion, ServiceBrowser, Zeroconf @@ -92,6 +94,7 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): super(AvahiSearch, self).__init__(parent) self.setupUi(self) + self.clipboard = QtGui.QGuiApplication.clipboard() self.connect_index = -1 self.known_hosts = {} self.th_zero_conf = AvahiSearchThread(self) @@ -106,6 +109,23 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): for i in range(self.tb_revpi.columnCount()): self.tb_revpi.setColumnWidth(i, int(column_sizes[i])) + # Global context menus + self.cm_quick_actions = QtWidgets.QMenu(self) + self.cm_quick_actions.addAction(self.act_open_pictory) + self.cm_quick_actions.addSeparator() + self.cm_quick_actions.addAction(self.act_copy_ip) + self.cm_quick_actions.addAction(self.act_copy_host) + + self.tb_revpi.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.tb_revpi.customContextMenuRequested.connect(self._context_menu) + + @QtCore.pyqtSlot(QtCore.QPoint) + def _context_menu(self, position: QtCore.QPoint) -> None: + sender = self.sender() + action = self.cm_quick_actions.exec(sender.mapToGlobal(position)) + if action: + action.trigger() + def _load_known_hosts(self) -> None: """Load existing connections to show hostname of existing ip addresses""" self.known_hosts.clear() @@ -201,6 +221,40 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): self.th_zero_conf.requestInterruption() return rc + @QtCore.pyqtSlot() + def on_act_copy_host_triggered(self) -> None: + """Copy ip address of selected item to clipboard.""" + selected_items = self.tb_revpi.selectedItems() + if not selected_items: + return + item = selected_items[0] + host_name = item.data(WidgetData.host_name) + if platform == "win32": + # Strip hostname on Windows systems, it can not resolve .local addresses + host_name = host_name[:host_name.find(".")] + self.clipboard.setText(host_name) + + @QtCore.pyqtSlot() + def on_act_copy_ip_triggered(self) -> None: + """Copy ip address of selected item to clipboard.""" + selected_items = self.tb_revpi.selectedItems() + if not selected_items: + return + item = selected_items[0] + self.clipboard.setText(item.data(WidgetData.address)) + + @QtCore.pyqtSlot() + def on_act_open_pictory_triggered(self) -> None: + """Open piCtory in default browser of operating system.""" + selected_items = self.tb_revpi.selectedItems() + if not selected_items: + return + item = selected_items[0] + if platform == "win32": + webbrowser.open("http://{0}/".format(item.data(WidgetData.address))) + else: + webbrowser.open("http://{0}/".format(item.data(WidgetData.host_name))) + @QtCore.pyqtSlot(str, str, int, str, str) def on_avahi_added(self, name: str, server: str, port: int, conf_type: str, ip: str) -> None: """New Revolution Pi found.""" @@ -224,14 +278,16 @@ class AvahiSearch(QtWidgets.QDialog, Ui_diag_search): item_name = self.tb_revpi.item(index, 0) item_ip = self.tb_revpi.item(index, 1) + host_name = server[:-1] item_name.setIcon(QtGui.QIcon(":/main/ico/cpu.ico")) if ip in self.known_hosts: - item_name.setText("{0} ({1})".format(server[:-1], self.known_hosts[ip])) + item_name.setText("{0} ({1})".format(host_name, self.known_hosts[ip])) else: - item_name.setText(server[:-1]) + item_name.setText(host_name) item_name.setData(WidgetData.object_name, name) item_name.setData(WidgetData.address, ip) item_name.setData(WidgetData.port, port) + item_name.setData(WidgetData.host_name, host_name) item_ip.setText(ip) @QtCore.pyqtSlot(str, str) diff --git a/revpicommander/helper.py b/revpicommander/helper.py index 9d2ad6a..18e7727 100644 --- a/revpicommander/helper.py +++ b/revpicommander/helper.py @@ -27,6 +27,7 @@ class WidgetData(IntEnum): port = 264 object_name = 265 timeout = 266 + host_name = 267 last_dir_upload = 301 last_file_upload = 302 last_dir_pictory = 303