#!/usr/bin/python3 """ Tasmotonov GUI - A simple Qt wrapper around the tasmotonov.py script Copyright (C) 2025 Benjamin Burkhardt This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import sys import tasmotonov import json from PySide6.QtUiTools import QUiLoader from PySide6.QtWidgets import QApplication,QFileDialog from PySide6.QtCore import QFile, QUrl, QIODevice # set some standard values filename = "" action = "toggle" def load_config(file="tasmotonov-gui-config.json"): # load config from configparser.ConfigParser object try: with open(file, "r") as f: to_load = json.loads(f.read()) global filename, action if "file" in to_load: filename = to_load['file'] if filename != "": try: tab1_load_file() except FileNotFoundError: tab1_clear() if "inline" in to_load: window.tab2_plainTextEdit.setPlainText(to_load['inline']) if "action" in to_load: a_new = to_load['action'] if a_new != "": action = a_new if "tab_index" in to_load: tab_index = to_load["tab_index"] if type(tab_index) == int and (0 <= tab_index < window.tabWidget.count()): window.tabWidget.setCurrentIndex(to_load["tab_index"]) except FileNotFoundError: pass # no config there yet def save_config(file="tasmotonov-gui-config.json"): window.tab3_textBrowser.append("Saving configuration!") global filename, action to_save = {} to_save['file'] = str(filename) to_save['inline'] = str(window.tab2_plainTextEdit.toPlainText()) to_save['action'] = str(action) to_save['tab_index'] = window.tabWidget.currentIndex() with open(file, 'w') as f: f.write(json.dumps(to_save)) # tab1 slots def tab1_load_file_pressed(): global filename dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) if dialog.exec(): filename = dialog.selectedFiles()[0] tab1_load_file() def tab1_load_file(): global filename window.tab1_label.setText(f"File loaded: {filename}") window.tab3_textBrowser.append(f"File loaded: {filename}") window.tab1_label.show() window.tab1_filecontent_textBrowser.setSource(QUrl(filename)) window.tab1_label_help.show() # clear listWidget and add the items window.tab1_listWidget.clear() addresses = tasmotonov.TasmotonovRunner("file", filename, action, False, False).get_addresses() items_to_add = [] for address, comment in addresses.items(): if comment == "": items_to_add.append(address) else: items_to_add.append(f"{comment} [{address}]") window.tab1_listWidget.addItems(items_to_add) def tab1_clear(): global filename filename = "" window.tab1_label.setText(f"File loaded: ") window.tab3_textBrowser.append(f"File unloaded") window.tab1_label.hide() window.tab1_label_help.hide() window.tab1_filecontent_textBrowser.clear() window.tab1_listWidget.clear() def tab1_action(): if filename != "": tasmotonov_runner = tasmotonov.TasmotonovRunner("file", filename, action, False, False) tasmotonov_runner.run() window.tab3_textBrowser.append("\n==== RUNNING ====\n\n" + str(tasmotonov_runner.logger.log_string) + "\n=================\n") tasmotonov_runner.logger.log_string = "" else: window.tab3_textBrowser.append("Will not run, no file selected!") def tab1_single_action(): if filename != "": tasmotonov_runner = tasmotonov.TasmotonovRunner("file", filename, action, False, False) tasmotonov_runner.run_single(window.tab1_listWidget.currentRow()) window.tab3_textBrowser.append(str(tasmotonov_runner.logger.log_string)) # tab2 slots def tab2_plainTextEdit_change(): # clear listWidget window.tab2_listWidget.clear() content = window.tab2_plainTextEdit.toPlainText() if content != "": tasmotonov_runner = tasmotonov.TasmotonovRunner("inline", content, action, False, False) addresses = tasmotonov_runner.get_addresses() items_to_add = [] for address, comment in addresses.items(): if comment == "": items_to_add.append(address) else: items_to_add.append(f"{comment} [{address}]") window.tab2_listWidget.addItems(items_to_add) window.tab3_textBrowser.append(str(tasmotonov_runner.logger.log_string)) def tab2_action(): content = window.tab2_plainTextEdit.toPlainText() if content != "": tasmotonov_runner = tasmotonov.TasmotonovRunner("inline", content, action, False, False) tasmotonov_runner.run() window.tab3_textBrowser.append("\n==== RUNNING ====\n\n" + str(tasmotonov_runner.logger.log_string) + "\n=================\n") else: window.tab3_textBrowser.append("Will not run, no input given!") def tab2_single_action(): content = window.tab2_plainTextEdit.toPlainText() tasmotonov_runner = tasmotonov.TasmotonovRunner("inline", content, action, False, False) if len(tasmotonov_runner.get_addresses()) != 0: tasmotonov_runner.run_single(window.tab2_listWidget.currentRow()) window.tab3_textBrowser.append(str(tasmotonov_runner.logger.log_string)) # tab3 slots def tab3_clear(): window.tab3_textBrowser.clear() # other slots def select_on(): global action action = "on" window.tab3_textBrowser.append("Now turning everything on when running.") def select_off(): global action action = "off" window.tab3_textBrowser.append("Now turning everything off when running.") def select_toggle(): global action action = "toggle" window.tab3_textBrowser.append("Now toggling when running.") if __name__ == "__main__": app = QApplication(sys.argv) ui_file_name = "tasmotonov-gui.ui" ui_file = QFile(ui_file_name) if not ui_file.open(QIODevice.ReadOnly): print(f"Cannot open {ui_file_name}: {ui_file.errorString()}") sys.exit(-1) loader = QUiLoader() window = loader.load(ui_file) ui_file.close() if not window: print(loader.errorString()) sys.exit(-1) window.tab1_label.hide() window.tab1_label_help.hide() window.tab1_load_file_pushButton.clicked.connect(tab1_load_file_pressed) window.tab1_clear_pushButton.clicked.connect(tab1_clear) window.tab1_action_pushButton.clicked.connect(tab1_action) window.tab1_single_action_pushButton.clicked.connect(tab1_single_action) window.tab2_plainTextEdit.textChanged.connect(tab2_plainTextEdit_change) window.tab2_action_pushButton.clicked.connect(tab2_action) window.tab2_single_action_pushButton.clicked.connect(tab2_single_action) window.radioButton_on.clicked.connect(select_on) window.radioButton_off.clicked.connect(select_off) window.radioButton_toggle.clicked.connect(select_toggle) window.tab3_clear_button.clicked.connect(tab3_clear) load_config() window.show() # execute app loop and define exit strategy code = app.exec() save_config() sys.exit(code)