Compare commits

...

11 Commits

Author SHA1 Message Date
linuswck 93d6df5e92 Merge pull request 'GUI: Some repo organisation' (#1) from gui_dev-repo_org into gui_dev
Reviewed-on: #1
2024-07-12 10:34:23 +08:00
atse 44bea87f03 Thermostat.disconnect -> Thermostat.end_session
QObject already has a disconnect method, avoid overriding it.
2024-07-10 15:56:43 +08:00
atse e6f62e9e19 flake: sha256 -> hash 2024-07-10 15:56:43 +08:00
atse 271fe449ba Remove duplicated show call
MainWindow.show() already called in coro_main
2024-07-10 15:56:43 +08:00
atse 70db0a39eb Remove duplicated antialias config option
Already set in live_plot_view.py
2024-07-10 15:56:43 +08:00
atse 26c7382b1e Move GUI components and examples into folder
For better organisation
2024-07-10 15:56:43 +08:00
atse c415d9de8a Use MANIFEST.in
Allows for more accurate control over included files in pytec package
2024-07-10 15:56:43 +08:00
atse 7069111e21 Expose frontend scripts exclusively in pytec 2024-07-10 15:56:43 +08:00
atse 1707728c3c thermostat_data_model.py -> thermostat.py 2024-07-10 15:56:34 +08:00
atse a16d2e9a9e Follow CapWords convention for class names
Re: PEP8
2024-07-10 15:45:03 +08:00
atse bc4ac43e0b Put comments in right place 2024-07-10 13:07:31 +08:00
22 changed files with 45 additions and 48 deletions

View File

@ -62,7 +62,7 @@
format = "pyproject"; format = "pyproject";
src = pkgs.fetchPypi { src = pkgs.fetchPypi {
inherit pname version; inherit pname version;
sha256 = "sha256-jcdo/R7l3hBEx8MF7M8tOdJNh4A+pxGJ1AJPtHX0mF8="; hash = "sha256-jcdo/R7l3hBEx8MF7M8tOdJNh4A+pxGJ1AJPtHX0mF8=";
}; };
buildInputs = [ pkgs.python3Packages.poetry-core ]; buildInputs = [ pkgs.python3Packages.poetry-core ];
propagatedBuildInputs = [ pkgs.python3Packages.pyqt6 ]; propagatedBuildInputs = [ pkgs.python3Packages.pyqt6 ];
@ -74,7 +74,7 @@
format = "pyproject"; format = "pyproject";
src = pkgs.fetchPypi { src = pkgs.fetchPypi {
inherit pname version; inherit pname version;
sha256 = "sha256-WBCNhBHHBU4IQdi3ke6F4QH8KWubNZwOAd3jipj/Ks4="; hash = "sha256-WBCNhBHHBU4IQdi3ke6F4QH8KWubNZwOAd3jipj/Ks4=";
}; };
propagatedBuildInputs = with pkgs.python3Packages; [ numpy pyqt6 ]; propagatedBuildInputs = with pkgs.python3Packages; [ numpy pyqt6 ];
}; };
@ -85,7 +85,7 @@
format = "pyproject"; format = "pyproject";
src = pkgs.fetchPypi { src = pkgs.fetchPypi {
inherit pname version; inherit pname version;
sha256 = "sha256-jqj8X6H1N5mJQ4OrY5ANqRB0YJByqg/bNneEALWmH1A="; hash = "sha256-jqj8X6H1N5mJQ4OrY5ANqRB0YJByqg/bNneEALWmH1A=";
}; };
buildInputs = [ pkgs.python3Packages.poetry-core ]; buildInputs = [ pkgs.python3Packages.poetry-core ];
propagatedBuildInputs = [ pyqtgraph pkgs.python3Packages.numpy ]; propagatedBuildInputs = [ pyqtgraph pkgs.python3Packages.numpy ];

4
pytec/MANIFEST.in Normal file
View File

@ -0,0 +1,4 @@
graft examples
include pytec/gui/resources/artiq.ico
include pytec/gui/view/param_tree.json
include pytec/gui/view/tec_qt.ui

View File

@ -15,7 +15,4 @@ tec_qt = "tec_qt:main"
[tool.setuptools] [tool.setuptools]
packages.find = {} packages.find = {}
py-modules = ["aioexample", "autotune", "example", "plot", "tec_qt", "ui_tec_qt", "waitingspinnerwidget"] py-modules = ["autotune", "plot", "tec_qt"]
[tool.setuptools.package-data]
"*" = ["*.*"]

View File

@ -1,7 +1,7 @@
from pytec.aioclient import Client from pytec.aioclient import Client
from PyQt6.QtCore import pyqtSignal, QObject, pyqtSlot from PyQt6.QtCore import pyqtSignal, QObject, pyqtSlot
from qasync import asyncSlot from qasync import asyncSlot
from model.property import Property, PropertyMeta from pytec.gui.model.property import Property, PropertyMeta
import asyncio import asyncio
import logging import logging
@ -104,7 +104,7 @@ class Thermostat(QObject, metaclass=PropertyMeta):
self.report[i]["interval"] for i in range(len(self.report)) self.report[i]["interval"] for i in range(len(self.report))
] ]
async def disconnect(self): async def end_session(self):
await self._client.end_session() await self._client.end_session()
async def set_ipv4(self, ipv4): async def set_ipv4(self, ipv4):

View File

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

@ -1,7 +1,7 @@
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
class conn_menu(QtWidgets.QMenu): class ConnMenu(QtWidgets.QMenu):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.setTitle("Connection Settings") self.setTitle("Connection Settings")

View File

@ -42,7 +42,7 @@ class MutexParameter(pTypes.ListParameter):
registerParameterType("mutex", MutexParameter) registerParameterType("mutex", MutexParameter)
class ctrl_panel(QObject): class CtrlPanel(QObject):
set_zero_limits_warning_sig = pyqtSignal(list) set_zero_limits_warning_sig = pyqtSignal(list)
def __init__( def __init__(

View File

@ -2,7 +2,7 @@ from PyQt6 import QtWidgets
from PyQt6.QtCore import pyqtSlot from PyQt6.QtCore import pyqtSlot
class info_box(QtWidgets.QMessageBox): class InfoBox(QtWidgets.QMessageBox):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.setIcon(QtWidgets.QMessageBox.Icon.Information) self.setIcon(QtWidgets.QMessageBox.Icon.Information)

View File

@ -66,9 +66,10 @@ class _TecGraphs:
self._t_line = self._t_widget.getPlotItem().addLine(label="{value} °C") self._t_line = self._t_widget.getPlotItem().addLine(label="{value} °C")
self._t_line.setVisible(False) self._t_line.setVisible(False)
# Hack for keeping setpoint line in plot range
self._t_setpoint_plot = ( self._t_setpoint_plot = (
LiveLinePlot() LiveLinePlot()
) # Hack for keeping setpoint line in plot range )
for graph in t_widget, i_widget: for graph in t_widget, i_widget:
time_axis = LiveAxis( time_axis = LiveAxis(
@ -83,8 +84,8 @@ class _TecGraphs:
# Enable linking of axes in the graph widget's context menu # Enable linking of axes in the graph widget's context menu
graph.register( graph.register(
graph.getPlotItem().titleLabel.text graph.getPlotItem().titleLabel.text # Slight hack getting the title
) # Slight hack getting the title )
temperature_axis = LiveAxis("left", text="Temperature", units="°C") temperature_axis = LiveAxis("left", text="Temperature", units="°C")
temperature_axis.showLabel() temperature_axis.showLabel()

View File

@ -3,7 +3,7 @@ from PyQt6.QtWidgets import QAbstractButton
from PyQt6.QtCore import pyqtSignal, pyqtSlot from PyQt6.QtCore import pyqtSignal, pyqtSlot
class net_settings_input_diag(QtWidgets.QInputDialog): class NetSettingsInputDiag(QtWidgets.QInputDialog):
set_ipv4_act = pyqtSignal(str) set_ipv4_act = pyqtSignal(str)
def __init__(self, current_ipv4_settings): def __init__(self, current_ipv4_settings):

View File

@ -1,7 +1,7 @@
from PyQt6 import QtWidgets, QtGui from PyQt6 import QtWidgets, QtGui
class plot_options_menu(QtWidgets.QMenu): class PlotOptionsMenu(QtWidgets.QMenu):
def __init__(self, max_samples=1000): def __init__(self, max_samples=1000):
super().__init__() super().__init__()
self.setTitle("Plot Settings") self.setTitle("Plot Settings")

View File

@ -588,7 +588,7 @@
<customwidget> <customwidget>
<class>QtWaitingSpinner</class> <class>QtWaitingSpinner</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>view.waitingspinnerwidget</header> <header>pytec.gui.view.waitingspinnerwidget</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>

View File

@ -2,7 +2,7 @@ from PyQt6 import QtWidgets, QtGui, QtCore
from PyQt6.QtCore import pyqtSignal, pyqtSlot from PyQt6.QtCore import pyqtSignal, pyqtSlot
class thermostat_ctrl_menu(QtWidgets.QMenu): class ThermostatCtrlMenu(QtWidgets.QMenu):
fan_set_act = pyqtSignal(int) fan_set_act = pyqtSignal(int)
fan_auto_set_act = pyqtSignal(int) fan_auto_set_act = pyqtSignal(int)

View File

@ -2,7 +2,7 @@ from PyQt6.QtCore import pyqtSlot, QObject
from PyQt6 import QtWidgets, QtGui from PyQt6 import QtWidgets, QtGui
class zero_limits_warning_view(QObject): class ZeroLimitsWarningView(QObject):
def __init__(self, style, limit_warning): def __init__(self, style, limit_warning):
super().__init__() super().__init__()
self._lbl = limit_warning self._lbl = limit_warning

View File

@ -14,5 +14,5 @@ setup(
"tec_qt = tec_qt:main", "tec_qt = tec_qt:main",
] ]
}, },
py_modules=['tec_qt', 'ui_tec_qt', 'autotune', 'waitingspinnerwidget'], py_modules=['autotune', 'plot', 'tec_qt'],
) )

View File

@ -1,13 +1,13 @@
from view.zero_limits_warning import zero_limits_warning_view from pytec.gui.view.zero_limits_warning import ZeroLimitsWarningView
from view.net_settings_input_diag import net_settings_input_diag from pytec.gui.view.net_settings_input_diag import NetSettingsInputDiag
from view.thermostat_ctrl_menu import thermostat_ctrl_menu from pytec.gui.view.thermostat_ctrl_menu import ThermostatCtrlMenu
from view.conn_menu import conn_menu from pytec.gui.view.conn_menu import ConnMenu
from view.plot_options_menu import plot_options_menu from pytec.gui.view.plot_options_menu import PlotOptionsMenu
from view.live_plot_view import LiveDataPlotter from pytec.gui.view.live_plot_view import LiveDataPlotter
from view.ctrl_panel import ctrl_panel from pytec.gui.view.ctrl_panel import CtrlPanel
from view.info_box import info_box from pytec.gui.view.info_box import InfoBox
from model.pid_autotuner import PIDAutoTuner from pytec.gui.model.pid_autotuner import PIDAutoTuner
from model.thermostat_data_model import WrappedClient, Thermostat from pytec.gui.model.thermostat import WrappedClient, Thermostat
import json import json
from autotune import PIDAutotuneState from autotune import PIDAutotuneState
from qasync import asyncSlot, asyncClose from qasync import asyncSlot, asyncClose
@ -23,9 +23,6 @@ from functools import partial
import importlib.resources import importlib.resources
pg.setConfigOptions(antialias=True)
def get_argparser(): def get_argparser():
parser = argparse.ArgumentParser(description="Thermostat Control Panel") parser = argparse.ArgumentParser(description="Thermostat Control Panel")
@ -47,7 +44,7 @@ def get_argparser():
parser.add_argument( parser.add_argument(
"-p", "-p",
"--param_tree", "--param_tree",
default=importlib.resources.files("view").joinpath("param_tree.json"), default=importlib.resources.files("pytec.gui.view").joinpath("param_tree.json"),
help="Param Tree Description JSON File", help="Param Tree Description JSON File",
) )
@ -60,13 +57,11 @@ class MainWindow(QtWidgets.QMainWindow):
def __init__(self, args): def __init__(self, args):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
ui_file_path = importlib.resources.files("view").joinpath("tec_qt.ui") ui_file_path = importlib.resources.files("pytec.gui.view").joinpath("tec_qt.ui")
uic.loadUi(ui_file_path, self) uic.loadUi(ui_file_path, self)
self.show()
self.hw_rev_data = None self.hw_rev_data = None
self.info_box = info_box() self.info_box = InfoBox()
self.client = WrappedClient(self) self.client = WrappedClient(self)
self.client.connection_error.connect(self.bail) self.client.connection_error.connect(self.bail)
@ -94,10 +89,10 @@ class MainWindow(QtWidgets.QMainWindow):
] ]
self.thermostat.info_box_trigger.connect(self.info_box.display_info_box) self.thermostat.info_box_trigger.connect(self.info_box.display_info_box)
self.zero_limits_warning = zero_limits_warning_view( self.zero_limits_warning = ZeroLimitsWarningView(
self.style(), self.limits_warning self.style(), self.limits_warning
) )
self.ctrl_panel_view = ctrl_panel( self.ctrl_panel_view = CtrlPanel(
[self.ch0_tree, self.ch1_tree], [self.ch0_tree, self.ch1_tree],
get_ctrl_panel_config(args), get_ctrl_panel_config(args),
self.send_command, self.send_command,
@ -136,17 +131,17 @@ class MainWindow(QtWidgets.QMainWindow):
self.thermostat.report_update.connect(self.channel_graphs.update_report) self.thermostat.report_update.connect(self.channel_graphs.update_report)
self.thermostat.pid_update.connect(self.channel_graphs.update_pid) self.thermostat.pid_update.connect(self.channel_graphs.update_pid)
self.plot_options_menu = plot_options_menu() self.plot_options_menu = PlotOptionsMenu()
self.plot_options_menu.clear.triggered.connect(self.clear_graphs) self.plot_options_menu.clear.triggered.connect(self.clear_graphs)
self.plot_options_menu.samples_spinbox.valueChanged.connect( self.plot_options_menu.samples_spinbox.valueChanged.connect(
self.channel_graphs.set_max_samples self.channel_graphs.set_max_samples
) )
self.plot_settings.setMenu(self.plot_options_menu) self.plot_settings.setMenu(self.plot_options_menu)
self.conn_menu = conn_menu() self.conn_menu = ConnMenu()
self.connect_btn.setMenu(self.conn_menu) self.connect_btn.setMenu(self.conn_menu)
self.thermostat_ctrl_menu = thermostat_ctrl_menu(self.style()) self.thermostat_ctrl_menu = ThermostatCtrlMenu(self.style())
self.thermostat_ctrl_menu.fan_set_act.connect(self.fan_set_request) self.thermostat_ctrl_menu.fan_set_act.connect(self.fan_set_request)
self.thermostat_ctrl_menu.fan_auto_set_act.connect(self.fan_auto_set_request) self.thermostat_ctrl_menu.fan_auto_set_act.connect(self.fan_auto_set_request)
self.thermostat_ctrl_menu.reset_act.connect(self.reset_request) self.thermostat_ctrl_menu.reset_act.connect(self.reset_request)
@ -213,8 +208,8 @@ class MainWindow(QtWidgets.QMainWindow):
return return
with QSignalBlocker(self.thermostat_ctrl_menu.fan_power_slider): with QSignalBlocker(self.thermostat_ctrl_menu.fan_power_slider):
self.thermostat_ctrl_menu.fan_power_slider.setValue( self.thermostat_ctrl_menu.fan_power_slider.setValue(
fan_settings["fan_pwm"] or 100 fan_settings["fan_pwm"] or 100 # 0 = PWM off = full strength
) # 0 = PWM off = full strength )
with QSignalBlocker(self.thermostat_ctrl_menu.fan_auto_box): with QSignalBlocker(self.thermostat_ctrl_menu.fan_auto_box):
self.thermostat_ctrl_menu.fan_auto_box.setChecked(fan_settings["auto_mode"]) self.thermostat_ctrl_menu.fan_auto_box.setChecked(fan_settings["auto_mode"])
if not self.hw_rev_data["settings"]["fan_pwm_recommended"]: if not self.hw_rev_data["settings"]["fan_pwm_recommended"]:
@ -399,7 +394,7 @@ class MainWindow(QtWidgets.QMainWindow):
@asyncSlot(bool) @asyncSlot(bool)
async def net_settings_request(self, _): async def net_settings_request(self, _):
ipv4 = await self.thermostat.get_ipv4() ipv4 = await self.thermostat.get_ipv4()
self.net_settings_input_diag = net_settings_input_diag(ipv4["addr"]) self.net_settings_input_diag = NetSettingsInputDiag(ipv4["addr"])
self.net_settings_input_diag.set_ipv4_act.connect(self.set_net_settings_request) self.net_settings_input_diag.set_ipv4_act.connect(self.set_net_settings_request)
@asyncSlot(str) @asyncSlot(str)
@ -419,7 +414,7 @@ async def coro_main():
app = QtWidgets.QApplication.instance() app = QtWidgets.QApplication.instance()
app.aboutToQuit.connect(app_quit_event.set) app.aboutToQuit.connect(app_quit_event.set)
app.setWindowIcon( app.setWindowIcon(
QtGui.QIcon(str(importlib.resources.files("resources").joinpath("artiq.ico"))) QtGui.QIcon(str(importlib.resources.files("pytec.gui.resources").joinpath("artiq.ico")))
) )
main_window = MainWindow(args) main_window = MainWindow(args)