class VisualTraceRoute(QMainWindow, visual_traceroute_ui.Ui_visual_traceroute_main_window): """ Performs a trace route on a given IP address, and displays as a raw text output and an overlay on top of Google Maps. This makes use of http://ip-api.com to determine the latitude and longitude (among other attributes) of each IP address in the route. """ def __init__(self): """ Sets up the initial windows """ super(VisualTraceRoute, self).__init__() self.setupUi(self) self.statusbar.show() self.setWindowTitle("Visual TraceRoute") self.setWindowIcon(QIcon('network-icon.png')) self.routeListObjectWrapper = RouteWrapper() # set up buttons self.doLookupPushButton.setToolTip("start Trace Route") self.doLookupPushButton.clicked.connect(self.onClickDoItButton) self.doLookupPushButton.setAutoDefault(True) # set up menu handlers self.aboutMenuItem.triggered.connect(self.onAboutClicked) self.exitMenuItem.triggered.connect(self.close) # set up async worker thread self.traceRouteThreadedHandler = None # set up web view hbx = QHBoxLayout() self.map.setLayout(hbx) self.web = QWebView() self.web.page().mainFrame().javaScriptWindowObjectCleared.connect(self.addJavascriptObjects) self.web.page().mainFrame().addToJavaScriptWindowObject("route_list", self.routeListObjectWrapper) hbx.addWidget(self.web) self.web.show() @pyqtSlot() def addJavascriptObjects(self): """ Needed to repopulate the Javascript with the python objects each time the web page is refreshed :return: None """ self.web.page().mainFrame().addToJavaScriptWindowObject("route_list", self.routeListObjectWrapper) @pyqtSlot() def onClickDoItButton(self): """ Called when the 'DoIt' button is pressed. Reads the entered URL, validates it and initiates the trace route command :return: None """ try: self.statusbar.clearMessage() self.statusbar.showMessage("Working...") self.doLookupPushButton.setEnabled(False) self.textOutput.clear() # read entered URL url = self.urlLineEdit.text() if url: with open("./busy.html", "r") as htmlFile: html = htmlFile.read() self.web.setHtml(html) self.traceRouteThreadedHandler = TraceRoute(url) # set up callbacks for the trace route output self.traceRouteThreadedHandler.traceRouteTerminated.connect(self.onTraceRouteComplete) self.traceRouteThreadedHandler.textOutputReady.connect(self.onTraceRouteRawOutput) self.traceRouteThreadedHandler.start() else: self.statusbar.showMessage("URL is invalid", 5000) self.doLookupPushButton.setEnabled(True) QMessageBox.information(self, "Empty Field", "The entered URL is invalid") except Exception as e: QMessageBox.critical(self, "Critical", "Problem initiating trace route : " + str(e)) @pyqtSlot(str) def onTraceRouteRawOutput(self, command_output): """ Accepts a single line of text from the traceroute command, and displays on the text view :param command_output: a single line from the traceroute output :return: None """ try: self.textOutput.moveCursor(QTextCursor.End) self.textOutput.insertPlainText(command_output) except Exception as e: QMessageBox.critical(self, "Critical", "Problem updating UI with traceroute text output : " + str(e)) @pyqtSlot(object) def onTraceRouteComplete(self, route_list): """ Called when the trace route command is complete. Takes the entire route list, passes it to the Javascript and draws the visual trace route :param route_list: a list of IP addresses :return: None """ try: self.doLookupPushButton.setEnabled(True) self.doLookupPushButton.update() self.statusbar.clearMessage() self.statusbar.showMessage("Complete!") self.routeListObjectWrapper.clear() self.routeListObjectWrapper.add(route_list) self.web.page().mainFrame().addToJavaScriptWindowObject("route_list", self.routeListObjectWrapper) with open("./map_js.html", "r") as htmlFile: html = htmlFile.read() self.web.setHtml(html) except Exception as e: QMessageBox.critical(self, "Critical", "Problem performing TraceRoute command : " + str(e)) @pyqtSlot() def onAboutClicked(self): box = QMessageBox.information(self, "About Visual TraceRoute", "Visual trace route") def closeEvent(self, event): """ Intercepts the app exit event :param event: incoming close event :return: None """ quit_msg = "Are you sure you want to exit the program?" reply = QMessageBox.question(self, 'Message', quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore()
class VisualTraceRoute(QMainWindow, visual_traceroute_ui.Ui_visual_traceroute_main_window): """ Performs a trace route on a given IP address, and displays as a raw text output and an overlay on top of Google Maps. This makes use of http://ip-api.com to determine the latitude and longitude (among other attributes) of each IP address in the route. """ def __init__(self): """ Sets up the initial windows """ super(VisualTraceRoute, self).__init__() self.setupUi(self) self.statusbar.show() self.setWindowTitle("Visual TraceRoute") self.setWindowIcon(QIcon('network-icon.png')) self.routeListObjectWrapper = RouteWrapper() # set up buttons self.doLookupPushButton.setToolTip("start Trace Route") self.doLookupPushButton.clicked.connect(self.onClickDoItButton) self.doLookupPushButton.setAutoDefault(True) # set up menu handlers self.aboutMenuItem.triggered.connect(self.onAboutClicked) self.exitMenuItem.triggered.connect(self.close) # set up async worker thread self.traceRouteThreadedHandler = None # set up web view hbx = QHBoxLayout() self.map.setLayout(hbx) self.web = QWebView() self.web.page().mainFrame().javaScriptWindowObjectCleared.connect( self.addJavascriptObjects) self.web.page().mainFrame().addToJavaScriptWindowObject( "route_list", self.routeListObjectWrapper) hbx.addWidget(self.web) self.web.show() @pyqtSlot() def addJavascriptObjects(self): """ Needed to repopulate the Javascript with the python objects each time the web page is refreshed :return: None """ self.web.page().mainFrame().addToJavaScriptWindowObject( "route_list", self.routeListObjectWrapper) @pyqtSlot() def onClickDoItButton(self): """ Called when the 'DoIt' button is pressed. Reads the entered URL, validates it and initiates the trace route command :return: None """ try: self.statusbar.clearMessage() self.statusbar.showMessage("Working...") self.doLookupPushButton.setEnabled(False) self.textOutput.clear() # read entered URL url = self.urlLineEdit.text() if url: with open("./busy.html", "r") as htmlFile: html = htmlFile.read() self.web.setHtml(html) self.traceRouteThreadedHandler = TraceRoute(url) # set up callbacks for the trace route output self.traceRouteThreadedHandler.traceRouteTerminated.connect( self.onTraceRouteComplete) self.traceRouteThreadedHandler.textOutputReady.connect( self.onTraceRouteRawOutput) self.traceRouteThreadedHandler.start() else: self.statusbar.showMessage("URL is invalid", 5000) self.doLookupPushButton.setEnabled(True) QMessageBox.information(self, "Empty Field", "The entered URL is invalid") except Exception as e: QMessageBox.critical(self, "Critical", "Problem initiating trace route : " + str(e)) @pyqtSlot(str) def onTraceRouteRawOutput(self, command_output): """ Accepts a single line of text from the traceroute command, and displays on the text view :param command_output: a single line from the traceroute output :return: None """ try: self.textOutput.moveCursor(QTextCursor.End) self.textOutput.insertPlainText(command_output) except Exception as e: QMessageBox.critical( self, "Critical", "Problem updating UI with traceroute text output : " + str(e)) @pyqtSlot(object) def onTraceRouteComplete(self, route_list): """ Called when the trace route command is complete. Takes the entire route list, passes it to the Javascript and draws the visual trace route :param route_list: a list of IP addresses :return: None """ try: self.doLookupPushButton.setEnabled(True) self.doLookupPushButton.update() self.statusbar.clearMessage() self.statusbar.showMessage("Complete!") self.routeListObjectWrapper.clear() self.routeListObjectWrapper.add(route_list) self.web.page().mainFrame().addToJavaScriptWindowObject( "route_list", self.routeListObjectWrapper) with open("./map_js.html", "r") as htmlFile: html = htmlFile.read() self.web.setHtml(html) except Exception as e: QMessageBox.critical( self, "Critical", "Problem performing TraceRoute command : " + str(e)) @pyqtSlot() def onAboutClicked(self): box = QMessageBox.information(self, "About Visual TraceRoute", "Visual trace route") def closeEvent(self, event): """ Intercepts the app exit event :param event: incoming close event :return: None """ quit_msg = "Are you sure you want to exit the program?" reply = QMessageBox.question(self, 'Message', quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: event.accept() else: event.ignore()