forked from M-Labs/artiq
gui: centralize subscribers
This commit is contained in:
parent
ae99af27ee
commit
c3f99eda8f
|
@ -12,13 +12,8 @@ from pyqtgraph import dockarea
|
||||||
|
|
||||||
from artiq.tools import verbosity_args, init_logger, artiq_dir
|
from artiq.tools import verbosity_args, init_logger, artiq_dir
|
||||||
from artiq.protocols.pc_rpc import AsyncioClient
|
from artiq.protocols.pc_rpc import AsyncioClient
|
||||||
from artiq.gui.state import StateManager
|
from artiq.gui.models import ModelSubscriber
|
||||||
from artiq.gui.explorer import ExplorerDock
|
from artiq.gui import state, explorer, moninj, datasets, schedule, log, console
|
||||||
from artiq.gui.moninj import MonInj
|
|
||||||
from artiq.gui.datasets import DatasetsDock
|
|
||||||
from artiq.gui.schedule import ScheduleDock
|
|
||||||
from artiq.gui.log import LogDock
|
|
||||||
from artiq.gui.console import ConsoleDock
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
|
@ -57,6 +52,12 @@ class MainWindow(QtGui.QMainWindow):
|
||||||
self.restoreGeometry(QtCore.QByteArray(state))
|
self.restoreGeometry(QtCore.QByteArray(state))
|
||||||
|
|
||||||
|
|
||||||
|
def atexit_register_coroutine(coroutine, loop=None):
|
||||||
|
if loop is None:
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
atexit.register(lambda: loop.run_until_complete(coroutine()))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = get_argparser().parse_args()
|
args = get_argparser().parse_args()
|
||||||
init_logger(args)
|
init_logger(args)
|
||||||
|
@ -74,7 +75,18 @@ def main():
|
||||||
atexit.register(client.close_rpc)
|
atexit.register(client.close_rpc)
|
||||||
rpc_clients[target] = client
|
rpc_clients[target] = client
|
||||||
|
|
||||||
smgr = StateManager(args.db_file)
|
sub_clients = dict()
|
||||||
|
for notifier_name, module in (("explist", explorer),
|
||||||
|
("datasets", datasets),
|
||||||
|
("schedule", schedule),
|
||||||
|
("log", log)):
|
||||||
|
subscriber = ModelSubscriber(notifier_name, module.Model)
|
||||||
|
loop.run_until_complete(subscriber.connect(
|
||||||
|
args.server, args.port_notify))
|
||||||
|
atexit_register_coroutine(subscriber.close)
|
||||||
|
sub_clients[notifier_name] = subscriber
|
||||||
|
|
||||||
|
smgr = state.StateManager(args.db_file)
|
||||||
|
|
||||||
win = MainWindow(app, args.server)
|
win = MainWindow(app, args.server)
|
||||||
area = dockarea.DockArea()
|
area = dockarea.DockArea()
|
||||||
|
@ -85,24 +97,20 @@ def main():
|
||||||
status_bar.showMessage("Connected to {}".format(args.server))
|
status_bar.showMessage("Connected to {}".format(args.server))
|
||||||
win.setStatusBar(status_bar)
|
win.setStatusBar(status_bar)
|
||||||
|
|
||||||
d_explorer = ExplorerDock(win, status_bar,
|
d_explorer = explorer.ExplorerDock(win, status_bar,
|
||||||
|
sub_clients["explist"],
|
||||||
|
sub_clients["schedule"],
|
||||||
rpc_clients["schedule"],
|
rpc_clients["schedule"],
|
||||||
rpc_clients["repository"])
|
rpc_clients["repository"])
|
||||||
smgr.register(d_explorer)
|
smgr.register(d_explorer)
|
||||||
loop.run_until_complete(d_explorer.sub_connect(
|
|
||||||
args.server, args.port_notify))
|
|
||||||
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))
|
|
||||||
|
|
||||||
d_datasets = DatasetsDock(win, area)
|
d_datasets = datasets.DatasetsDock(win, area, sub_clients["datasets"])
|
||||||
smgr.register(d_datasets)
|
smgr.register(d_datasets)
|
||||||
loop.run_until_complete(d_datasets.sub_connect(
|
|
||||||
args.server, args.port_notify))
|
|
||||||
atexit.register(lambda: loop.run_until_complete(d_datasets.sub_close()))
|
|
||||||
|
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
d_ttl_dds = MonInj()
|
d_ttl_dds = moninj.MonInj()
|
||||||
loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify))
|
loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify))
|
||||||
atexit.register(lambda: loop.run_until_complete(d_ttl_dds.stop()))
|
atexit_register_coroutine(d_ttl_dds.stop)
|
||||||
|
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
area.addDock(d_ttl_dds.dds_dock, "top")
|
area.addDock(d_ttl_dds.dds_dock, "top")
|
||||||
|
@ -112,23 +120,17 @@ def main():
|
||||||
area.addDock(d_datasets, "top")
|
area.addDock(d_datasets, "top")
|
||||||
area.addDock(d_explorer, "above", d_datasets)
|
area.addDock(d_explorer, "above", d_datasets)
|
||||||
|
|
||||||
d_schedule = ScheduleDock(status_bar, rpc_clients["schedule"])
|
d_schedule = schedule.ScheduleDock(
|
||||||
loop.run_until_complete(d_schedule.sub_connect(
|
status_bar, rpc_clients["schedule"], sub_clients["schedule"])
|
||||||
args.server, args.port_notify))
|
|
||||||
atexit.register(lambda: loop.run_until_complete(d_schedule.sub_close()))
|
|
||||||
d_explorer.get_current_schedule = d_schedule.get_current_schedule
|
|
||||||
|
|
||||||
d_log = LogDock()
|
d_log = log.LogDock(sub_clients["log"])
|
||||||
smgr.register(d_log)
|
smgr.register(d_log)
|
||||||
loop.run_until_complete(d_log.sub_connect(
|
|
||||||
args.server, args.port_notify))
|
|
||||||
atexit.register(lambda: loop.run_until_complete(d_log.sub_close()))
|
|
||||||
|
|
||||||
def _set_dataset(k, v):
|
def _set_dataset(k, v):
|
||||||
asyncio.ensure_future(rpc_clients["dataset_db"].set(k, v))
|
asyncio.ensure_future(rpc_clients["dataset_db"].set(k, v))
|
||||||
def _del_dataset(k):
|
def _del_dataset(k):
|
||||||
asyncio.ensure_future(rpc_clients["dataset_db"].delete(k))
|
asyncio.ensure_future(rpc_clients["dataset_db"].delete(k))
|
||||||
d_console = ConsoleDock(
|
d_console = console.ConsoleDock(
|
||||||
d_datasets.get_dataset,
|
d_datasets.get_dataset,
|
||||||
_set_dataset,
|
_set_dataset,
|
||||||
_del_dataset)
|
_del_dataset)
|
||||||
|
@ -139,7 +141,7 @@ def main():
|
||||||
|
|
||||||
smgr.load()
|
smgr.load()
|
||||||
smgr.start()
|
smgr.start()
|
||||||
atexit.register(lambda: loop.run_until_complete(smgr.stop()))
|
atexit_register_coroutine(smgr.stop)
|
||||||
win.show()
|
win.show()
|
||||||
loop.run_until_complete(win.exit_request.wait())
|
loop.run_until_complete(win.exit_request.wait())
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@ from quamash import QtGui, QtCore
|
||||||
from pyqtgraph import dockarea
|
from pyqtgraph import dockarea
|
||||||
from pyqtgraph import LayoutWidget
|
from pyqtgraph import LayoutWidget
|
||||||
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
|
||||||
from artiq.tools import short_format
|
from artiq.tools import short_format
|
||||||
from artiq.gui.tools import DictSyncModel
|
from artiq.gui.models import DictSyncModel
|
||||||
from artiq.gui.displays import *
|
from artiq.gui.displays import *
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -21,10 +20,9 @@ except AttributeError:
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DatasetsModel(DictSyncModel):
|
class Model(DictSyncModel):
|
||||||
def __init__(self, parent, init):
|
def __init__(self, init):
|
||||||
DictSyncModel.__init__(self, ["Dataset", "Persistent", "Value"],
|
DictSyncModel.__init__(self, ["Dataset", "Persistent", "Value"], init)
|
||||||
parent, init)
|
|
||||||
|
|
||||||
def sort_key(self, k, v):
|
def sort_key(self, k, v):
|
||||||
return k
|
return k
|
||||||
|
@ -47,7 +45,7 @@ def _get_display_type_name(display_cls):
|
||||||
|
|
||||||
|
|
||||||
class DatasetsDock(dockarea.Dock):
|
class DatasetsDock(dockarea.Dock):
|
||||||
def __init__(self, dialog_parent, dock_area):
|
def __init__(self, dialog_parent, dock_area, datasets_sub):
|
||||||
dockarea.Dock.__init__(self, "Datasets", size=(1500, 500))
|
dockarea.Dock.__init__(self, "Datasets", size=(1500, 500))
|
||||||
self.dialog_parent = dialog_parent
|
self.dialog_parent = dialog_parent
|
||||||
self.dock_area = dock_area
|
self.dock_area = dock_area
|
||||||
|
@ -66,6 +64,9 @@ class DatasetsDock(dockarea.Dock):
|
||||||
QtGui.QHeaderView.ResizeToContents)
|
QtGui.QHeaderView.ResizeToContents)
|
||||||
grid.addWidget(self.table, 1, 0)
|
grid.addWidget(self.table, 1, 0)
|
||||||
|
|
||||||
|
self.table_model = Model(dict())
|
||||||
|
datasets_sub.add_setmodel_callback(self.set_model)
|
||||||
|
|
||||||
add_display_box = QtGui.QGroupBox("Add display")
|
add_display_box = QtGui.QGroupBox("Add display")
|
||||||
grid.addWidget(add_display_box, 1, 1)
|
grid.addWidget(add_display_box, 1, 1)
|
||||||
display_grid = QtGui.QGridLayout()
|
display_grid = QtGui.QGridLayout()
|
||||||
|
@ -79,25 +80,18 @@ class DatasetsDock(dockarea.Dock):
|
||||||
self.displays = dict()
|
self.displays = dict()
|
||||||
|
|
||||||
def _search_datasets(self):
|
def _search_datasets(self):
|
||||||
self.table_model_filter.setFilterFixedString(self.search.displayText())
|
if hasattr(self, "table_model_filter"):
|
||||||
|
self.table_model_filter.setFilterFixedString(
|
||||||
|
self.search.displayText())
|
||||||
|
|
||||||
def get_dataset(self, key):
|
def get_dataset(self, key):
|
||||||
return self.table_model.backing_store[key][1]
|
return self.table_model.backing_store[key][1]
|
||||||
|
|
||||||
async def sub_connect(self, host, port):
|
def set_model(self, model):
|
||||||
self.subscriber = Subscriber("datasets", self.init_datasets_model,
|
self.table_model = model
|
||||||
self.on_mod)
|
|
||||||
await self.subscriber.connect(host, port)
|
|
||||||
|
|
||||||
async def sub_close(self):
|
|
||||||
await self.subscriber.close()
|
|
||||||
|
|
||||||
def init_datasets_model(self, init):
|
|
||||||
self.table_model = DatasetsModel(self.table, init)
|
|
||||||
self.table_model_filter = QSortFilterProxyModel()
|
self.table_model_filter = QSortFilterProxyModel()
|
||||||
self.table_model_filter.setSourceModel(self.table_model)
|
self.table_model_filter.setSourceModel(self.table_model)
|
||||||
self.table.setModel(self.table_model_filter)
|
self.table.setModel(self.table_model_filter)
|
||||||
return self.table_model
|
|
||||||
|
|
||||||
def update_display_data(self, dsp):
|
def update_display_data(self, dsp):
|
||||||
filtered_data = {k: self.table_model.backing_store[k][1]
|
filtered_data = {k: self.table_model.backing_store[k][1]
|
||||||
|
|
|
@ -5,19 +5,18 @@ from quamash import QtGui, QtCore
|
||||||
from pyqtgraph import dockarea
|
from pyqtgraph import dockarea
|
||||||
from pyqtgraph import LayoutWidget
|
from pyqtgraph import LayoutWidget
|
||||||
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
|
||||||
from artiq.protocols import pyon
|
from artiq.protocols import pyon
|
||||||
from artiq.gui.tools import DictSyncModel
|
from artiq.gui.models import DictSyncModel
|
||||||
from artiq.gui.scan import ScanController
|
from artiq.gui.scan import ScanController
|
||||||
from artiq.gui.shortcuts import ShortcutManager
|
from artiq.gui.shortcuts import ShortcutManager
|
||||||
|
|
||||||
|
|
||||||
class _ExplistModel(DictSyncModel):
|
class Model(DictSyncModel):
|
||||||
def __init__(self, explorer, parent, init):
|
def __init__(self, init):
|
||||||
self.explorer = explorer
|
|
||||||
DictSyncModel.__init__(self,
|
DictSyncModel.__init__(self,
|
||||||
["Experiment"],
|
["Experiment"],
|
||||||
parent, init)
|
init)
|
||||||
|
self.explorer = None
|
||||||
|
|
||||||
def sort_key(self, k, v):
|
def sort_key(self, k, v):
|
||||||
return k
|
return k
|
||||||
|
@ -27,6 +26,7 @@ class _ExplistModel(DictSyncModel):
|
||||||
|
|
||||||
def __setitem__(self, k, v):
|
def __setitem__(self, k, v):
|
||||||
DictSyncModel.__setitem__(self, k, v)
|
DictSyncModel.__setitem__(self, k, v)
|
||||||
|
if self.explorer is not None:
|
||||||
if k == self.explorer.selected_key:
|
if k == self.explorer.selected_key:
|
||||||
self.explorer.update_selection(k, k)
|
self.explorer.update_selection(k, k)
|
||||||
|
|
||||||
|
@ -216,11 +216,14 @@ class _ArgumentEditor(QtGui.QTreeWidget):
|
||||||
|
|
||||||
|
|
||||||
class ExplorerDock(dockarea.Dock):
|
class ExplorerDock(dockarea.Dock):
|
||||||
def __init__(self, main_window, status_bar, schedule_ctl, repository_ctl):
|
def __init__(self, main_window, status_bar,
|
||||||
|
explist_sub, schedule_sub,
|
||||||
|
schedule_ctl, repository_ctl):
|
||||||
dockarea.Dock.__init__(self, "Explorer", size=(1500, 500))
|
dockarea.Dock.__init__(self, "Explorer", size=(1500, 500))
|
||||||
|
|
||||||
self.main_window = main_window
|
self.main_window = main_window
|
||||||
self.status_bar = status_bar
|
self.status_bar = status_bar
|
||||||
|
self.schedule_sub = schedule_sub
|
||||||
self.schedule_ctl = schedule_ctl
|
self.schedule_ctl = schedule_ctl
|
||||||
|
|
||||||
self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
|
self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
|
||||||
|
@ -271,6 +274,8 @@ class ExplorerDock(dockarea.Dock):
|
||||||
self.splitter.addWidget(self.argeditor)
|
self.splitter.addWidget(self.argeditor)
|
||||||
self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])
|
self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])
|
||||||
self.argeditor_states = dict()
|
self.argeditor_states = dict()
|
||||||
|
self.explist_model = Model(dict())
|
||||||
|
explist_sub.add_setmodel_callback(self.set_model)
|
||||||
|
|
||||||
self.shortcuts = ShortcutManager(self.main_window, self)
|
self.shortcuts = ShortcutManager(self.main_window, self)
|
||||||
|
|
||||||
|
@ -299,6 +304,11 @@ class ExplorerDock(dockarea.Dock):
|
||||||
scan_repository_action.triggered.connect(scan_repository)
|
scan_repository_action.triggered.connect(scan_repository)
|
||||||
self.el.addAction(scan_repository_action)
|
self.el.addAction(scan_repository_action)
|
||||||
|
|
||||||
|
def set_model(self, model):
|
||||||
|
model.explorer = self
|
||||||
|
self.explist_model = model
|
||||||
|
self.el.setModel(model)
|
||||||
|
|
||||||
def update_selection(self, selected, deselected):
|
def update_selection(self, selected, deselected):
|
||||||
if deselected:
|
if deselected:
|
||||||
self.argeditor_states[deselected] = self.argeditor.save_state()
|
self.argeditor_states[deselected] = self.argeditor.save_state()
|
||||||
|
@ -346,19 +356,6 @@ class ExplorerDock(dockarea.Dock):
|
||||||
def enable_duedate(self):
|
def enable_duedate(self):
|
||||||
self.datetime_en.setChecked(True)
|
self.datetime_en.setChecked(True)
|
||||||
|
|
||||||
async def sub_connect(self, host, port):
|
|
||||||
self.explist_subscriber = Subscriber("explist",
|
|
||||||
self.init_explist_model)
|
|
||||||
await self.explist_subscriber.connect(host, port)
|
|
||||||
|
|
||||||
async def sub_close(self):
|
|
||||||
await self.explist_subscriber.close()
|
|
||||||
|
|
||||||
def init_explist_model(self, init):
|
|
||||||
self.explist_model = _ExplistModel(self, self.el, init)
|
|
||||||
self.el.setModel(self.explist_model)
|
|
||||||
return self.explist_model
|
|
||||||
|
|
||||||
async def submit_task(self, pipeline_name, file, class_name, arguments,
|
async def submit_task(self, pipeline_name, file, class_name, arguments,
|
||||||
priority, due_date, flush):
|
priority, due_date, flush):
|
||||||
expid = {
|
expid = {
|
||||||
|
@ -414,9 +411,8 @@ class ExplorerDock(dockarea.Dock):
|
||||||
def request_inst_term(self):
|
def request_inst_term(self):
|
||||||
if self.selected_key is not None:
|
if self.selected_key is not None:
|
||||||
expinfo = self.explist_model.backing_store[self.selected_key]
|
expinfo = self.explist_model.backing_store[self.selected_key]
|
||||||
# attribute get_current_schedule must be set externally after
|
if self.schedule_sub.model is not None:
|
||||||
# instance creation
|
current_schedule = self.schedule_sub.model.backing_store
|
||||||
current_schedule = self.get_current_schedule()
|
|
||||||
rids = []
|
rids = []
|
||||||
for rid, desc in current_schedule.items():
|
for rid, desc in current_schedule.items():
|
||||||
expid = desc["expid"]
|
expid = desc["expid"]
|
||||||
|
|
|
@ -5,8 +5,6 @@ import time
|
||||||
from quamash import QtGui, QtCore
|
from quamash import QtGui, QtCore
|
||||||
from pyqtgraph import dockarea, LayoutWidget
|
from pyqtgraph import dockarea, LayoutWidget
|
||||||
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
QSortFilterProxyModel = QtCore.QSortFilterProxyModel
|
QSortFilterProxyModel = QtCore.QSortFilterProxyModel
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -25,9 +23,9 @@ def _level_to_name(level):
|
||||||
return "DEBUG"
|
return "DEBUG"
|
||||||
|
|
||||||
|
|
||||||
class _LogModel(QtCore.QAbstractTableModel):
|
class Model(QtCore.QAbstractTableModel):
|
||||||
def __init__(self, parent, init):
|
def __init__(self, init):
|
||||||
QtCore.QAbstractTableModel.__init__(self, parent)
|
QtCore.QAbstractTableModel.__init__(self)
|
||||||
|
|
||||||
self.headers = ["Level", "Source", "Time", "Message"]
|
self.headers = ["Level", "Source", "Time", "Message"]
|
||||||
|
|
||||||
|
@ -153,7 +151,7 @@ class _LogFilterProxyModel(QSortFilterProxyModel):
|
||||||
|
|
||||||
|
|
||||||
class LogDock(dockarea.Dock):
|
class LogDock(dockarea.Dock):
|
||||||
def __init__(self):
|
def __init__(self, log_sub):
|
||||||
dockarea.Dock.__init__(self, "Log", size=(1000, 300))
|
dockarea.Dock.__init__(self, "Log", size=(1000, 300))
|
||||||
|
|
||||||
grid = LayoutWidget()
|
grid = LayoutWidget()
|
||||||
|
@ -183,12 +181,7 @@ class LogDock(dockarea.Dock):
|
||||||
grid.addWidget(self.log, 1, 0, colspan=4)
|
grid.addWidget(self.log, 1, 0, colspan=4)
|
||||||
self.scroll_at_bottom = False
|
self.scroll_at_bottom = False
|
||||||
|
|
||||||
async def sub_connect(self, host, port):
|
log_sub.add_setmodel_callback(self.set_model)
|
||||||
self.subscriber = Subscriber("log", self.init_log_model)
|
|
||||||
await self.subscriber.connect(host, port)
|
|
||||||
|
|
||||||
async def sub_close(self):
|
|
||||||
await self.subscriber.close()
|
|
||||||
|
|
||||||
def filter_level_changed(self):
|
def filter_level_changed(self):
|
||||||
if not hasattr(self, "table_model_filter"):
|
if not hasattr(self, "table_model_filter"):
|
||||||
|
@ -223,8 +216,8 @@ class LogDock(dockarea.Dock):
|
||||||
scrollbar = self.log.verticalScrollBar()
|
scrollbar = self.log.verticalScrollBar()
|
||||||
scrollbar.setValue(self.scroll_value)
|
scrollbar.setValue(self.scroll_value)
|
||||||
|
|
||||||
def init_log_model(self, init):
|
def set_model(self, model):
|
||||||
self.table_model = _LogModel(self.log, init)
|
self.table_model = model
|
||||||
self.table_model_filter = _LogFilterProxyModel(
|
self.table_model_filter = _LogFilterProxyModel(
|
||||||
getattr(logging, self.filter_level.currentText()),
|
getattr(logging, self.filter_level.currentText()),
|
||||||
self.filter_freetext.text())
|
self.filter_freetext.text())
|
||||||
|
@ -233,7 +226,6 @@ class LogDock(dockarea.Dock):
|
||||||
self.table_model_filter.rowsAboutToBeInserted.connect(self.rows_inserted_before)
|
self.table_model_filter.rowsAboutToBeInserted.connect(self.rows_inserted_before)
|
||||||
self.table_model_filter.rowsInserted.connect(self.rows_inserted_after)
|
self.table_model_filter.rowsInserted.connect(self.rows_inserted_after)
|
||||||
self.table_model_filter.rowsRemoved.connect(self.rows_removed)
|
self.table_model_filter.rowsRemoved.connect(self.rows_removed)
|
||||||
return self.table_model
|
|
||||||
|
|
||||||
def save_state(self):
|
def save_state(self):
|
||||||
return {"min_level_idx": self.filter_level.currentIndex()}
|
return {"min_level_idx": self.filter_level.currentIndex()}
|
||||||
|
|
|
@ -1,5 +1,26 @@
|
||||||
from quamash import QtCore
|
from quamash import QtCore
|
||||||
|
|
||||||
|
from artiq.protocols.sync_struct import Subscriber
|
||||||
|
|
||||||
|
|
||||||
|
class ModelSubscriber(Subscriber):
|
||||||
|
def __init__(self, notifier_name, model_factory):
|
||||||
|
Subscriber.__init__(self, notifier_name, self._create_model)
|
||||||
|
self.model = None
|
||||||
|
self._model_factory = model_factory
|
||||||
|
self._setmodel_callbacks = []
|
||||||
|
|
||||||
|
def _create_model(self, init):
|
||||||
|
self.model = self._model_factory(init)
|
||||||
|
for cb in self._setmodel_callbacks:
|
||||||
|
cb(self.model)
|
||||||
|
return self.model
|
||||||
|
|
||||||
|
def add_setmodel_callback(self, cb):
|
||||||
|
self._setmodel_callbacks.append(cb)
|
||||||
|
if self.model is not None:
|
||||||
|
cb(self.model)
|
||||||
|
|
||||||
|
|
||||||
class _SyncSubstruct:
|
class _SyncSubstruct:
|
||||||
def __init__(self, update_cb, ref):
|
def __init__(self, update_cb, ref):
|
||||||
|
@ -31,12 +52,12 @@ class _SyncSubstruct:
|
||||||
|
|
||||||
|
|
||||||
class DictSyncModel(QtCore.QAbstractTableModel):
|
class DictSyncModel(QtCore.QAbstractTableModel):
|
||||||
def __init__(self, headers, parent, init):
|
def __init__(self, headers, init):
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.backing_store = init
|
self.backing_store = init
|
||||||
self.row_to_key = sorted(self.backing_store.keys(),
|
self.row_to_key = sorted(self.backing_store.keys(),
|
||||||
key=lambda k: self.sort_key(k, self.backing_store[k]))
|
key=lambda k: self.sort_key(k, self.backing_store[k]))
|
||||||
QtCore.QAbstractTableModel.__init__(self, parent)
|
QtCore.QAbstractTableModel.__init__(self)
|
||||||
|
|
||||||
def rowCount(self, parent):
|
def rowCount(self, parent):
|
||||||
return len(self.backing_store)
|
return len(self.backing_store)
|
||||||
|
@ -45,10 +66,9 @@ class DictSyncModel(QtCore.QAbstractTableModel):
|
||||||
return len(self.headers)
|
return len(self.headers)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid() or role != QtCore.Qt.DisplayRole:
|
||||||
return None
|
|
||||||
elif role != QtCore.Qt.DisplayRole:
|
|
||||||
return None
|
return None
|
||||||
|
else:
|
||||||
k = self.row_to_key[index.row()]
|
k = self.row_to_key[index.row()]
|
||||||
return self.convert(k, self.backing_store[k], index.column())
|
return self.convert(k, self.backing_store[k], index.column())
|
||||||
|
|
||||||
|
@ -113,10 +133,10 @@ class DictSyncModel(QtCore.QAbstractTableModel):
|
||||||
|
|
||||||
|
|
||||||
class ListSyncModel(QtCore.QAbstractTableModel):
|
class ListSyncModel(QtCore.QAbstractTableModel):
|
||||||
def __init__(self, headers, parent, init):
|
def __init__(self, headers, init):
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.backing_store = init
|
self.backing_store = init
|
||||||
QtCore.QAbstractTableModel.__init__(self, parent)
|
QtCore.QAbstractTableModel.__init__(self)
|
||||||
|
|
||||||
def rowCount(self, parent):
|
def rowCount(self, parent):
|
||||||
return len(self.backing_store)
|
return len(self.backing_store)
|
||||||
|
@ -125,11 +145,11 @@ class ListSyncModel(QtCore.QAbstractTableModel):
|
||||||
return len(self.headers)
|
return len(self.headers)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid() or role != QtCore.Qt.DisplayRole:
|
||||||
return None
|
return None
|
||||||
elif role != QtCore.Qt.DisplayRole:
|
else:
|
||||||
return None
|
return self.convert(self.backing_store[index.row()],
|
||||||
return self.convert(self.backing_store[index.row()], index.column())
|
index.column())
|
||||||
|
|
||||||
def headerData(self, col, orientation, role):
|
def headerData(self, col, orientation, role):
|
||||||
if (orientation == QtCore.Qt.Horizontal
|
if (orientation == QtCore.Qt.Horizontal
|
|
@ -5,17 +5,16 @@ from functools import partial
|
||||||
from quamash import QtGui, QtCore
|
from quamash import QtGui, QtCore
|
||||||
from pyqtgraph import dockarea
|
from pyqtgraph import dockarea
|
||||||
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
from artiq.gui.models import DictSyncModel
|
||||||
from artiq.gui.tools import DictSyncModel
|
|
||||||
from artiq.tools import elide
|
from artiq.tools import elide
|
||||||
|
|
||||||
|
|
||||||
class _ScheduleModel(DictSyncModel):
|
class Model(DictSyncModel):
|
||||||
def __init__(self, parent, init):
|
def __init__(self, init):
|
||||||
DictSyncModel.__init__(self,
|
DictSyncModel.__init__(self,
|
||||||
["RID", "Pipeline", "Status", "Prio", "Due date",
|
["RID", "Pipeline", "Status", "Prio", "Due date",
|
||||||
"Revision", "File", "Class name"],
|
"Revision", "File", "Class name"],
|
||||||
parent, init)
|
init)
|
||||||
|
|
||||||
def sort_key(self, k, v):
|
def sort_key(self, k, v):
|
||||||
# order by priority, and then by due date and RID
|
# order by priority, and then by due date and RID
|
||||||
|
@ -57,7 +56,7 @@ class _ScheduleModel(DictSyncModel):
|
||||||
|
|
||||||
|
|
||||||
class ScheduleDock(dockarea.Dock):
|
class ScheduleDock(dockarea.Dock):
|
||||||
def __init__(self, status_bar, schedule_ctl):
|
def __init__(self, status_bar, schedule_ctl, schedule_sub):
|
||||||
dockarea.Dock.__init__(self, "Schedule", size=(1000, 300))
|
dockarea.Dock.__init__(self, "Schedule", size=(1000, 300))
|
||||||
|
|
||||||
self.status_bar = status_bar
|
self.status_bar = status_bar
|
||||||
|
@ -82,24 +81,12 @@ class ScheduleDock(dockarea.Dock):
|
||||||
delete_action.setShortcut("SHIFT+DELETE")
|
delete_action.setShortcut("SHIFT+DELETE")
|
||||||
self.table.addAction(delete_action)
|
self.table.addAction(delete_action)
|
||||||
|
|
||||||
async def sub_connect(self, host, port):
|
self.table_model = Model(dict())
|
||||||
self.subscriber = Subscriber("schedule", self.init_schedule_model)
|
schedule_sub.add_setmodel_callback(self.set_model)
|
||||||
await self.subscriber.connect(host, port)
|
|
||||||
|
|
||||||
async def sub_close(self):
|
def set_model(self, model):
|
||||||
await self.subscriber.close()
|
self.table_model = model
|
||||||
|
|
||||||
def get_current_schedule(self):
|
|
||||||
try:
|
|
||||||
table_model = self.table_model
|
|
||||||
except AttributeError:
|
|
||||||
return dict()
|
|
||||||
return table_model.backing_store
|
|
||||||
|
|
||||||
def init_schedule_model(self, init):
|
|
||||||
self.table_model = _ScheduleModel(self.table, init)
|
|
||||||
self.table.setModel(self.table_model)
|
self.table.setModel(self.table_model)
|
||||||
return self.table_model
|
|
||||||
|
|
||||||
async def delete(self, rid, graceful):
|
async def delete(self, rid, graceful):
|
||||||
if graceful:
|
if graceful:
|
||||||
|
|
Loading…
Reference in New Issue