diff --git a/pythermostat/pythermostat/gui/view/connection_details_menu.py b/pythermostat/pythermostat/gui/view/connection_details_menu.py deleted file mode 100644 index 7bef471..0000000 --- a/pythermostat/pythermostat/gui/view/connection_details_menu.py +++ /dev/null @@ -1,73 +0,0 @@ -from PyQt6 import QtWidgets, QtCore -from PyQt6.QtCore import pyqtSlot -from pythermostat.gui.model.thermostat import ThermostatConnectionState - - -class ConnectionDetailsMenu(QtWidgets.QMenu): - def __init__(self, thermostat, connect_btn): - super().__init__() - self._thermostat = thermostat - self._connect_btn = connect_btn - self._thermostat.connection_state_update.connect( - self.thermostat_state_change_handler - ) - - self.setTitle("Connection Settings") - - self.host_set_line = QtWidgets.QLineEdit() - self.host_set_line.setMinimumSize(QtCore.QSize(160, 0)) - self.host_set_line.setMaximumSize(QtCore.QSize(160, 16777215)) - self.host_set_line.setMaxLength(15) - self.host_set_line.setClearButtonEnabled(True) - - def connect_on_enter_press(): - self._connect_btn.click() - self.hide() - - self.host_set_line.returnPressed.connect(connect_on_enter_press) - - self.host_set_line.setText("192.168.1.26") - self.host_set_line.setPlaceholderText("IP for the Thermostat") - - host = QtWidgets.QWidgetAction(self) - host.setDefaultWidget(self.host_set_line) - self.addAction(host) - self.host = host - - self.port_set_spin = QtWidgets.QSpinBox() - self.port_set_spin.setMinimumSize(QtCore.QSize(70, 0)) - self.port_set_spin.setMaximumSize(QtCore.QSize(70, 16777215)) - self.port_set_spin.setMaximum(65535) - self.port_set_spin.setValue(23) - - def connect_only_if_enter_pressed(): - if ( - not self.port_set_spin.hasFocus() - ): # Don't connect if the spinbox only lost focus - return - connect_on_enter_press() - - self.port_set_spin.editingFinished.connect(connect_only_if_enter_pressed) - - port = QtWidgets.QWidgetAction(self) - port.setDefaultWidget(self.port_set_spin) - self.addAction(port) - self.port = port - - self.exit_button = QtWidgets.QPushButton() - self.exit_button.setText("Exit GUI") - self.exit_button.pressed.connect(QtWidgets.QApplication.instance().quit) - - exit_action = QtWidgets.QWidgetAction(self.exit_button) - exit_action.setDefaultWidget(self.exit_button) - self.addAction(exit_action) - self.exit_action = exit_action - - @pyqtSlot(ThermostatConnectionState) - def thermostat_state_change_handler(self, state): - self.host_set_line.setEnabled( - state == ThermostatConnectionState.DISCONNECTED - ) - self.port_set_spin.setEnabled( - state == ThermostatConnectionState.DISCONNECTED - ) diff --git a/pythermostat/pythermostat/gui/view/menus.py b/pythermostat/pythermostat/gui/view/menus.py new file mode 100644 index 0000000..8476e03 --- /dev/null +++ b/pythermostat/pythermostat/gui/view/menus.py @@ -0,0 +1,310 @@ +import logging +from PyQt6 import QtWidgets, QtCore, QtGui +from PyQt6.QtCore import pyqtSignal, pyqtSlot, QSignalBlocker +from qasync import asyncSlot +from pythermostat.gui.model.thermostat import ThermostatConnectionState +from pythermostat.gui.view.net_settings_input_diag import NetSettingsInputDiag +from pythermostat.gui.model.thermostat import ThermostatConnectionState + + +class ConnectionDetailsMenu(QtWidgets.QMenu): + def __init__(self, thermostat, connect_btn): + super().__init__() + self._thermostat = thermostat + self._connect_btn = connect_btn + self._thermostat.connection_state_update.connect( + self.thermostat_state_change_handler + ) + + self.setTitle("Connection Settings") + + self.host_set_line = QtWidgets.QLineEdit() + self.host_set_line.setMinimumSize(QtCore.QSize(160, 0)) + self.host_set_line.setMaximumSize(QtCore.QSize(160, 16777215)) + self.host_set_line.setMaxLength(15) + self.host_set_line.setClearButtonEnabled(True) + + def connect_on_enter_press(): + self._connect_btn.click() + self.hide() + + self.host_set_line.returnPressed.connect(connect_on_enter_press) + + self.host_set_line.setText("192.168.1.26") + self.host_set_line.setPlaceholderText("IP for the Thermostat") + + host = QtWidgets.QWidgetAction(self) + host.setDefaultWidget(self.host_set_line) + self.addAction(host) + self.host = host + + self.port_set_spin = QtWidgets.QSpinBox() + self.port_set_spin.setMinimumSize(QtCore.QSize(70, 0)) + self.port_set_spin.setMaximumSize(QtCore.QSize(70, 16777215)) + self.port_set_spin.setMaximum(65535) + self.port_set_spin.setValue(23) + + def connect_only_if_enter_pressed(): + if ( + not self.port_set_spin.hasFocus() + ): # Don't connect if the spinbox only lost focus + return + connect_on_enter_press() + + self.port_set_spin.editingFinished.connect(connect_only_if_enter_pressed) + + port = QtWidgets.QWidgetAction(self) + port.setDefaultWidget(self.port_set_spin) + self.addAction(port) + self.port = port + + self.exit_button = QtWidgets.QPushButton() + self.exit_button.setText("Exit GUI") + self.exit_button.pressed.connect(QtWidgets.QApplication.instance().quit) + + exit_action = QtWidgets.QWidgetAction(self.exit_button) + exit_action.setDefaultWidget(self.exit_button) + self.addAction(exit_action) + self.exit_action = exit_action + + @pyqtSlot(ThermostatConnectionState) + def thermostat_state_change_handler(self, state): + self.host_set_line.setEnabled( + state == ThermostatConnectionState.DISCONNECTED + ) + self.port_set_spin.setEnabled( + state == ThermostatConnectionState.DISCONNECTED + ) + + +class PlotOptionsMenu(QtWidgets.QMenu): + def __init__(self, channel_graphs, max_samples=1000): + super().__init__() + self.channel_graphs = channel_graphs + + self.setTitle("Plot Settings") + + clear = QtGui.QAction("Clear graphs", self) + self.addAction(clear) + self.clear = clear + self.clear.triggered.connect(self.channel_graphs.clear_graphs) + + self.samples_spinbox = QtWidgets.QSpinBox() + self.samples_spinbox.setRange(2, 100000) + self.samples_spinbox.setSuffix(" samples") + self.samples_spinbox.setValue(max_samples) + self.samples_spinbox.valueChanged.connect(self.channel_graphs.set_max_samples) + + limit_samples = QtWidgets.QWidgetAction(self) + limit_samples.setDefaultWidget(self.samples_spinbox) + self.addAction(limit_samples) + self.limit_samples = limit_samples + + +class ThermostatSettingsMenu(QtWidgets.QMenu): + def __init__(self, thermostat, info_box, style): + super().__init__() + self._thermostat = thermostat + self._info_box = info_box + self._style = style + self.setTitle("Thermostat settings") + + self.hw_rev_data = dict() + self._thermostat.hw_rev_update.connect(self.hw_rev) + self._thermostat.connection_state_update.connect( + self.thermostat_state_change_handler + ) + + self.fan_group = QtWidgets.QWidget() + self.fan_group.setEnabled(False) + self.fan_group.setMinimumSize(QtCore.QSize(40, 0)) + self.fan_layout = QtWidgets.QHBoxLayout(self.fan_group) + self.fan_layout.setSpacing(9) + self.fan_lbl = QtWidgets.QLabel(parent=self.fan_group) + self.fan_lbl.setMinimumSize(QtCore.QSize(40, 0)) + self.fan_lbl.setMaximumSize(QtCore.QSize(40, 16777215)) + self.fan_lbl.setBaseSize(QtCore.QSize(40, 0)) + self.fan_layout.addWidget(self.fan_lbl) + self.fan_power_slider = QtWidgets.QSlider(parent=self.fan_group) + self.fan_power_slider.setMinimumSize(QtCore.QSize(200, 0)) + self.fan_power_slider.setMaximumSize(QtCore.QSize(200, 16777215)) + self.fan_power_slider.setBaseSize(QtCore.QSize(200, 0)) + self.fan_power_slider.setRange(1, 100) + self.fan_power_slider.setOrientation(QtCore.Qt.Orientation.Horizontal) + self.fan_layout.addWidget(self.fan_power_slider) + self.fan_auto_box = QtWidgets.QCheckBox(parent=self.fan_group) + self.fan_auto_box.setMinimumSize(QtCore.QSize(70, 0)) + self.fan_auto_box.setMaximumSize(QtCore.QSize(70, 16777215)) + self.fan_layout.addWidget(self.fan_auto_box) + self.fan_pwm_warning = QtWidgets.QLabel(parent=self.fan_group) + self.fan_pwm_warning.setMinimumSize(QtCore.QSize(16, 0)) + self.fan_layout.addWidget(self.fan_pwm_warning) + + self.fan_power_slider.valueChanged.connect(self.fan_set_request) + self.fan_auto_box.stateChanged.connect(self.fan_auto_set_request) + self._thermostat.fan_update.connect(self.fan_update) + + self.fan_lbl.setToolTip("Adjust the fan") + self.fan_lbl.setText("Fan:") + self.fan_auto_box.setText("Auto") + + fan = QtWidgets.QWidgetAction(self) + fan.setDefaultWidget(self.fan_group) + self.addAction(fan) + self.fan = fan + + self.actionReset = QtGui.QAction("Reset Thermostat", self) + self.actionReset.triggered.connect(self.reset_request) + self.addAction(self.actionReset) + + self.actionEnter_DFU_Mode = QtGui.QAction("Enter DFU Mode", self) + self.actionEnter_DFU_Mode.triggered.connect(self.dfu_request) + self.addAction(self.actionEnter_DFU_Mode) + + self.actionnet_settings_input_diag = QtGui.QAction("Set IPV4 Settings", self) + self.actionnet_settings_input_diag.triggered.connect(self.net_settings_request) + self.addAction(self.actionnet_settings_input_diag) + + @asyncSlot(bool) + async def load(_): + await self._thermostat.load_cfg() + + self._info_box.display_info_box( + "Config loaded", "All channel configs have been loaded from flash." + ) + + self.actionLoad_all_configs = QtGui.QAction("Load Config", self) + self.actionLoad_all_configs.triggered.connect(load) + self.addAction(self.actionLoad_all_configs) + + @asyncSlot(bool) + async def save(_): + await self._thermostat.save_cfg() + + self._info_box.display_info_box( + "Config saved", "All channel configs have been saved to flash." + ) + + self.actionSave_all_configs = QtGui.QAction("Save Config", self) + self.actionSave_all_configs.triggered.connect(save) + self.addAction(self.actionSave_all_configs) + + def about_thermostat(): + QtWidgets.QMessageBox.about( + self, + "About Thermostat", + f""" +