From b870d23f135f8f2aa85b207c766bef847499bc28 Mon Sep 17 00:00:00 2001 From: Simon Renblad Date: Wed, 17 Jan 2024 15:50:12 +0800 Subject: [PATCH] waveform: attempting a MVC approach to the waveformarea --- artiq/dashboard/waveform.py | 127 ++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/artiq/dashboard/waveform.py b/artiq/dashboard/waveform.py index be23fc931..24cc0e3bd 100644 --- a/artiq/dashboard/waveform.py +++ b/artiq/dashboard/waveform.py @@ -428,6 +428,133 @@ class AnalogWaveform(Waveform): self.cursor_label.setText(lbl) +class _WaveformView(QtWidgets.QWidget): + def __init__(self, parent): + QtWidgets.QWidget.__init__(self, parent=parent) + + layout = QtWidgets.QVBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + self.setLayout(layout) + + self._ref_axis = pg.PlotWidget() + self._ref_axis.hideAxis("bottom") + self._ref_axis.hideAxis("left") + self._ref_axis.hideButtons() + self._ref_axis.setFixedHeight(45) + self._ref_axis.setMenuEnabled(False) + self._top = pg.AxisItem("top") + self._top.setScale(1e-12) + self._top.setLabel(units="s") + self._ref_axis.setAxisItems({"top": self._top}) + layout.addWidget(self._ref_axis) + + self._ref_vb = self._ref_axis.getPlotItem().getViewBox() + self._ref_vb.setFixedHeight(0) + self._ref_vb.setMouseEnabled(x=True, y=False) + self._ref_vb.setLimits(xMin=0) + + scroll_area = VDragScrollArea(self) + scroll_area.setWidgetResizable(True) + scroll_area.setContentsMargins(0, 0, 0, 0) + scroll_area.setFrameShape(QtWidgets.QFrame.NoFrame) + layout.addWidget(scroll_area) + + self._splitter = VDragDropSplitter(parent=scroll_area) + self._splitter.setHandleWidth(1) + scroll_area.setWidget(self._splitter) + + def setModel(self, model): + self._model = model + self._model.dataChanged.connect(self.onDataChanged) + self._model.rowsInserted.connect(self.onInsert) + self._model.rowsRemoved.connect(self.onRemove) + self._model.rowsMoved.connect(self.onMove) + + def onDataChange(self, top, bottom, roles): + first = top.row() + last = bottom.row() + for i in range(first, last + 1): + data = self._model.data(self._model.index(i, 2)) + self._splitter.widget(i).onDataChange(data) + + def onInsert(self, parent, first, last): + for i in range(first, last + 1): + w = self._create_waveform(self.index(i, 0)) + self.splitter.insertWidget(i, w) + self._resize() + + def onRemove(self, parent, first, last): + for i in reversed(range(first, last + 1)): + w = self.splitter.widget(i) + w.deleteLater() + self.splitter.refresh() + self._resize() + + def onMove(self, src_parent, src_start, src_end, dest_parent, dest_row): + w = self.splitter.widget(src_start) + self.splitter.insertWidget(dest_row, w) + + def _create_waveform(self, row): + name = self._model.data(self.index(row, 0)) + ty = self._model.data(self.index(row, 1)) + width = self._model.data(self.index(row, 2)) + waveform_cls = { + WaveformType.BIT: BitWaveform, + WaveformType.VECTOR: BitVectorWaveform, + WaveformType.ANALOG: AnalogWaveform, + WaveformType.LOG: LogWaveform + }[ty] + return waveform_cls(name, width) + + def _resize(self): + self._splitter.setMinimumHeight(Waveform.MIN_HEIGHT * self._model.rowCount()) + self._splitter.setMaximumHeight(Waveform.MAX_HEIGHT * self._model.rowCount()) + + +class _WaveformModel(QtWidgets.QAbstractTableModel): + def __init__(self): + self.backing_struct = [] + self.headers = ["name", "type", "width", "data"] + QtWidgets.QAbstractTableModel.__init__(self) + + def rowCount(self): + return len(self.backing_struct) + + def columnCount(self): + return len(self.headers) + + def data(self, index, role=QtCore.Qt.DisplayRole): + if index.isValid(): + return self.backing_struct[index.row()][index.col()] + return None + + def extend(self, data): + l = len(self.backing_struct) + l_data = len(data) + self.beginInsertRows(QtCore.QModelIndex(), l, l + l_data - 1) + self.backing_struct.extend(data) + self.endInsertRows() + + def pop(self, row): + self.beginRemoveRows(QtCore.QModelIndex(), row, row) + self.backing_struct.pop(row) + self.endRemoveRows() + + def move(self, src, dest): + self.beginMoveRows(QtCore.QModelIndex(), src, src, QtCore.QModelIndex(), dest) + self.backing_struct.insert(dest, self.backing_struct.pop(src)) + self.endMoveRows() + + def update_data(self, waveform_data): + for i in range(len(self.backing_struct)): + name = self.data(self.index(i, 0)) + if name in waveform_data: + self.backing_struct[i][3] = waveform_data[name] + self.dataChanged.emit(self.index(0, 0), + self.index(len(self.backing_struct)-1, len(self.headers))) + + class WaveformArea(QtWidgets.QWidget): cursorMoved = QtCore.pyqtSignal(float)