class App(QMainWindow): def __init__(self, args=None): super().__init__() self.args = args self.initModel() self.initUI() self.snipWidget = SnipWidget(self) self.show() def initModel(self): args, *objs = pix2tex.initialize(self.args) self.args = args self.objs = objs def initUI(self): self.setWindowTitle("LaTeX OCR") QApplication.setWindowIcon(QtGui.QIcon(':/icons/icon.svg')) self.left = 300 self.top = 300 self.width = 500 self.height = 300 self.setGeometry(self.left, self.top, self.width, self.height) # Create LaTeX display self.webView = QWebEngineView() self.webView.setHtml("") self.webView.setMinimumHeight(80) # Create textbox self.textbox = QTextEdit(self) self.textbox.textChanged.connect(self.displayPrediction) self.textbox.setMinimumHeight(40) # Create temperature text input self.tempField = QDoubleSpinBox(self) self.tempField.setValue(self.args.get('temperature', 0.25)) self.tempField.setRange(0, 1) self.tempField.setSingleStep(0.1) # Create snip button self.snipButton = QPushButton('Snip', self) self.snipButton.clicked.connect(self.onClick) # Create retry button self.retryButton = QPushButton('Retry', self) self.retryButton.setEnabled(False) self.retryButton.clicked.connect(self.returnSnip) # Create layout centralWidget = QWidget() centralWidget.setMinimumWidth(200) self.setCentralWidget(centralWidget) lay = QVBoxLayout(centralWidget) lay.addWidget(self.webView, stretch=4) lay.addWidget(self.textbox, stretch=2) buttons = QHBoxLayout() buttons.addWidget(self.snipButton) buttons.addWidget(self.retryButton) lay.addLayout(buttons) settings = QFormLayout() settings.addRow('Temperature:', self.tempField) lay.addLayout(settings) @pyqtSlot() def onClick(self): self.close() self.snipWidget.snip() def returnSnip(self, img=None): # Show processing icon pageSource = """<center> <img src="qrc:/icons/processing-icon-anim.svg" width="50", height="50"> </center>""" self.webView.setHtml(pageSource) self.snipButton.setEnabled(False) self.retryButton.setEnabled(False) self.show() try: self.args.temperature = self.tempField.value() if self.args.temperature == 0: self.args.temperature = 1e-8 except: pass # Run the model in a separate thread self.thread = ModelThread(img=img, args=self.args, objs=self.objs) self.thread.finished.connect(self.returnPrediction) self.thread.finished.connect(self.thread.deleteLater) self.thread.start() def returnPrediction(self, result): self.snipButton.setEnabled(True) success, prediction = result["success"], result["prediction"] if success: self.displayPrediction(prediction) self.retryButton.setEnabled(True) else: self.webView.setHtml("") msg = QMessageBox() msg.setWindowTitle(" ") msg.setText("Prediction failed.") msg.exec_() def displayPrediction(self, prediction=None): if prediction is not None: self.textbox.setText("${equation}$".format(equation=prediction)) else: prediction = self.textbox.toPlainText().strip('$') pageSource = """ <html> <head><script id="MathJax-script" src="qrc:MathJax.js"></script> <script> MathJax.Hub.Config({messageStyle: 'none',tex2jax: {preview: 'none'}}); MathJax.Hub.Queue( function () { document.getElementById("equation").style.visibility = ""; } ); </script> </head> """ + """ <body> <div id="equation" style="font-size:1em; visibility:hidden">$${equation}$$</div> </body> </html> """.format(equation=prediction) self.webView.setHtml(pageSource)
class View_Main(QMainWindow, Ui_MainWindow): classroom_briefs = [] class_brief_threads = [] view_real_time = None def __init__(self): super().__init__() self.setupUi(self) # 四个页面的切换 self.widget_building.clicked.connect(self.change_page_class) self.widget_status.clicked.connect(self.change_page_status) self.widget_abnormal.clicked.connect(self.change_page_abnormal) self.widget_record.clicked.connect(self.change_page_record) # 从数据库读取教室信息 get_class_briefs(self.classroom_briefs) # 多线程完成教室初始化显示 threads = [] for brief in self.classroom_briefs: threads.append( threading.Thread(target=init_thumbnail, args=(brief, ))) for thread in threads: thread.start() thread.join() # 注册教室列表 self.class_web = QWebEngineView(self.page_class) self.class_channel = QWebChannel(self.class_web.page()) self.class_obj = ClassObj() # 注册按教学楼分类的标题组件 self.building_title_web = QWebEngineView(self.page_class) self.building_title_web.setMaximumHeight(90) self.building_title_web.setMinimumHeight(90) self.building_title_channel = QWebChannel( self.building_title_web.page()) self.building_title_obj = BuildingTitleObj() # 注册按状态分类的标题栏组件 self.state_title_web = QWebEngineView(self.page_class) self.state_title_web.setMinimumHeight(65) self.state_title_web.setMaximumHeight(65) self.state_title_channel = QWebChannel(self.state_title_web.page()) self.state_title_obj = StateTitleObj() self.setup_class_page() # 注册上课回看列表需要的组件 self.record_list_page = QWebEngineView(self.page_reocrd) self.record_list_channel = QWebChannel(self.record_list_page.page()) self.record_list_obj = RecordListObj() self.setup_record_table() def setup_class_page(self): # 初始化按教学楼搜索标题栏 self.building_title_obj.sig_confirm_clicked.connect( self.sift_by_building) self.building_title_channel.registerObject('building_title_obj', self.building_title_obj) self.building_title_web.page().setWebChannel( self.building_title_channel) self.building_title_web.load( QUrl.fromLocalFile( os.path.abspath('view/html/TitleBuilding.html'))) # 初始化按状态搜索标题栏 self.state_title_channel.registerObject('state_title_obj', self.state_title_obj) self.state_title_web.page().setWebChannel(self.state_title_channel) self.state_title_web.load( QUrl.fromLocalFile(os.path.abspath('view/html/TitleState.html'))) self.state_title_web.hide() # 初始化教室页面 self.class_obj.sig_class_item_clicked.connect(self.open_real_time) self.class_channel.registerObject('class_obj', self.class_obj) self.class_web.page().setWebChannel(self.class_channel) self.class_web.load( QUrl.fromLocalFile(os.path.abspath('view/html/ClassTable.html'))) self.class_web.loadFinished.connect(self.refresh_page) self.verticalLayout_7.addWidget(self.building_title_web) self.verticalLayout_7.addWidget(self.state_title_web) self.verticalLayout_7.addWidget(self.class_web) # 统计学生人数线程对象生成 for brief in self.classroom_briefs: self.class_brief_threads.append( ClassBriefThread(brief, self.class_web.page())) for thread in self.class_brief_threads: thread.start() def refresh_page(self): # 刷新教室列表的显示 init_table = '' for brief in self.classroom_briefs: if brief.isShow: init_table += HTMLFactory.get_instance().class_brief_box_first( brief) self.class_web.page().runJavaScript( "setupTable('{0}')".format(init_table)) def open_real_time(self, class_brief_id): for brief in self.classroom_briefs: if brief.classroom.classroom_id == class_brief_id: print( ">>>>>>>>>>>>>>>>>>>>>> classroom {0} begin to be monitored" .format(class_brief_id)) for thread in self.class_brief_threads: thread.pause() time.sleep(2) self.view_real_time = View_RealTime(brief) self.view_real_time.sig_on_closed.connect(self.resume) self.view_real_time.showMaximized() break def sift_by_building(self, campus, building, floor): # 按照教学楼显示 # 根据校区、教学楼、教室号来进行筛选 for brief in self.classroom_briefs: if (campus in brief.classroom.campus) and ( building in brief.classroom.building) and ( floor in brief.classroom.floor): if not brief.isShow: self.add_box(brief) brief.isShow = True elif brief.isShow: self.remove_box(brief) brief.isShow = False # 初始化上课回看列表 def setup_record_table(self): self.record_list_obj.sig_record_list_item_clicked.connect( self.open_replay) self.record_list_channel.registerObject('record_list_obj', self.record_list_obj) self.record_list_page.page().setWebChannel(self.record_list_channel) self.verticalLayout_10.addWidget(self.record_list_page) self.record_list_page.load( QUrl.fromLocalFile(os.path.abspath('view/html/Record.html'))) def open_replay(self, item_id): self.view_replay = View_Replay() self.view_replay.showMaximized() def change_page_class(self): for thread in self.class_brief_threads: thread.resume() self.stackedWidget.setCurrentIndex(0) self.building_title_web.show() self.state_title_web.hide() for brief in self.classroom_briefs: if not brief.isShow: self.add_box(brief) brief.isShow = True def change_page_status(self): for thread in self.class_brief_threads: thread.resume() self.stackedWidget.setCurrentIndex(0) self.building_title_web.hide() self.state_title_web.show() for brief in self.classroom_briefs: if not brief.isShow: self.add_box(brief) brief.isShow = True def change_page_abnormal(self): for thread in self.class_brief_threads: thread.resume() self.stackedWidget.setCurrentIndex(0) self.building_title_web.hide() self.state_title_web.hide() for brief in self.classroom_briefs: if brief.isAbnormal: if not brief.isShow: self.add_box(brief) brief.isShow = True else: if brief.isShow: self.remove_box(brief) brief.isShow = False def add_box(self, brief): box = HTMLFactory.get_instance().class_brief_box_first(brief) update_class_table_lock.acquire() self.class_web.page().runJavaScript("addBox('{0}')".format(box)) update_class_table_lock.release() def remove_box(self, brief): update_class_table_lock.acquire() self.class_web.page().runJavaScript("removeBox('class_{}')".format( brief.classroom.classroom_id)) update_class_table_lock.release() def change_page_record(self): self.stackedWidget.setCurrentIndex(1) for thread in self.class_brief_threads: thread.pause() # 关闭实时监控页之后调用 def resume(self): for thread in self.class_brief_threads: thread.resume()
class App(QWidget): def __init__(self, parent=None): super().__init__(parent) self.actions = [] self.project = Project() self.create_window() def create_window(self): # labels nameLabel = QLabel("Nazwa akcji", self) nameLabel.setFixedWidth(100) durationLabel = QLabel("Czas trwania akcji", self) durationLabel.setFixedWidth(100) predLabel = QLabel("Poprzednicy [;]", self) predLabel.setFixedWidth(100) self.criticalPathLabel = QLabel("Ścieżka krytyczna: ", self) self.timeLabel = QLabel("Czas trwania: ", self) self.messageLabel = QLabel("", self) self.graphLabel = QLabel(self) pixmap2 = QPixmap('images/graph.png') self.graphLabel.setPixmap(pixmap2) # entries self.nameEntry = QLineEdit() self.nameEntry.setFixedWidth(150) self.durationEntry = QLineEdit() self.durationEntry.setFixedWidth(150) self.predEntry = QLineEdit() self.predEntry.setFixedWidth(150) # buttons addButton = QPushButton("Dodaj czynność", self) addButton.setFixedWidth(100) computeButton = QPushButton("Oblicz", self) computeButton.setFixedWidth(100) # buttons action addButton.clicked.connect(self.add_action) computeButton.clicked.connect(self.compute_task) # web view self.view = QWebEngineView(self) self.view.setMinimumWidth(800) self.view.setMinimumHeight(600) url = QtCore.QUrl.fromLocalFile(r"/temp-plot.html") self.view.load(url) # grid hboxRow1 = QHBoxLayout() hboxRow1.addWidget(nameLabel) hboxRow1.addWidget(self.nameEntry) hboxRow1.addWidget(addButton) hboxRow1.addStretch(1) hboxRow2 = QHBoxLayout() hboxRow2.addWidget(durationLabel) hboxRow2.addWidget(self.durationEntry) hboxRow2.addWidget(computeButton) hboxRow2.addStretch(1) hboxRow3 = QHBoxLayout() hboxRow3.addWidget(predLabel) hboxRow3.addWidget(self.predEntry) hboxRow3.addStretch(1) vboxRowLast = QVBoxLayout() vboxRowLast.addWidget(self.criticalPathLabel) vboxRowLast.addWidget(self.timeLabel) vboxEntryData = QVBoxLayout() vboxEntryData.addLayout(hboxRow1) vboxEntryData.addLayout(hboxRow2) vboxEntryData.addLayout(hboxRow3) vboxEntryData.addLayout(vboxRowLast) vboxGraphInfo = QVBoxLayout() vboxGraphInfo.addWidget(self.graphLabel) vboxGraphInfo.addStretch(1) vboxGraphInfo.addWidget(self.messageLabel) vboxLeftSide = QVBoxLayout() vboxLeftSide.addLayout(vboxEntryData) vboxLeftSide.addStretch(1) vboxLeftSide.addLayout(vboxGraphInfo) hboxFinal = QHBoxLayout() hboxFinal.addLayout(vboxLeftSide) hboxFinal.addStretch(1) hboxFinal.addWidget(self.view) self.setLayout(hboxFinal) self.resize(500, 500) self.setWindowTitle("App") self.show() def add_action(self): name = self.nameEntry.text() duration = self.durationEntry.text() if self.predEntry.text() == '': pred = [] else: pred = self.predEntry.text().split(";") try: #s self.actions.append(Action(name, duration, pred)) self.messageLabel.setText("Dodano czynność: " + name) except Exception as error: self.messageLabel.setText(error.args[0]) self.actions = [] for task in self.actions: print(task.name + " " + str(task.duration) + " " + str(task.predecessors)) def compute_task(self): if self.actions != []: self.project.create_network(self.actions) cp = self.project.get_critical_path() dr = self.project.get_duration() create_graph_image(self.actions, cp) self.graphLabel.setPixmap(QPixmap('images/graph.png')) create_gantt_chart(self.actions, cp) url = QtCore.QUrl.fromLocalFile(r"/temp-plot.html") self.view.load(url) # self.ganttLabel.setPixmap(QPixmap('images/gantt.png')) self.timeLabel.setText("Czas trwania " + str(dr) + "h") string_cp = str(cp[0]) for node in cp[1:]: string_cp += " -> " + str(node) self.criticalPathLabel.setText(string_cp) self.actions = [] self.project = Project() else: self.messageLabel.setText("Brak danych!") self.actions = [] self.project = Project()
class OWPlotlyViewer(SparkEnvironment, widget.OWWidget): # --------------- Widget metadata protocol --------------- priority = 2 name = "Plotly" description = "A plotly canvas" icon = "../assets/DataFrameViewer.svg" input_figure: go.Figure = None class Inputs: figure = widget.Input("Figure", go.Figure) class Outputs: pass #data_frame = widget.Output("DataFrame", pyspark.sql.DataFrame) want_control_area = True def __init__(self): super().__init__() self.controlArea.setMinimumWidth(250) self.v_info_box = gui.vBox(self.controlArea, 'Info') self.v_info = gui.label(self.v_info_box, self, '') self.v_info.setAlignment(QtCore.Qt.AlignTop) self.mainArea.setMinimumWidth(800) self.mainArea.setMinimumHeight(600) self.v_webview = QWebEngineView(self.mainArea) self.v_webview.setMinimumWidth(800) self.v_webview.setMinimumHeight(600) @Inputs.figure def set_input_figure(self, figure): self.input_figure = figure # called after received all inputs def handleNewSignals(self): self.apply() def _check_input(self): if self.input_figure is None: self.warning('Input figure does not exist') return False else: return True # this is the logic: computation, update UI, send outputs. .. def apply(self): if not self._check_input(): return self.clear_messages() filename = tempfile.NamedTemporaryFile(suffix='.html').name print('Plot file path: %s' % filename) plotly.offline.plot(self.input_figure, output_type='file', filename=filename, auto_open=False, show_link=False) # , include_plotlyjs=True) self.v_webview.load(QUrl.fromLocalFile(filename))
# loop.exec_() # html = webview.page().mainFrame().toHtml() # tree = lxml.html.fromstring(html) # content = tree.cssselect('#result')[0].text # print(content) ## 新版本使用 # pip install PySide2==5.12.0 # pip install PyQt5==5.11.3 # try: # from PySide2.QtCore import QUrl # from PySide2.QtWidgets import QApplication # from PySide2.QtWebEngineWidgets import QWebEnginePage, QWebEngineView # except: from PyQt5.QtCore import QUrl from PyQt5.QtWidgets import QApplication from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineView # 弹窗显示 url = 'http://example.webscraping.com/places/default/search' app = QApplication([]) view = QWebEngineView() view.setWindowTitle("阿尔法科技有限公司") view.setMinimumWidth(1000) view.setMinimumHeight(800) view.load(QUrl(url)) view.show() app.exec() # 基于webkit的解决方案 # Ghost是Selenium 与PhantomJS 的结合体,安装时会携带PySide,PyQt4 # pip install Ghost==0.5.0
class MainWindow(QWidget): def __init__(self): super().__init__() # Init a state dict self.state = { "internet": { "connected": False, }, "serial": { "client": serial.Serial(), "connected": False, "device": "", "baud": 0, }, "mqtt": { "client": mqtt.Client(), "connected": False, "hostname": "", "port": "", "username": "", } } # Grab config self.config = configparser.ConfigParser() self.config.read('config.ini') # Setup MQTT Callbacks self.state["mqtt"]["client"].on_connect = self.mqtt_on_connect self.state["mqtt"]["client"].on_disconnect = self.mqtt_on_disconnect self.state["mqtt"]["client"].on_subscribe = self.mqtt_on_subscribe self.state["mqtt"]["client"].on_unsubscribe = self.mqtt_on_unsubscribe self.state["mqtt"]["client"].on_publish = self.mqtt_on_publish self.state["mqtt"]["client"].on_message = self.mqtt_on_message self.state["mqtt"]["client"].on_log = self.mqtt_on_log # Setup support things self.create_icons() # Setup main window self.layout_main_window = QGridLayout() self.setWindowTitle("Icarus GCS") self.setWindowIcon(QIcon('assets/balloon_map_icon.png')) self.create_toolbar_interface() self.create_map_interface() self.create_serial_interface() self.create_mqtt_interface() self.layout_main_window.addWidget(self.toolbar_status, 0, 1, 1, -1) self.layout_main_window.addWidget(self.webengine_map, 1, 1, -1, -1) self.layout_main_window.addWidget(self.groupbox_serial_interface, 0, 0, 2, 1) self.layout_main_window.addWidget(self.groupbox_mqtt_interface, 2, 0) self.setLayout(self.layout_main_window) # Setup timers for events self.timer_internet_status = QTimer(self) self.timer_internet_status.timeout.connect( self.on_timer_internet_status) self.timer_internet_status.start(5 * 1000) # Check timed events once at the start # self.on_timer_internet_status() # Let's do this! self.show() def create_toolbar_interface(self): self.toolbar_status = QToolBar() self.toolbar_status.setFloatable(False) self.toolbar_status.setMovable(False) self.toolbar_status.setIconSize(QSize(24, 24)) self.toolbutton_internet_status = QToolButton() self.toolbutton_internet_status.setIcon(self.icons["cloud-line"]) self.toolbutton_internet_status.setEnabled(False) self.toolbutton_mqtt_status = QToolButton() self.toolbutton_mqtt_status.setIcon(self.icons["server-line"]) self.toolbutton_mqtt_status.setEnabled(False) self.toolbutton_radio_status = QToolButton() self.toolbutton_radio_status.setIcon(self.icons["wifi-line"]) self.toolbutton_radio_status.setEnabled(False) self.toolbutton_cellular_status = QToolButton() self.toolbutton_cellular_status.setIcon(self.icons["sim-card-line"]) self.toolbutton_cellular_status.setEnabled(False) self.toolbutton_heartbeat_status = QToolButton() self.toolbutton_heartbeat_status.setIcon(self.icons["heart-line"]) self.toolbutton_heartbeat_status.setEnabled(False) self.toolbar_status.addWidget(self.toolbutton_internet_status) self.toolbar_status.addWidget(self.toolbutton_mqtt_status) self.toolbar_status.addWidget(self.toolbutton_radio_status) self.toolbar_status.addWidget(self.toolbutton_cellular_status) self.toolbar_status.addWidget(self.toolbutton_heartbeat_status) def create_map_interface(self): self.webengine_map = QWebEngineView() self.map_wrapper = MapWrapper( self.webengine_map, { "home_latitude": self.config["Map"]["Home Latitude"], "home_longitude": self.config["Map"]["Home Longitude"], "home_zoom": self.config["Map"]["Zoom Level"], "max_zoom": self.config["Map"]["Max Zoom Level"], "min_zoom": self.config["Map"]["Min Zoom Level"], }) self.map_view_webchannel = QWebChannel() self.map_view_webchannel.registerObject("python_link", self.map_wrapper) self.webengine_map.page().setWebChannel(self.map_view_webchannel) self.webengine_map.load( QtCore.QUrl.fromLocalFile( QtCore.QDir.current().filePath("static/map.html"))) self.webengine_map.setMinimumWidth(1024) self.webengine_map.setMinimumHeight(768) def create_serial_interface(self): self.groupbox_serial_interface = QGroupBox("Serial") self.groupbox_serial_interface.setMinimumWidth(320) self.groupbox_serial_interface.setMaximumWidth(320) self.layout_serial_interface = QGridLayout() self.groupbox_serial_interface.setLayout(self.layout_serial_interface) self.label_serial_port = QLabel(self) self.label_serial_port.setText("Device:") self.label_serial_port.setMinimumWidth(100) self.label_serial_port.setMaximumWidth(100) self.combo_serial_port = QComboBox(self) devices = self.serial_list_ports() for device in devices: self.combo_serial_port.addItem(device) self.label_serial_baud_rate = QLabel(self) self.label_serial_baud_rate.setText("Baud Rate:") self.line_edit_serial_baud_rate = QLineEdit(self) self.line_edit_serial_baud_rate.setText("115200") self.button_serial_connect = QPushButton(self) self.button_serial_connect.setText("Connect") self.button_serial_connect.clicked.connect( self.button_serial_connect_clicked) self.layout_serial_interface.addWidget(self.label_serial_port, 0, 0) self.layout_serial_interface.addWidget(self.combo_serial_port, 0, 1) self.layout_serial_interface.addWidget(self.label_serial_baud_rate, 1, 0) self.layout_serial_interface.addWidget(self.line_edit_serial_baud_rate, 1, 1) self.layout_serial_interface.addWidget(self.button_serial_connect, 2, 0, 1, 2) def lock_serial_interface(self): self.combo_serial_port.setReadOnly(True) self.line_edit_serial_baud_rate.setReadOnly(True) self.button_serial_connect.setText("Disconnect") def unlock_serial_interface(self): self.combo_serial_port.setReadOnly(False) self.line_edit_serial_baud_rate.setReadOnly(False) self.button_serial_connect.setText("Connect") def serial_list_ports(self): ports = list(serial.tools.list_ports.comports(False)) devices = [] for port in ports: devices.append(str(port.description) + " (" + port.device + ")") return devices def button_serial_connect_clicked(self): if not self.state["serial"]["connected"]: selected_serial_port = self.combo_serial_port.currentText().split( "(")[1].replace(")", "") try: self.state["serial"]["client"].port = selected_serial_port self.state["serial"]["client"].baudrate = int( self.line_edit_serial_baud_rate.text()) self.state["serial"]["client"].open() self.state["serial"]["connected"] = True self.state["serial"]["device"] = selected_serial_port self.state["serial"][ "baud"] = self.line_edit_serial_baud_rate.text() self.lock_serial_interface() print("Connected to: " + self.combo_serial_port.currentText()) except serial.SerialException as e: print("Failed to connect to Serial Port: " + self.combo_serial_port.currentText()) print(e) else: try: self.serial_port.close() self.state["serial"]["connected"] = False self.state["serial"]["device"] = "" self.state["serial"]["baud"] = 0 self.unlock_serial_interface() print("Disconnected from: " + self.state["serial"]["device"]) except serial.SerialException as e: print("Failed to disconnect from: " + self.state["serial"]["device"]) print(e) def create_mqtt_interface(self): self.groupbox_mqtt_interface = QGroupBox("MQTT") self.groupbox_mqtt_interface.setMinimumWidth(320) self.groupbox_mqtt_interface.setMaximumWidth(320) self.layout_mqtt_interface = QGridLayout() self.groupbox_mqtt_interface.setLayout(self.layout_mqtt_interface) self.label_internet_status = QLabel(self) self.label_internet_status.setText("Internet:") self.label_internet_status.setMinimumWidth(100) self.label_internet_status.setMaximumWidth(100) self.line_edit_internet_status = QLineEdit(self) self.line_edit_internet_status.setText("Disconnected") self.line_edit_internet_status.setReadOnly(True) self.label_mqtt_hostname = QLabel(self) self.label_mqtt_hostname.setText("Hostname:") self.line_edit_mqtt_hostname = QLineEdit(self) self.line_edit_mqtt_hostname.setText(self.config["MQTT"]["Hostname"]) self.label_mqtt_port = QLabel(self) self.label_mqtt_port.setText("Port: ") self.line_edit_mqtt_port = QLineEdit(self) self.line_edit_mqtt_port.setText(self.config["MQTT"]["Port"]) self.label_mqtt_username = QLabel(self) self.label_mqtt_username.setText("Username: "******"MQTT"]["Username"]) self.label_mqtt_password = QLabel(self) self.label_mqtt_password.setText("Password: "******"MQTT"]["Password"]) self.line_edit_mqtt_password.setEchoMode(QLineEdit.Password) self.button_mqtt_connect = QPushButton(self) self.button_mqtt_connect.setText("Connect") self.button_mqtt_connect.clicked.connect( self.button_mqtt_connect_clicked) self.label_mqtt_topic = QLabel(self) self.label_mqtt_topic.setText("Topic:") self.line_edit_mqtt_topic = QLineEdit(self) self.button_mqtt_subscribe = QPushButton(self) self.button_mqtt_subscribe.setText("Subscribe") #self.button_mqtt_subscribe.clicked.connect(self.button_mqtt_subscribe_clicked) self.list_box_mqtt_subscriptions = QListWidget(self) self.list_box_mqtt_subscriptions.setMaximumHeight(100) self.button_mqtt_unsubscribe = QPushButton(self) self.button_mqtt_unsubscribe.setText("Unsubscribe") #self.button_mqtt_unsubscribe.clicked.connect(self.button_mqtt_unsubscribe_clicked) self.layout_mqtt_interface.addWidget(self.label_internet_status, 0, 0) self.layout_mqtt_interface.addWidget(self.line_edit_internet_status, 0, 1) self.layout_mqtt_interface.addWidget(self.label_mqtt_hostname, 1, 0) self.layout_mqtt_interface.addWidget(self.line_edit_mqtt_hostname, 1, 1) self.layout_mqtt_interface.addWidget(self.label_mqtt_port, 2, 0) self.layout_mqtt_interface.addWidget(self.line_edit_mqtt_port, 2, 1) self.layout_mqtt_interface.addWidget(self.label_mqtt_username, 3, 0) self.layout_mqtt_interface.addWidget(self.line_edit_mqtt_username, 3, 1) self.layout_mqtt_interface.addWidget(self.label_mqtt_password, 4, 0) self.layout_mqtt_interface.addWidget(self.line_edit_mqtt_password, 4, 1) self.layout_mqtt_interface.addWidget(self.button_mqtt_connect, 5, 0, 1, 2) self.layout_mqtt_interface.addWidget(self.label_mqtt_topic, 6, 0) self.layout_mqtt_interface.addWidget(self.line_edit_mqtt_topic, 6, 1) self.layout_mqtt_interface.addWidget(self.button_mqtt_subscribe, 7, 0, 1, 2) self.layout_mqtt_interface.addWidget(self.list_box_mqtt_subscriptions, 8, 0, 1, 2) self.layout_mqtt_interface.addWidget(self.button_mqtt_unsubscribe, 9, 0, 1, 2) def lock_mqtt_interface(self): self.line_edit_mqtt_hostname.setReadOnly(True) self.line_edit_mqtt_port.setReadOnly(True) self.line_edit_mqtt_username.setReadOnly(True) self.line_edit_mqtt_password.setReadOnly(True) self.button_mqtt_connect.setText("Disconnect") def unlock_mqtt_interface(self): self.line_edit_mqtt_hostname.setReadOnly(False) self.line_edit_mqtt_port.setReadOnly(False) self.line_edit_mqtt_username.setReadOnly(False) self.line_edit_mqtt_password.setReadOnly(False) self.button_mqtt_connect.setText("Connect") def button_mqtt_connect_clicked(self): if not self.state["mqtt"]["connected"]: self.state["mqtt"]["client"].username_pw_set( self.line_edit_mqtt_username.text(), self.line_edit_mqtt_password.text()) self.state["mqtt"]["client"].connect( self.line_edit_mqtt_hostname.text(), int(self.line_edit_mqtt_port.text()), 30) self.state["mqtt"]["client"].loop_start() else: self.state["mqtt"]["client"].loop_stop() self.state["mqtt"]["client"].disconnect() def create_chart_interface(self): fig = Figure(figsize=(100, 100), dpi=100) self.axes = fig.add_subplot(111) fig.axes.plot([0, 1, 2, 3, 4], [10, 1, 20, 3, 40]) self.wid self.layout_chart_interface = QGridLayout() def on_timer_internet_status(self): try: socket.create_connection(("1.1.1.1", 53)) self.state["internet"]["connected"] = True self.line_edit_internet_status.setText("Connected") self.toolbutton_internet_status.setIcon(self.icons["cloud"]) return True except OSError: pass self.state["internet"]["connected"] = False self.line_edit_internet_status.setText("Disconnected") self.toolbutton_internet_status.setIcon(self.icons["cloud-line"]) return False def mqtt_on_connect(self, client, userdata, flags, return_code): if return_code == 0: print("Connected to MQTT broker at: " + self.line_edit_mqtt_hostname.text()) self.state["mqtt"]["connected"] = True self.state["mqtt"]["hostname"] = self.line_edit_mqtt_hostname.text( ) self.state["mqtt"]["port"] = self.line_edit_mqtt_port.text() self.state["mqtt"]["username"] = self.line_edit_mqtt_username.text( ) self.toolbutton_mqtt_status.setIcon(self.icons["server"]) self.lock_mqtt_interface() else: print("Failed to connect to MQTT broker at: " + self.line_edit_mqtt_hostname.text()) def mqtt_on_disconnect(self, client, userdata, return_code): if return_code == 0: print("Disconnected from MQTT broker") else: print( "Failed to cleanly disconnect from MQTT broker, already disconnected" ) self.state["mqtt"]["connected"] = False self.state["mqtt"]["hostname"] = "" self.state["mqtt"]["port"] = "" self.state["mqtt"]["username"] = "" self.toolbutton_mqtt_status.setIcon(self.icons["server-line"]) self.unlock_mqtt_interface() def mqtt_on_subscribe(self, client, userdata, message_id, granted_qos): print("test") def mqtt_on_unsubscribe(self, client, userdata, message_id): print("test") def mqtt_on_publish(self, client, userdata, message_id): print("test") def mqtt_on_message(self, client, userdata, message): print("test") def mqtt_on_log(self, client, userdata, level, string): print(level + ", " + string) def create_icons(self): self.icons = {} icon_path = "assets/remix/icons" self.icons["cloud"] = QIcon(icon_path + "/Business/cloud-fill.svg") self.icons["cloud-line"] = QIcon(icon_path + "/Business/cloud-line.svg") self.icons["cloud-off"] = QIcon(icon_path + "/Business/cloud-off-fill.svg") self.icons["wifi"] = QIcon(icon_path + "/Device/signal-wifi-fill.svg") self.icons["wifi-line"] = QIcon(icon_path + "/Device/signal-wifi-line.svg") self.icons["server"] = QIcon(icon_path + "/Device/server-fill.svg") self.icons["server-line"] = QIcon(icon_path + "/Device/server-line.svg") self.icons["wifi-off"] = QIcon(icon_path + "/Device/signal-wifi-off-fill.svg") self.icons["radio"] = QIcon(icon_path + "/Device/wifi-fill.svg") self.icons["radio-off"] = QIcon(icon_path + "/Device/wifi-off-fill.svg") self.icons["sim-card"] = QIcon(icon_path + "/Device/sim-card-2-fill.svg") self.icons["sim-card-line"] = QIcon(icon_path + "/Device/sim-card-2-line.svg") self.icons["takeoff"] = QIcon(icon_path + "/Map/flight-takeoff-fill.svg") self.icons["land"] = QIcon(icon_path + "/Map/flight-land-fill.svg") self.icons["heart"] = QIcon(icon_path + "/Health/heart-3-fill.svg") self.icons["heart-line"] = QIcon(icon_path + "/Health/heart-3-line.svg") self.icons["heart-off"] = QIcon(icon_path + "/Health/dislike-fill.svg") self.icons["heart-pulse"] = QIcon(icon_path + "/Health/heart-pulse-fill.svg")