def createUI(self): vl = VLayout() self.setLayout(vl) # Port groupbox gbPort = GroupBoxH("Select port", 3) self.cbxPort = QComboBox() pbRefreshPorts = QPushButton("Refresh") gbPort.addWidget(self.cbxPort) gbPort.addWidget(pbRefreshPorts) gbPort.layout().setStretch(0, 4) gbPort.layout().setStretch(1, 1) # Firmware groupbox gbFW = GroupBoxV("Select image", 3) self.wFile = QWidget() hl_file = HLayout(0) self.file = QLineEdit() self.file.setReadOnly(True) self.file.setText(self.bin_file) pbFile = QPushButton("Open") hl_file.addWidgets([self.file, pbFile]) self.wFile.setLayout(hl_file) gbFW.addWidgets([self.wFile]) # Buttons self.pbFlash = QPushButton("Flash!") self.pbFlash.setFixedHeight(50) self.pbFlash.setStyleSheet("background-color: #223579;") self.pbConfig = QPushButton("Setup WIFI") self.pbConfig.setStyleSheet("background-color: #571054;") self.pbConfig.setFixedHeight(50) self.pbQuit = QPushButton("Quit") self.pbQuit.setStyleSheet("background-color: #c91017;") self.pbQuit.setFixedSize(QSize(50, 50)) hl_btns = HLayout([50, 3, 50, 3]) hl_btns.addWidgets([self.pbFlash, self.pbConfig, self.pbQuit]) vl.addWidgets([gbPort, gbFW]) vl.addLayout(hl_btns) pbRefreshPorts.clicked.connect(self.refreshPorts) pbFile.clicked.connect(self.openBinFile) self.pbFlash.clicked.connect(self.start_process) self.pbConfig.clicked.connect(self.send_config) self.pbQuit.clicked.connect(self.reject)
def createUI(self): vl = VLayout() self.setLayout(vl) # Banner banner = QLabel() banner.setPixmap(QPixmap(":/banner.png")) vl.addWidget(banner) # Port groupbox gbPort = GroupBoxH("Select port", 3) self.cbxPort = QComboBox() pbRefreshPorts = QPushButton("Refresh") gbPort.addWidget(self.cbxPort) gbPort.addWidget(pbRefreshPorts) gbPort.layout().setStretch(0, 4) gbPort.layout().setStretch(1, 1) # Firmware groupbox gbFW = GroupBoxV("Select image", 3) hl_rb = HLayout(0) rbFile = QRadioButton("BIN file") self.rbRelease = QRadioButton("Release") self.rbRelease.setEnabled(False) self.rbDev = QRadioButton("Development") self.rbDev.setEnabled(False) rbgFW = QButtonGroup(gbFW) rbgFW.addButton(rbFile, 0) rbgFW.addButton(self.rbRelease, 1) rbgFW.addButton(self.rbDev, 2) hl_rb.addWidgets([rbFile, self.rbRelease, self.rbDev]) gbFW.addLayout(hl_rb) self.wFile = QWidget() hl_file = HLayout(0) self.file = QLineEdit() self.file.setReadOnly(True) self.file.setPlaceholderText("Click 'Open' to select the image") pbFile = QPushButton("Open") hl_file.addWidgets([self.file, pbFile]) self.wFile.setLayout(hl_file) self.cbHackboxBin = QComboBox() self.cbHackboxBin.setVisible(False) self.cbHackboxBin.setEnabled(False) self.cbBackup = QCheckBox("Backup original firmware") self.cbBackup.setToolTip( "Firmware backup is ESPECIALLY recommended when you flash a Sonoff, Tuya, Shelly etc. for the first time.\nWithout a backup you won't be able to restore the original functionality." ) self.cbErase = QCheckBox("Erase before flashing") self.cbErase.setToolTip( "Erasing previous firmware ensures all flash regions are clean for Tasmota, which prevents many unexpected issues.\nIf unsure, leave enabled." ) self.cbErase.setChecked(True) gbFW.addWidgets( [self.wFile, self.cbHackboxBin, self.cbBackup, self.cbErase]) # Buttons self.pbTasmotize = QPushButton("Tasmotize!") self.pbTasmotize.setFixedHeight(50) self.pbTasmotize.setStyleSheet("background-color: #223579;") self.pbConfig = QPushButton("Send config") self.pbConfig.setStyleSheet("background-color: #571054;") self.pbConfig.setFixedHeight(50) self.pbQuit = QPushButton("Quit") self.pbQuit.setStyleSheet("background-color: #c91017;") self.pbQuit.setFixedSize(QSize(50, 50)) hl_btns = HLayout([50, 3, 50, 3]) hl_btns.addWidgets([self.pbTasmotize, self.pbConfig, self.pbQuit]) vl.addWidgets([gbPort, gbFW]) vl.addLayout(hl_btns) pbRefreshPorts.clicked.connect(self.refreshPorts) rbgFW.buttonClicked[int].connect(self.setBinMode) rbFile.setChecked(True) pbFile.clicked.connect(self.openBinFile) self.pbTasmotize.clicked.connect(self.start_process) self.pbConfig.clicked.connect(self.send_config) self.pbQuit.clicked.connect(self.reject)
def createUI(self): vl = VLayout() self.setLayout(vl) # Wifi groupbox self.gbWifi = QGroupBox("WiFi") self.gbWifi.setCheckable(True) self.gbWifi.setChecked(False) flWifi = QFormLayout() self.leAP = QLineEdit() self.leAPPwd = QLineEdit() self.leAPPwd.setEchoMode(QLineEdit.Password) flWifi.addRow("SSID", self.leAP) flWifi.addRow("Password", self.leAPPwd) self.gbWifi.setLayout(flWifi) # Recovery Wifi groupbox self.gbRecWifi = QGroupBox("Recovery WiFi") self.gbRecWifi.setCheckable(True) self.gbRecWifi.setChecked(False) flRecWifi = QFormLayout() lbRecAP = QLabel("Recovery") lbRecAP.setAlignment(Qt.AlignVCenter | Qt.AlignRight) lbRecAPPwd = QLabel("a1b2c3d4") lbRecAPPwd.setAlignment(Qt.AlignVCenter | Qt.AlignRight) flRecWifi.addRow("SSID", lbRecAP) flRecWifi.addRow("Password", lbRecAPPwd) self.gbRecWifi.setLayout(flRecWifi) vl_wifis = VLayout(0) vl_wifis.addWidgets([self.gbWifi, self.gbRecWifi]) # MQTT groupbox self.gbMQTT = QGroupBox("MQTT") self.gbMQTT.setCheckable(True) self.gbMQTT.setChecked(False) flMQTT = QFormLayout() self.leBroker = QLineEdit() self.sbPort = SpinBox() self.sbPort.setValue(1883) self.leTopic = QLineEdit() self.leTopic.setText("tasmota") self.leFullTopic = QLineEdit() self.leFullTopic.setText("%prefix%/%topic%/") self.leFriendlyName = QLineEdit() self.leMQTTUser = QLineEdit() self.leMQTTPass = QLineEdit() self.leMQTTPass.setEchoMode(QLineEdit.Password) flMQTT.addRow("Host", self.leBroker) flMQTT.addRow("Port", self.sbPort) flMQTT.addRow("Topic", self.leTopic) flMQTT.addRow("FullTopic", self.leFullTopic) flMQTT.addRow("FriendlyName", self.leFriendlyName) flMQTT.addRow("User [optional]", self.leMQTTUser) flMQTT.addRow("Password [optional]", self.leMQTTPass) self.gbMQTT.setLayout(flMQTT) # Module/template groupbox self.gbModule = GroupBoxV("Module/template") self.gbModule.setCheckable(True) self.gbModule.setChecked(False) hl_m_rb = HLayout() self.rbModule = QRadioButton("Module") self.rbModule.setChecked(True) self.rbTemplate = QRadioButton("Template") hl_m_rb.addWidgets([self.rbModule, self.rbTemplate]) self.rbgModule = QButtonGroup(self.gbModule) self.rbgModule.addButton(self.rbModule, 0) self.rbgModule.addButton(self.rbTemplate, 1) self.cbModule = QComboBox() for mod_id, mod_name in modules.items(): self.cbModule.addItem(mod_name, mod_id) self.leTemplate = QLineEdit() self.leTemplate.setPlaceholderText("Paste template string here") self.leTemplate.setVisible(False) self.gbModule.addLayout(hl_m_rb) self.gbModule.addWidgets([self.cbModule, self.leTemplate]) self.rbgModule.buttonClicked[int].connect(self.setModuleMode) # layout all widgets hl_wifis_mqtt = HLayout(0) hl_wifis_mqtt.addLayout(vl_wifis) hl_wifis_mqtt.addWidget(self.gbMQTT) vl.addLayout(hl_wifis_mqtt) vl.addWidget(self.gbModule) btns = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close) btns.accepted.connect(self.accept) btns.rejected.connect(self.reject) vl.addWidget(btns)
class SendConfigDialog(QDialog): def __init__(self): super().__init__() self.setMinimumWidth(640) self.setWindowTitle("Send configuration to device") self.settings = QSettings("tasmotizer.cfg", QSettings.IniFormat) self.commands = None self.module_mode = 0 self.createUI() self.loadSettings() def createUI(self): vl = VLayout() self.setLayout(vl) # Wifi groupbox self.gbWifi = QGroupBox("WiFi") self.gbWifi.setCheckable(True) self.gbWifi.setChecked(False) flWifi = QFormLayout() self.leAP = QLineEdit() self.leAPPwd = QLineEdit() self.leAPPwd.setEchoMode(QLineEdit.Password) flWifi.addRow("SSID", self.leAP) flWifi.addRow("Password", self.leAPPwd) self.gbWifi.setLayout(flWifi) # Recovery Wifi groupbox self.gbRecWifi = QGroupBox("Recovery WiFi") self.gbRecWifi.setCheckable(True) self.gbRecWifi.setChecked(False) flRecWifi = QFormLayout() lbRecAP = QLabel("Recovery") lbRecAP.setAlignment(Qt.AlignVCenter | Qt.AlignRight) lbRecAPPwd = QLabel("a1b2c3d4") lbRecAPPwd.setAlignment(Qt.AlignVCenter | Qt.AlignRight) flRecWifi.addRow("SSID", lbRecAP) flRecWifi.addRow("Password", lbRecAPPwd) self.gbRecWifi.setLayout(flRecWifi) vl_wifis = VLayout(0) vl_wifis.addWidgets([self.gbWifi, self.gbRecWifi]) # MQTT groupbox self.gbMQTT = QGroupBox("MQTT") self.gbMQTT.setCheckable(True) self.gbMQTT.setChecked(False) flMQTT = QFormLayout() self.leBroker = QLineEdit() self.sbPort = SpinBox() self.sbPort.setValue(1883) self.leTopic = QLineEdit() self.leTopic.setText("tasmota") self.leFullTopic = QLineEdit() self.leFullTopic.setText("%prefix%/%topic%/") self.leFriendlyName = QLineEdit() self.leMQTTUser = QLineEdit() self.leMQTTPass = QLineEdit() self.leMQTTPass.setEchoMode(QLineEdit.Password) flMQTT.addRow("Host", self.leBroker) flMQTT.addRow("Port", self.sbPort) flMQTT.addRow("Topic", self.leTopic) flMQTT.addRow("FullTopic", self.leFullTopic) flMQTT.addRow("FriendlyName", self.leFriendlyName) flMQTT.addRow("User [optional]", self.leMQTTUser) flMQTT.addRow("Password [optional]", self.leMQTTPass) self.gbMQTT.setLayout(flMQTT) # Module/template groupbox self.gbModule = GroupBoxV("Module/template") self.gbModule.setCheckable(True) self.gbModule.setChecked(False) hl_m_rb = HLayout() self.rbModule = QRadioButton("Module") self.rbModule.setChecked(True) self.rbTemplate = QRadioButton("Template") hl_m_rb.addWidgets([self.rbModule, self.rbTemplate]) self.rbgModule = QButtonGroup(self.gbModule) self.rbgModule.addButton(self.rbModule, 0) self.rbgModule.addButton(self.rbTemplate, 1) self.cbModule = QComboBox() for mod_id, mod_name in modules.items(): self.cbModule.addItem(mod_name, mod_id) self.leTemplate = QLineEdit() self.leTemplate.setPlaceholderText("Paste template string here") self.leTemplate.setVisible(False) self.gbModule.addLayout(hl_m_rb) self.gbModule.addWidgets([self.cbModule, self.leTemplate]) self.rbgModule.buttonClicked[int].connect(self.setModuleMode) # layout all widgets hl_wifis_mqtt = HLayout(0) hl_wifis_mqtt.addLayout(vl_wifis) hl_wifis_mqtt.addWidget(self.gbMQTT) vl.addLayout(hl_wifis_mqtt) vl.addWidget(self.gbModule) btns = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close) btns.accepted.connect(self.accept) btns.rejected.connect(self.reject) vl.addWidget(btns) def loadSettings(self): self.gbWifi.setChecked(self.settings.value("gbWifi", False, bool)) self.leAP.setText(self.settings.value("AP")) self.gbRecWifi.setChecked(self.settings.value("gbRecWifi", False, bool)) self.gbMQTT.setChecked(self.settings.value("gbMQTT", False, bool)) self.leBroker.setText(self.settings.value("Broker")) self.sbPort.setValue(self.settings.value("Port", 1883, int)) self.leTopic.setText(self.settings.value("Topic", "tasmota")) self.leFullTopic.setText( self.settings.value("FullTopic", "%prefix%/%topic%/")) self.leFriendlyName.setText(self.settings.value("FriendlyName")) self.leMQTTUser.setText(self.settings.value("MQTTUser")) self.gbModule.setChecked(self.settings.value("gbModule", False, bool)) module_mode = self.settings.value("ModuleMode", 0, int) for b in self.rbgModule.buttons(): if self.rbgModule.id(b) == module_mode: b.setChecked(True) self.setModuleMode(module_mode) self.cbModule.setCurrentText(self.settings.value("Module", "Generic")) self.leTemplate.setText(self.settings.value("Template")) def setModuleMode(self, radio): self.module_mode = radio self.cbModule.setVisible(not radio) self.leTemplate.setVisible(radio) def accept(self): ok = True if self.gbWifi.isChecked() and (len(self.leAP.text()) == 0 or len(self.leAPPwd.text()) == 0): ok = False QMessageBox.warning(self, "WiFi details incomplete", "Input WiFi AP and Password") if self.gbMQTT.isChecked() and not self.leBroker.text(): ok = False QMessageBox.warning(self, "MQTT details incomplete", "Input broker hostname") if self.module_mode == 1 and len(self.leTemplate.text()) == 0: ok = False QMessageBox.warning(self, "Template string missing", "Input template string") if ok: backlog = [] if self.gbWifi.isChecked(): backlog.extend([ "ssid1 {}".format(self.leAP.text()), "password1 {}".format(self.leAPPwd.text()) ]) if self.gbRecWifi.isChecked(): backlog.extend(["ssid2 Recovery", "password2 a1b2c3d4"]) if self.gbMQTT.isChecked(): backlog.extend([ "mqtthost {}".format(self.leBroker.text()), "mqttport {}".format(self.sbPort.value()) ]) topic = self.leTopic.text() if topic and topic != "tasmota": backlog.append("topic {}".format(topic)) fulltopic = self.leFullTopic.text() if fulltopic and fulltopic != "%prefix%/%topic%/": backlog.append("fulltopic {}".format(fulltopic)) fname = self.leFriendlyName.text() if fname: backlog.append("friendlyname {}".format(fname)) mqttuser = self.leMQTTUser.text() if mqttuser: backlog.append("mqttuser {}".format(mqttuser)) mqttpassword = self.leMQTTPass.text() if mqttpassword: backlog.append("mqttpassword {}".format(mqttpassword)) if self.gbModule.isChecked(): if self.module_mode == 0: backlog.append("module {}".format( self.cbModule.currentData())) elif self.module_mode == 1: backlog.extend([ "template {}".format(self.leTemplate.text()), "module 0" ]) self.commands = "backlog {}\n".format(";".join(backlog)) self.done(QDialog.Accepted)
class SendConfigDialog(QDialog): def __init__(self): super().__init__() self.setMinimumWidth(640) self.setWindowTitle('Send configuration to device') self.settings = QSettings('tasmotizer.cfg', QSettings.IniFormat) self.commands = None self.module_mode = 0 self.createUI() self.loadSettings() def createUI(self): vl = VLayout() self.setLayout(vl) # Wifi groupbox self.gbWifi = QGroupBox('WiFi') self.gbWifi.setCheckable(True) self.gbWifi.setChecked(False) flWifi = QFormLayout() self.leAP = QLineEdit() self.leAPPwd = QLineEdit() self.leAPPwd.setEchoMode(QLineEdit.Password) flWifi.addRow('SSID', self.leAP) flWifi.addRow('Password', self.leAPPwd) self.gbWifi.setLayout(flWifi) # Recovery Wifi groupbox self.gbRecWifi = QGroupBox('Recovery WiFi') self.gbRecWifi.setCheckable(True) self.gbRecWifi.setChecked(False) flRecWifi = QFormLayout() lbRecAP = QLabel('Recovery') lbRecAP.setAlignment(Qt.AlignVCenter | Qt.AlignRight) lbRecAPPwd = QLabel('a1b2c3d4') lbRecAPPwd.setAlignment(Qt.AlignVCenter | Qt.AlignRight) flRecWifi.addRow('SSID', lbRecAP) flRecWifi.addRow('Password', lbRecAPPwd) self.gbRecWifi.setLayout(flRecWifi) vl_wifis = VLayout(0) vl_wifis.addWidgets([self.gbWifi, self.gbRecWifi]) # MQTT groupbox self.gbMQTT = QGroupBox('MQTT') self.gbMQTT.setCheckable(True) self.gbMQTT.setChecked(False) flMQTT = QFormLayout() self.leBroker = QLineEdit() self.sbPort = SpinBox() self.sbPort.setValue(1883) self.leTopic = QLineEdit() self.leTopic.setText('tasmota') self.leFullTopic = QLineEdit() self.leFullTopic.setText('%prefix%/%topic%/') self.leFriendlyName = QLineEdit() self.leMQTTUser = QLineEdit() self.leMQTTPass = QLineEdit() self.leMQTTPass.setEchoMode(QLineEdit.Password) flMQTT.addRow('Host', self.leBroker) flMQTT.addRow('Port', self.sbPort) flMQTT.addRow('Topic', self.leTopic) flMQTT.addRow('FullTopic', self.leFullTopic) flMQTT.addRow('FriendlyName', self.leFriendlyName) flMQTT.addRow('User [optional]', self.leMQTTUser) flMQTT.addRow('Password [optional]', self.leMQTTPass) self.gbMQTT.setLayout(flMQTT) # Module/template groupbox self.gbModule = GroupBoxV('Module/template') self.gbModule.setCheckable(True) self.gbModule.setChecked(False) hl_m_rb = HLayout() self.rbModule = QRadioButton('Module') self.rbModule.setChecked(True) self.rbTemplate = QRadioButton('Template') hl_m_rb.addWidgets([self.rbModule, self.rbTemplate]) self.rbgModule = QButtonGroup(self.gbModule) self.rbgModule.addButton(self.rbModule, 0) self.rbgModule.addButton(self.rbTemplate, 1) self.cbModule = QComboBox() for mod_id, mod_name in MODULES.items(): self.cbModule.addItem(mod_name, mod_id) self.leTemplate = QLineEdit() self.leTemplate.setPlaceholderText('Paste template string here') self.leTemplate.setVisible(False) self.gbModule.addLayout(hl_m_rb) self.gbModule.addWidgets([self.cbModule, self.leTemplate]) self.rbgModule.buttonClicked[int].connect(self.setModuleMode) # layout all widgets hl_wifis_mqtt = HLayout(0) hl_wifis_mqtt.addLayout(vl_wifis) hl_wifis_mqtt.addWidget(self.gbMQTT) vl.addLayout(hl_wifis_mqtt) vl.addWidget(self.gbModule) btns = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close) btns.accepted.connect(self.accept) btns.rejected.connect(self.reject) vl.addWidget(btns) def loadSettings(self): self.gbWifi.setChecked(self.settings.value('gbWifi', False, bool)) self.leAP.setText(self.settings.value('AP')) self.gbRecWifi.setChecked(self.settings.value('gbRecWifi', False, bool)) self.gbMQTT.setChecked(self.settings.value('gbMQTT', False, bool)) self.leBroker.setText(self.settings.value('Broker')) self.sbPort.setValue(self.settings.value('Port', 1883, int)) self.leTopic.setText(self.settings.value('Topic', 'tasmota')) self.leFullTopic.setText( self.settings.value('FullTopic', '%prefix%/%topic%/')) self.leFriendlyName.setText(self.settings.value('FriendlyName')) self.leMQTTUser.setText(self.settings.value('MQTTUser')) self.gbModule.setChecked(self.settings.value('gbModule', False, bool)) module_mode = self.settings.value('ModuleMode', 0, int) for b in self.rbgModule.buttons(): if self.rbgModule.id(b) == module_mode: b.setChecked(True) self.setModuleMode(module_mode) self.cbModule.setCurrentText(self.settings.value('Module', 'Generic')) self.leTemplate.setText(self.settings.value('Template')) def setModuleMode(self, radio): self.module_mode = radio self.cbModule.setVisible(not radio) self.leTemplate.setVisible(radio) def accept(self): ok = True if self.gbWifi.isChecked() and (len(self.leAP.text()) == 0 or len(self.leAPPwd.text()) == 0): ok = False QMessageBox.warning(self, 'WiFi details incomplete', 'Input WiFi AP and Password') if self.gbMQTT.isChecked() and not self.leBroker.text(): ok = False QMessageBox.warning(self, 'MQTT details incomplete', 'Input broker hostname') if self.module_mode == 1 and len(self.leTemplate.text()) == 0: ok = False QMessageBox.warning(self, 'Template string missing', 'Input template string') if ok: backlog = [] if self.gbWifi.isChecked(): backlog.extend([ 'ssid1 {}'.format(self.leAP.text()), 'password1 {}'.format(self.leAPPwd.text()) ]) if self.gbRecWifi.isChecked(): backlog.extend(['ssid2 Recovery', 'password2 a1b2c3d4']) if self.gbMQTT.isChecked(): backlog.extend([ 'mqtthost {}'.format(self.leBroker.text()), 'mqttport {}'.format(self.sbPort.value()) ]) topic = self.leTopic.text() if topic and topic != 'tasmota': backlog.append('topic {}'.format(topic)) fulltopic = self.leFullTopic.text() if fulltopic and fulltopic != '%prefix%/%topic%/': backlog.append('fulltopic {}'.format(fulltopic)) fname = self.leFriendlyName.text() if fname: backlog.append('friendlyname {}'.format(fname)) mqttuser = self.leMQTTUser.text() if mqttuser: backlog.append('mqttuser {}'.format(mqttuser)) mqttpassword = self.leMQTTPass.text() if mqttpassword: backlog.append('mqttpassword {}'.format(mqttpassword)) if self.gbModule.isChecked(): if self.module_mode == 0: backlog.append('module {}'.format( self.cbModule.currentData())) elif self.module_mode == 1: backlog.extend([ 'template {}'.format(self.leTemplate.text()), 'module 0' ]) self.commands = 'backlog {}\n'.format(';'.join(backlog)) self.done(QDialog.Accepted)
def create_ui(self): vl = VLayout(5) self.setLayout(vl) # Banner banner = QLabel() banner.setPixmap(QPixmap(':/banner.png')) vl.addWidget(banner) # Port groupbox gbPort = GroupBoxH('Select port', 3) self.cbxPort = QComboBox() pbRefreshPorts = QPushButton('Refresh') gbPort.addWidget(self.cbxPort) gbPort.addWidget(pbRefreshPorts) gbPort.layout().setStretch(0, 4) gbPort.layout().setStretch(1, 1) # Firmware groupbox gbFW = GroupBoxV('Select image', 3) hl_rb = HLayout(0) rbFile = QRadioButton('BIN file') self.rbRelease = QRadioButton('Release') self.rbRelease.setEnabled(False) self.rbDev = QRadioButton('Development') self.rbDev.setEnabled(False) self.rbgFW = QButtonGroup(gbFW) self.rbgFW.addButton(rbFile, 0) self.rbgFW.addButton(self.rbRelease, 1) self.rbgFW.addButton(self.rbDev, 2) hl_rb.addWidgets([rbFile, self.rbRelease, self.rbDev]) gbFW.addLayout(hl_rb) self.wFile = QWidget() hl_file = HLayout(0) self.file = QLineEdit() self.file.setReadOnly(True) self.file.setPlaceholderText('Click "Open" to select the image') pbFile = QPushButton('Open') hl_file.addWidgets([self.file, pbFile]) self.wFile.setLayout(hl_file) self.cbHackboxBin = QComboBox() self.cbHackboxBin.setVisible(False) self.cbHackboxBin.setEnabled(False) self.cbSelfReset = QCheckBox('Self-resetting device (NodeMCU, Wemos)') self.cbSelfReset.setToolTip( 'Check if your device has self-resetting capabilities supported by esptool' ) gbBackup = GroupBoxV('Backup') self.cbBackup = QCheckBox('Save original firmware') self.cbBackup.setToolTip( 'Firmware backup is ESPECIALLY recommended when you flash a Sonoff, Tuya, Shelly etc. for the first time.\nWithout a backup you will not be able to restore the original functionality.' ) self.cbxBackupSize = QComboBox() self.cbxBackupSize.addItems([f'{2 ** s}MB' for s in range(5)]) self.cbxBackupSize.setEnabled(False) hl_backup_size = HLayout(0) hl_backup_size.addWidgets([QLabel('Flash size:'), self.cbxBackupSize]) hl_backup_size.setStretch(0, 3) hl_backup_size.setStretch(1, 1) gbBackup.addWidget(self.cbBackup) gbBackup.addLayout(hl_backup_size) self.cbErase = QCheckBox('Erase before flashing') self.cbErase.setToolTip( 'Erasing previous firmware ensures all flash regions are clean for Tasmota, which prevents many unexpected issues.\nIf unsure, leave enabled.' ) self.cbErase.setChecked(True) gbFW.addWidgets( [self.wFile, self.cbHackboxBin, self.cbSelfReset, self.cbErase]) # Buttons self.pbTasmotize = QPushButton('Upload tinyGS firmware!') self.pbTasmotize.setFixedHeight(50) self.pbTasmotize.setStyleSheet('background-color: #223579;') self.pbConfig = QPushButton('Send config') self.pbConfig.setStyleSheet('background-color: #571054;') self.pbConfig.setFixedHeight(50) self.pbGetIP = QPushButton('Get IP') self.pbGetIP.setFixedSize(QSize(75, 50)) self.pbGetIP.setStyleSheet('background-color: #2a8a26;') self.pbQuit = QPushButton('Quit') self.pbQuit.setStyleSheet('background-color: #c91017;') self.pbQuit.setFixedSize(QSize(50, 50)) hl_btns = HLayout([50, 3, 50, 3]) hl_btns.addWidgets([self.pbTasmotize]) vl.addWidgets([gbPort]) vl.addLayout(hl_btns) pbRefreshPorts.clicked.connect(self.refreshPorts) self.rbgFW.buttonClicked[int].connect(self.setBinMode) rbFile.setChecked(True) pbFile.clicked.connect(self.openBinFile) self.cbBackup.toggled.connect(self.cbxBackupSize.setEnabled) self.pbTasmotize.clicked.connect(self.start_process) self.pbConfig.clicked.connect(self.send_config) self.pbGetIP.clicked.connect(self.get_ip) self.pbQuit.clicked.connect(self.reject)