artiq/artiq/gui/models.py

183 lines
5.6 KiB
Python
Raw Normal View History

2015-05-22 17:05:15 +08:00
from quamash import QtCore
2015-11-11 12:13:19 +08:00
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)
2015-07-22 05:13:46 +08:00
class _SyncSubstruct:
2015-05-17 16:11:00 +08:00
def __init__(self, update_cb, ref):
self.update_cb = update_cb
self.ref = ref
def append(self, x):
self.ref.append(x)
self.update_cb()
def insert(self, i, x):
self.ref.insert(i, x)
self.update_cb()
def pop(self, i=-1):
self.ref.pop(i)
self.update_cb()
2015-05-17 16:11:00 +08:00
def __setitem__(self, key, value):
self.ref[key] = value
self.update_cb()
def __delitem__(self, key):
self.ref.__delitem__(key)
self.update_cb()
def __getitem__(self, key):
2015-07-22 05:13:46 +08:00
return _SyncSubstruct(self.update_cb, self.ref[key])
2015-05-17 16:11:00 +08:00
2015-05-22 17:05:15 +08:00
class DictSyncModel(QtCore.QAbstractTableModel):
2015-11-11 12:13:19 +08:00
def __init__(self, headers, init):
2015-05-22 17:05:15 +08:00
self.headers = headers
self.backing_store = init
self.row_to_key = sorted(self.backing_store.keys(),
key=lambda k: self.sort_key(k, self.backing_store[k]))
2015-11-11 12:13:19 +08:00
QtCore.QAbstractTableModel.__init__(self)
2015-05-22 17:05:15 +08:00
def rowCount(self, parent):
return len(self.backing_store)
2015-05-22 17:05:15 +08:00
def columnCount(self, parent):
return len(self.headers)
def data(self, index, role):
2015-11-11 12:13:19 +08:00
if not index.isValid() or role != QtCore.Qt.DisplayRole:
2015-05-22 17:05:15 +08:00
return None
2015-11-11 12:13:19 +08:00
else:
k = self.row_to_key[index.row()]
return self.convert(k, self.backing_store[k], index.column())
2015-05-22 17:05:15 +08:00
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.backing_store[self.row_to_key[mid]])
2015-05-22 17:05:15 +08:00
< self.sort_key(k, v)):
lo = mid + 1
else:
hi = mid
return lo
def __setitem__(self, k, v):
if k in self.backing_store:
2015-05-22 17:05:15 +08:00
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)-1))
2015-05-22 17:05:15 +08:00
else:
self.beginMoveRows(QtCore.QModelIndex(), old_row, old_row,
QtCore.QModelIndex(), new_row)
self.backing_store[k] = v
2015-05-22 17:05:15 +08:00
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()
2015-01-02 22:09:02 +08:00
else:
2015-05-22 17:05:15 +08:00
row = self._find_row(k, v)
self.beginInsertRows(QtCore.QModelIndex(), row, row)
self.backing_store[k] = v
2015-05-22 17:05:15 +08:00
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.backing_store[k]
2015-05-22 17:05:15 +08:00
self.endRemoveRows()
2015-05-17 16:11:00 +08:00
2015-07-22 05:13:46 +08:00
def __getitem__(self, k):
2015-05-17 16:11:00 +08:00
def update():
2015-07-22 05:13:46 +08:00
self[k] = self.backing_store[k]
return _SyncSubstruct(update, self.backing_store[k])
2015-01-02 22:09:02 +08:00
2015-05-22 17:05:15 +08:00
def sort_key(self, k, v):
2015-01-02 22:09:02 +08:00
raise NotImplementedError
2015-05-22 17:05:15 +08:00
def convert(self, k, v, column):
2015-01-02 22:09:02 +08:00
raise NotImplementedError
2015-07-22 05:13:46 +08:00
class ListSyncModel(QtCore.QAbstractTableModel):
2015-11-11 12:13:19 +08:00
def __init__(self, headers, init):
2015-07-22 05:13:46 +08:00
self.headers = headers
self.backing_store = init
2015-11-11 12:13:19 +08:00
QtCore.QAbstractTableModel.__init__(self)
2015-07-22 05:13:46 +08:00
def rowCount(self, parent):
return len(self.backing_store)
def columnCount(self, parent):
return len(self.headers)
def data(self, index, role):
2015-11-11 12:13:19 +08:00
if not index.isValid() or role != QtCore.Qt.DisplayRole:
2015-07-22 05:13:46 +08:00
return None
2015-11-11 12:13:19 +08:00
else:
return self.convert(self.backing_store[index.row()],
index.column())
2015-07-22 05:13:46 +08:00
def headerData(self, col, orientation, role):
if (orientation == QtCore.Qt.Horizontal
and role == QtCore.Qt.DisplayRole):
return self.headers[col]
return None
def __setitem__(self, k, v):
self.dataChanged.emit(self.index(k, 0),
self.index(k, len(self.headers)-1))
2015-07-22 05:13:46 +08:00
self.backing_store[k] = v
def __delitem__(self, k):
self.beginRemoveRows(QtCore.QModelIndex(), k, k)
del self.backing_store[k]
self.endRemoveRows()
def __getitem__(self, k):
def update():
self[k] = self.backing_store[k]
return _SyncSubstruct(update, self.backing_store[k])
def append(self, v):
row = len(self.backing_store)
self.beginInsertRows(QtCore.QModelIndex(), row, row)
self.backing_store.append(v)
self.endInsertRows()
def convert(self, v, column):
raise NotImplementedError