moninj: add load/save config

This commit is contained in:
Simon Renblad 2024-04-22 14:06:09 +08:00
parent 6730f35489
commit c1c0f63f81

View File

@ -1,15 +1,19 @@
import asyncio import asyncio
import logging import logging
import textwrap import textwrap
import os
from collections import namedtuple from collections import namedtuple
from PyQt5 import QtCore, QtWidgets, QtGui from PyQt5 import QtCore, QtWidgets, QtGui
import pyqtgraph as pg import pyqtgraph as pg
from sipyco import pyon
from artiq.coredevice.comm_moninj import CommMonInj, TTLOverride, TTLProbe from artiq.coredevice.comm_moninj import CommMonInj, TTLOverride, TTLProbe
from artiq.coredevice.ad9912_reg import AD9912_SER_CONF from artiq.coredevice.ad9912_reg import AD9912_SER_CONF
from artiq.gui.tools import LayoutWidget from artiq.gui.tools import LayoutWidget, get_open_file_name, get_save_file_name
from artiq.gui.models import DictSyncTreeSepModel from artiq.gui.models import DictSyncTreeSepModel
from artiq.tools import exc_to_warning
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -930,6 +934,14 @@ class MonInjDock(QtWidgets.QDockWidget):
layout = LayoutWidget() layout = LayoutWidget()
self.setWidget(layout) self.setWidget(layout)
self._current_dir = os.getcwd()
self._menu_btn = QtWidgets.QPushButton()
self._menu_btn.setIcon(
QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_FileDialogStart))
layout.addWidget(self._menu_btn, 0, 0)
self._channel_model = Model({}) self._channel_model = Model({})
self.add_channel_dialog = _AddChannelDialog(self, self._channel_model) self.add_channel_dialog = _AddChannelDialog(self, self._channel_model)
self.add_channel_dialog.accepted.connect( self.add_channel_dialog.accepted.connect(
@ -940,11 +952,22 @@ class MonInjDock(QtWidgets.QDockWidget):
QtWidgets.QApplication.style().standardIcon( QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_FileDialogListView)) QtWidgets.QStyle.SP_FileDialogListView))
add_channel_btn.clicked.connect(self.add_channel_dialog.open) add_channel_btn.clicked.connect(self.add_channel_dialog.open)
layout.addWidget(add_channel_btn, 0, 0, colspan=1) layout.addWidget(add_channel_btn, 0, 1)
self.tree = MoninjTreeWidget() self.tree = MoninjTreeWidget()
layout.addWidget(self.tree, 1, 0, colspan=10) layout.addWidget(self.tree, 1, 0, colspan=10)
self._file_menu = QtWidgets.QMenu()
self._add_async_action("Open configuration...", self.load_configuration)
self._add_async_action("Save configuration...", self.save_configuration)
self._menu_btn.setMenu(self._file_menu)
def _add_async_action(self, label, coro):
action = QtWidgets.QAction(label, self)
action.triggered.connect(
lambda: asyncio.ensure_future(exc_to_warning(coro())))
self._file_menu.addAction(action)
def layout_widgets(self, handlers): def layout_widgets(self, handlers):
for handler in handlers: for handler in handlers:
handler.create_widget() handler.create_widget()
@ -955,6 +978,67 @@ class MonInjDock(QtWidgets.QDockWidget):
self._channel_model.clear() self._channel_model.clear()
self._channel_model.update(handlers) self._channel_model.update(handlers)
def _get_widget_from_handler(self, uid):
if uid in self.dm.handlers_by_uid:
handler = self.dm.handlers_by_uid[uid]
handler.create_widget()
return handler.widget
else:
logger.warning("skipping moninj widget with uid {}:"
" description incorrect/missing from device db".format(uid))
return None
def _connect_config(self, config):
out_config = []
for item in config:
if isinstance(item, dict):
out_widgets = []
for uid in item["widgets"]:
widget = self._get_widget_from_handler(uid)
if widget is not None:
out_widgets.append(widget)
item["widgets"] = out_widgets
out_config.append(item)
else:
widget = self._get_widget_from_handler(item)
if widget is not None:
out_config.append(widget)
return out_config
async def load_configuration(self):
try:
filename = await get_open_file_name(
self,
"Load configuration",
self._current_dir,
"PYON files (*.pyon);;All files (*.*)")
except asyncio.CancelledError:
return
self._current_dir = os.path.dirname(filename)
try:
configuration = pyon.load_file(filename)
connected_config = self._connect_config(configuration)
self.tree.clear()
self.tree.extend(connected_config)
except Exception:
logger.error("Failed to load moninj configuration", exc_info=True)
async def save_configuration(self):
try:
filename = await get_save_file_name(
self,
"Save configuration",
self._current_dir,
"PYON files (*.pyon);;All files (*.*)")
except asyncio.CancelledError:
return
self._current_dir = os.path.dirname(filename)
try:
configuration = self.tree.export_list()
pyon.store_file(filename, configuration)
except Exception:
logger.error("Failed to save moninj configuration", exc_info=True)
async def stop(self): async def stop(self):
if self.dm is not None: if self.dm is not None:
await self.dm.close() await self.dm.close()