Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4a7a4acf074f
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a64766a10d58
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on Aug 1, 2015

  1. gui: add state manager

    sbourdeauducq committed Aug 1, 2015
    Copy the full SHA
    9e24b56 View commit details
  2. Copy the full SHA
    00cae1c View commit details
  3. Copy the full SHA
    a64766a View commit details
Showing with 74 additions and 14 deletions.
  1. +9 −5 artiq/frontend/artiq_gui.py
  2. +63 −0 artiq/gui/state.py
  3. +2 −9 artiq/protocols/file_db.py
14 changes: 9 additions & 5 deletions artiq/frontend/artiq_gui.py
Original file line number Diff line number Diff line change
@@ -10,8 +10,8 @@
from quamash import QEventLoop, QtGui
from pyqtgraph import dockarea

from artiq.protocols.file_db import FlatFileDB
from artiq.protocols.pc_rpc import AsyncioClient
from artiq.gui.state import StateManager
from artiq.gui.explorer import ExplorerDock
from artiq.gui.moninj import MonInj
from artiq.gui.results import ResultsDock
@@ -53,23 +53,24 @@ def __init__(self, app):
def closeEvent(self, *args):
self.exit_request.set()

def main():
args = get_argparser().parse_args()

db = FlatFileDB(args.db_file, default_data=dict())

def main():
app = QtGui.QApplication([])
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
atexit.register(lambda: loop.close())

args = get_argparser().parse_args()
smgr = StateManager(args.db_file)

schedule_ctl = AsyncioClient()
loop.run_until_complete(schedule_ctl.connect_rpc(
args.server, args.port_control, "master_schedule"))
atexit.register(lambda: schedule_ctl.close_rpc())

win = _MainWindow(app)
area = dockarea.DockArea()
smgr.register(area)
win.setCentralWidget(area)
status_bar = QtGui.QStatusBar()
status_bar.showMessage("Connected to {}".format(args.server))
@@ -125,6 +126,9 @@ def _get_parameter(k, v):
area.addDock(d_log, "above", d_console)
area.addDock(d_schedule, "above", d_log)

smgr.load()
smgr.start()
atexit.register(lambda: loop.run_until_complete(smgr.stop()))
win.show()
loop.run_until_complete(win.exit_request.wait())

63 changes: 63 additions & 0 deletions artiq/gui/state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import asyncio
from collections import OrderedDict

from artiq.tools import TaskObject
from artiq.protocols import pyon


# support Qt CamelCase naming scheme for save/restore state
def _save_state(obj):
method = getattr(obj, "save_state", None)
if method is None:
method = obj.saveState
return method()


def _restore_state(obj, state):
method = getattr(obj, "restore_state", None)
if method is None:
method = obj.restoreState
method(state)


class StateManager(TaskObject):
def __init__(self, filename, autosave_period=30):
self.filename = filename
self.autosave_period = autosave_period
self.stateful_objects = OrderedDict()

def register(self, obj, name=None):
if name is None:
name = obj.__class__.__name__
if name in self.stateful_objects:
raise RuntimeError("Name '{}' already exists in state"
.format(name))
self.stateful_objects[name] = obj

def load(self):
try:
data = pyon.load_file(self.filename)
except FileNotFoundError:
return
# The state of one object may depend on the state of another,
# e.g. the display state may create docks that are referenced in
# the area state.
# To help address this problem, state is restored in the opposite
# order as the stateful objects are registered.
for name, obj in reversed(list(self.stateful_objects.items())):
state = data.get(name, None)
if state is not None:
_restore_state(obj, state)

def save(self):
data = {k: _save_state(v) for k, v in self.stateful_objects.items()}
pyon.store_file(self.filename, data)

@asyncio.coroutine
def _do(self):
try:
while True:
yield from asyncio.sleep(self.autosave_period)
self.save()
finally:
self.save()
11 changes: 2 additions & 9 deletions artiq/protocols/file_db.py
Original file line number Diff line number Diff line change
@@ -5,16 +5,9 @@


class FlatFileDB:
def __init__(self, filename, default_data=None):
def __init__(self, filename):
self.filename = filename
try:
data = pyon.load_file(self.filename)
except FileNotFoundError:
if default_data is None:
raise
else:
data = default_data
self.data = Notifier(data)
self.data = Notifier(pyon.load_file(self.filename))
self.hooks = []

def save(self):