sync_struct,gui: refactor Subscriber data distribution to support access to parameter DB from GUI file

This commit is contained in:
Sebastien Bourdeauducq 2015-02-04 15:06:25 +08:00
parent 186aa7fdb7
commit 1b122dd887
5 changed files with 31 additions and 26 deletions

View File

@ -9,6 +9,7 @@ from gi.repository import Gtk
from artiq.protocols.file_db import FlatFileDB
from artiq.protocols.pc_rpc import AsyncioClient
from artiq.protocols.sync_struct import Subscriber
from artiq.gui.tools import LayoutManager
from artiq.gui.scheduler import SchedulerWindow
from artiq.gui.parameters import ParametersWindow
@ -67,6 +68,13 @@ def main():
atexit.register(
lambda: loop.run_until_complete(parameters_win.sub_close()))
parameters_sub = Subscriber("parameters",
parameters_win.init_parameters_store)
loop.run_until_complete(
parameters_sub.connect(args.server, args.port_notify))
atexit.register(
lambda: loop.run_until_complete(parameters_sub.close()))
def exit(*args):
lmgr.save()
Gtk.main_quit(*args)

View File

@ -88,7 +88,8 @@ class ExplorerWindow(Window):
@asyncio.coroutine
def sub_connect(self, host, port):
self.explist_subscriber = Subscriber("explist",
self.init_explist_store)
[self.init_explist_store,
self.init_explist_data])
yield from self.explist_subscriber.connect(host, port)
@asyncio.coroutine
@ -102,14 +103,16 @@ class ExplorerWindow(Window):
self.pane_contents.show_all()
def init_explist_store(self, init):
self.explist_syncer = _ExplistStoreSyncer(self.explist_store, init,
keep_data=True)
return self.explist_syncer
return _ExplistStoreSyncer(self.explist_store, init)
def init_explist_data(self, init):
self.explist_data = init
return init
def explist_row_activated(self, widget, index, column):
self.controls = None
name = self.explist_store[index][0]
gui_file = self.explist_syncer.data[name]["gui_file"]
gui_file = self.explist_data[name]["gui_file"]
if gui_file is None:
self.set_pane_contents(Gtk.Label("No GUI controls"))
else:
@ -128,7 +131,7 @@ class ExplorerWindow(Window):
store, selected = self.explist_tree.get_selection().get_selected()
if selected is not None:
name = store[selected][0]
data = self.explist_syncer.data[name]
data = self.explist_data[name]
if self.controls is None:
arguments = {}
else:

View File

@ -59,21 +59,13 @@ class ParametersWindow(Window):
@asyncio.coroutine
def sub_connect(self, host, port):
self.parameters_subscriber = Subscriber("parameters",
self.init_parameters_store)
yield from self.parameters_subscriber.connect(host, port)
try:
self.lastchanges_subscriber = Subscriber(
"parameters_simplehist", self.init_lastchanges_store)
yield from self.lastchanges_subscriber.connect(host, port)
except:
yield from self.parameters_subscriber.close()
raise
self.lastchanges_subscriber = Subscriber(
"parameters_simplehist", self.init_lastchanges_store)
yield from self.lastchanges_subscriber.connect(host, port)
@asyncio.coroutine
def sub_close(self):
yield from self.lastchanges_subscriber.close()
yield from self.parameters_subscriber.close()
def init_parameters_store(self, init):
return _ParameterStoreSyncer(self.parameters_store, init)

View File

@ -79,9 +79,7 @@ class ListSyncer:
class DictSyncer:
def __init__(self, store, init, keep_data=False):
if keep_data:
self.data = init
def __init__(self, store, init):
self.store = store
self.store.clear()
self.order = []
@ -115,8 +113,6 @@ class DictSyncer:
self.order.insert(j, (key, ord_el))
def __delitem__(self, key):
if hasattr(self, "data"):
del self.data[key]
i = self._find_index(key)
del self.store[i]
del self.order[i]

View File

@ -49,13 +49,18 @@ class Subscriber:
:param target_builder: A function called during initialization that takes
the object received from the publisher and returns the corresponding
local structure to use. Can be identity.
Multiple functions can be specified in a list for the ``Subscriber``
to update several local objects simultaneously.
:param notify_cb: An optional function called every time a mod is received
from the publisher. The mod is passed as parameter.
"""
def __init__(self, notifier_name, target_builder, notify_cb=None):
self.notifier_name = notifier_name
self.target_builder = target_builder
if isinstance(target_builder, list):
self.target_builders = target_builder
else:
self.target_builders = [target_builder]
self.notify_cb = notify_cb
@asyncio.coroutine
@ -87,7 +92,7 @@ class Subscriber:
@asyncio.coroutine
def _receive_cr(self):
target = None
targets = []
while True:
line = yield from self._reader.readline()
if not line:
@ -95,9 +100,10 @@ class Subscriber:
mod = pyon.decode(line.decode())
if mod["action"] == "init":
target = self.target_builder(mod["struct"])
targets = [tb(mod["struct"]) for tb in self.target_builders]
else:
process_mod(target, mod)
for target in targets:
process_mod(target, mod)
if self.notify_cb is not None:
self.notify_cb(mod)