-
Notifications
You must be signed in to change notification settings - Fork 201
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1 parent
c91cd0a
commit ea53ed1
Showing
15 changed files
with
198 additions
and
794 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,47 @@ | ||
import asyncio | ||
from operator import itemgetter | ||
import time | ||
|
||
from gi.repository import Gtk | ||
from quamash import QtGui | ||
from pyqtgraph.dockarea import Dock | ||
|
||
from artiq.gui.tools import Window, ListSyncer, DictSyncer | ||
from artiq.protocols.sync_struct import Subscriber | ||
from artiq.gui.tools import DictSyncModel | ||
|
||
|
||
class _ParameterStoreSyncer(DictSyncer): | ||
def order_key(self, kv_pair): | ||
return kv_pair[0] | ||
class ParametersModel(DictSyncModel): | ||
def __init__(self, parent, init): | ||
DictSyncModel.__init__(self, ["Parameter", "Value"], | ||
parent, init) | ||
|
||
def convert(self, name, value): | ||
return [name, str(value)] | ||
def sort_key(self, k, v): | ||
return k | ||
|
||
|
||
class _LastChangesStoreSyncer(ListSyncer): | ||
def convert(self, x): | ||
if len(x) == 3: | ||
timestamp, name, value = x | ||
def convert(self, k, v, column): | ||
if column == 0: | ||
return k | ||
elif column == 1: | ||
return str(v) | ||
else: | ||
timestamp, name = x | ||
value = "<deleted>" | ||
return [time.strftime("%m/%d %H:%M:%S", time.localtime(timestamp)), | ||
name, str(value)] | ||
|
||
raise ValueError | ||
|
||
class ParametersWindow(Window): | ||
def __init__(self, **kwargs): | ||
Window.__init__(self, | ||
title="Parameters", | ||
default_size=(500, 500), | ||
**kwargs) | ||
|
||
notebook = Gtk.Notebook() | ||
self.add(notebook) | ||
class ParametersDock(Dock): | ||
def __init__(self, parent): | ||
Dock.__init__(self, "Parameters", size=(500, 300)) | ||
|
||
self.parameters_store = Gtk.ListStore(str, str) | ||
tree = Gtk.TreeView(self.parameters_store) | ||
for i, title in enumerate(["Parameter", "Value"]): | ||
renderer = Gtk.CellRendererText() | ||
column = Gtk.TreeViewColumn(title, renderer, text=i) | ||
tree.append_column(column) | ||
scroll = Gtk.ScrolledWindow() | ||
scroll.add(tree) | ||
notebook.insert_page(scroll, Gtk.Label("Current values"), -1) | ||
|
||
self.lastchanges_store = Gtk.ListStore(str, str, str) | ||
tree = Gtk.TreeView(self.lastchanges_store) | ||
for i, title in enumerate(["Time", "Parameter", "Value"]): | ||
renderer = Gtk.CellRendererText() | ||
column = Gtk.TreeViewColumn(title, renderer, text=i) | ||
tree.append_column(column) | ||
scroll = Gtk.ScrolledWindow() | ||
scroll.add(tree) | ||
notebook.insert_page(scroll, Gtk.Label("Last changes"), -1) | ||
self.table = QtGui.QTableView() | ||
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) | ||
self.addWidget(self.table) | ||
|
||
@asyncio.coroutine | ||
def sub_connect(self, host, port): | ||
self.lastchanges_subscriber = Subscriber( | ||
"parameters_simplehist", self.init_lastchanges_store) | ||
yield from self.lastchanges_subscriber.connect(host, port) | ||
self.subscriber = Subscriber("parameters", self.init_parameters_model) | ||
yield from self.subscriber.connect(host, port) | ||
|
||
@asyncio.coroutine | ||
def sub_close(self): | ||
yield from self.lastchanges_subscriber.close() | ||
|
||
def init_parameters_store(self, init): | ||
return _ParameterStoreSyncer(self.parameters_store, init) | ||
yield from self.subscriber.close() | ||
|
||
def init_lastchanges_store(self, init): | ||
return _LastChangesStoreSyncer(self.lastchanges_store, init) | ||
def init_parameters_model(self, init): | ||
table_model = ParametersModel(self.table, init) | ||
self.table.setModel(table_model) | ||
return table_model |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import asyncio | ||
import time | ||
|
||
from quamash import QtGui | ||
from pyqtgraph.dockarea import Dock | ||
|
||
from artiq.protocols.sync_struct import Subscriber | ||
from artiq.gui.tools import DictSyncModel | ||
from artiq.tools import format_arguments | ||
|
||
|
||
class _ScheduleModel(DictSyncModel): | ||
def __init__(self, parent, init): | ||
DictSyncModel.__init__(self, | ||
["RID", "Pipeline", "Status", "Due date", | ||
"File", "Experiment", "Arguments"], | ||
parent, init) | ||
|
||
def sort_key(self, k, v): | ||
# order by due date, and then by RID | ||
return (v["due_date"] or 0, k) | ||
|
||
def convert(self, k, v, column): | ||
if column == 0: | ||
return k | ||
elif column == 1: | ||
return v["pipeline"] | ||
elif column == 2: | ||
return v["status"] | ||
elif column == 3: | ||
if v["due_date"] is None: | ||
return "" | ||
else: | ||
return time.strftime("%m/%d %H:%M:%S", | ||
time.localtime(v["due_date"])) | ||
elif column == 4: | ||
return v["expid"]["file"] | ||
elif column == 5: | ||
if v["expid"]["experiment"] is None: | ||
return "" | ||
else: | ||
return v["expid"]["experiment"] | ||
elif column == 6: | ||
return format_arguments(v["expid"]["arguments"]) | ||
else: | ||
raise ValueError | ||
|
||
|
||
class ScheduleDock(Dock): | ||
def __init__(self, parent): | ||
Dock.__init__(self, "Schedule", size=(1000, 300)) | ||
|
||
self.table = QtGui.QTableView() | ||
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) | ||
self.addWidget(self.table) | ||
|
||
@asyncio.coroutine | ||
def sub_connect(self, host, port): | ||
self.subscriber = Subscriber("schedule", self.init_schedule_model) | ||
yield from self.subscriber.connect(host, port) | ||
|
||
@asyncio.coroutine | ||
def sub_close(self): | ||
yield from self.subscriber.close() | ||
|
||
def init_schedule_model(self, init): | ||
table_model = _ScheduleModel(self.table, init) | ||
self.table.setModel(table_model) | ||
return table_model |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,143 +1,96 @@ | ||
import os | ||
from quamash import QtCore | ||
|
||
from gi.repository import Gtk | ||
|
||
|
||
data_dir = os.path.abspath(os.path.dirname(__file__)) | ||
|
||
|
||
def getitem(d, item, default): | ||
try: | ||
return d[item] | ||
except KeyError: | ||
return default | ||
|
||
|
||
class Window(Gtk.Window): | ||
def __init__(self, title, default_size, layout_dict=dict()): | ||
Gtk.Window.__init__(self, title=title + " - ARTIQ") | ||
|
||
self.set_wmclass("ARTIQ", "ARTIQ") | ||
self.set_icon_from_file(os.path.join(data_dir, "icon.png")) | ||
self.set_border_width(6) | ||
|
||
size = getitem(layout_dict, "size", default_size) | ||
self.set_default_size(size[0], size[1]) | ||
try: | ||
position = layout_dict["position"] | ||
except KeyError: | ||
pass | ||
else: | ||
self.move(position[0], position[1]) | ||
|
||
def get_layout_dict(self): | ||
return { | ||
"size": self.get_size(), | ||
"position": self.get_position() | ||
} | ||
|
||
|
||
class LayoutManager: | ||
def __init__(self, db): | ||
self.db = db | ||
self.windows = dict() | ||
|
||
def create_window(self, cls, name, *args, **kwargs): | ||
try: | ||
win_layouts = self.db.request("win_layouts") | ||
layout_dict = win_layouts[name] | ||
except KeyError: | ||
layout_dict = dict() | ||
win = cls(*args, layout_dict=layout_dict, **kwargs) | ||
self.windows[name] = win | ||
return win | ||
|
||
def save(self): | ||
win_layouts = {name: window.get_layout_dict() | ||
for name, window in self.windows.items()} | ||
self.db.set("win_layouts", win_layouts) | ||
|
||
|
||
class ListSyncer: | ||
def __init__(self, store, init): | ||
self.store = store | ||
self.store.clear() | ||
for x in init: | ||
self.append(x) | ||
|
||
def append(self, x): | ||
self.store.append(self.convert(x)) | ||
|
||
def insert(self, i, x): | ||
self.store.insert(i, self.convert(x)) | ||
|
||
def __delitem__(self, key): | ||
del self.store[key] | ||
|
||
def convert(self, x): | ||
raise NotImplementedError | ||
|
||
|
||
class _DictSyncerSubstruct: | ||
class _DictSyncSubstruct: | ||
def __init__(self, update_cb, ref): | ||
self.update_cb = update_cb | ||
self.ref = ref | ||
|
||
def __getitem__(self, key): | ||
return _DictSyncerSubstruct(self.update_cb, self.ref[key]) | ||
return _DictSyncSubstruct(self.update_cb, self.ref[key]) | ||
|
||
def __setitem__(self, key, value): | ||
self.ref[key] = value | ||
self.update_cb() | ||
|
||
|
||
class DictSyncer: | ||
def __init__(self, store, init): | ||
self.store = store | ||
self.store.clear() | ||
self.order = [] | ||
for k, v in sorted(init.items(), key=self.order_key): | ||
self.store.append(self.convert(k, v)) | ||
self.order.append((k, self.order_key((k, v)))) | ||
self.local_copy = init | ||
|
||
def _find_index(self, key): | ||
for i, e in enumerate(self.order): | ||
if e[0] == key: | ||
return i | ||
raise KeyError | ||
|
||
def __setitem__(self, key, value): | ||
try: | ||
i = self._find_index(key) | ||
except KeyError: | ||
pass | ||
class DictSyncModel(QtCore.QAbstractTableModel): | ||
def __init__(self, headers, parent, init): | ||
self.headers = headers | ||
self.data = init | ||
self.row_to_key = sorted(self.data.keys(), | ||
key=lambda k: self.sort_key(k, self.data[k])) | ||
QtCore.QAbstractTableModel.__init__(self, parent) | ||
|
||
def rowCount(self, parent): | ||
return len(self.data) | ||
|
||
def columnCount(self, parent): | ||
return len(self.headers) | ||
|
||
def data(self, index, role): | ||
if not index.isValid(): | ||
return None | ||
elif role != QtCore.Qt.DisplayRole: | ||
return None | ||
k = self.row_to_key[index.row()] | ||
return self.convert(k, self.data[k], index.column()) | ||
|
||
def headerData(self, col, orientation, role): | ||
if (orientation == QtCore.Qt.Horizontal | ||
and role == QtCore.Qt.DisplayRole): | ||
return self.headers[col] | ||
return None | ||
|
||
def _find_row(self, k, v): | ||
lo = 0 | ||
hi = len(self.row_to_key) | ||
while lo < hi: | ||
mid = (lo + hi)//2 | ||
if (self.sort_key(self.row_to_key[mid], | ||
self.data[self.row_to_key[mid]]) | ||
< self.sort_key(k, v)): | ||
lo = mid + 1 | ||
else: | ||
hi = mid | ||
return lo | ||
|
||
def __setitem__(self, k, v): | ||
if k in self.data: | ||
old_row = self.row_to_key.index(k) | ||
new_row = self._find_row(k, v) | ||
if old_row == new_row: | ||
self.dataChanged.emit(self.index(old_row, 0), | ||
self.index(old_row, len(self.headers))) | ||
else: | ||
self.beginMoveRows(QtCore.QModelIndex(), old_row, old_row, | ||
QtCore.QModelIndex(), new_row) | ||
self.data[k] = v | ||
self.row_to_key[old_row], self.row_to_key[new_row] = \ | ||
self.row_to_key[new_row], self.row_to_key[old_row] | ||
if old_row != new_row: | ||
self.endMoveRows() | ||
else: | ||
del self.store[i] | ||
del self.order[i] | ||
ord_el = self.order_key((key, value)) | ||
j = len(self.order) | ||
for i, (k, o) in enumerate(self.order): | ||
if o > ord_el: | ||
j = i | ||
break | ||
self.store.insert(j, self.convert(key, value)) | ||
self.order.insert(j, (key, ord_el)) | ||
self.local_copy[key] = value | ||
|
||
def __delitem__(self, key): | ||
i = self._find_index(key) | ||
del self.store[i] | ||
del self.order[i] | ||
del self.local_copy[key] | ||
row = self._find_row(k, v) | ||
self.beginInsertRows(QtCore.QModelIndex(), row, row) | ||
self.data[k] = v | ||
self.row_to_key.insert(row, k) | ||
self.endInsertRows() | ||
|
||
def __delitem__(self, k): | ||
row = self.row_to_key.index(k) | ||
self.beginRemoveRows(QtCore.QModelIndex(), row, row) | ||
del self.row_to_key[row] | ||
del self.data[k] | ||
self.endRemoveRows() | ||
|
||
def __getitem__(self, key): | ||
def update(): | ||
self[key] = self.local_copy[key] | ||
return _DictSyncerSubstruct(update, self.local_copy[key]) | ||
self[key] = self.data[key] | ||
return _DictSyncSubstruct(update, self.data[key]) | ||
|
||
def order_key(self, kv_pair): | ||
def sort_key(self, k, v): | ||
raise NotImplementedError | ||
|
||
def convert(self, key, value): | ||
def convert(self, k, v, column): | ||
raise NotImplementedError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 0 additions & 58 deletions
58
examples/master/repository/flopping_f_simulation_gui.glade
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters