示例#1
0
    def loadElements(self, rows):
        """
        elemplist - a list of (elem obj, field). *field=None* means separator.
        """
        self.beginResetModel()
        self.clear()
        for i, (elem, fld) in enumerate(rows):
            pvsp = elem.pv(field=fld, handle="setpoint")
            for j, pv in enumerate(pvsp):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i, C_VAL_SP, j))
            pvrb = elem.pv(field=fld, handle="readback")
            for j, pv in enumerate(pvrb):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i, C_VAL_RB, j))

            # one data record, pvs are all list
            rec = [elem, fld, [None] * len(pvsp), [None] * len(pvrb)]
            for j, s in enumerate(self._unitsys):
                rec.append([None] * len(pvrb))
            self._data.append(tuple(rec))
            self._pvlst.append(pvsp + pvrb)

        self._block = [0]
        k = 0
        for i in range(1, len(rows)):
            elem, fld = rows[i]
            if elem != rows[i - 1][0]:
                k += 1
            self._block.append(k)

        self._cadata = CaDataMonitor(wait=0.0)
        for pv in self._pvidx.keys():
            #self._cadata.addHook(pv, self._ca_update)
            self._cadata.addHook(pv, self._ca_update)
        self._cadata.addPv(self._pvidx.keys())

        self.endResetModel()
        self._cadata.start()
示例#2
0
    def loadElements(self, rows):
        """
        elemplist - a list of (elem obj, field). *field=None* means separator.
        """
        self.beginResetModel()
        self.clear()
        for i, (elem, fld) in enumerate(rows):
            pvsp = elem.pv(field=fld, handle="setpoint")
            for j,pv in enumerate(pvsp):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i,C_VAL_SP,j))
            pvrb = elem.pv(field=fld, handle="readback")
            for j,pv in enumerate(pvrb):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i,C_VAL_RB,j))

            # one data record, pvs are all list
            rec = [elem, fld, [None] * len(pvsp), [None] * len(pvrb)]
            for j,s in enumerate(self._unitsys):
                rec.append([None] * len(pvrb))
            self._data.append(tuple(rec))
            self._pvlst.append(pvsp + pvrb)

        self._block = [0]
        k = 0
        for i in range(1, len(rows)):
            elem, fld = rows[i]
            if elem != rows[i-1][0]:
                k += 1
            self._block.append(k)

        self._cadata = CaDataMonitor(wait=0.0)
        for pv in self._pvidx.keys():
            #self._cadata.addHook(pv, self._ca_update)
            self._cadata.addHook(pv, self._ca_update)
        self._cadata.addPv(self._pvidx.keys())

        self.endResetModel()
        self._cadata.start()
示例#3
0
class ElementPropertyTableModel(QAbstractTableModel):
    def __init__(self, **kwargs):
        super(ElementPropertyTableModel, self).__init__()
        # elem obj, idx, name/fld
        self._unitsys = ['phy']
        self._unitsymb = []
        self._data = []
        self._block = []  # block of fields for one element
        self._inactive = []
        self._pvidx = {}  # map pv to row,column,idx
        self._pvlst = []  # map row to pv list
        self._cadata = None
        self._t0 = datetime.now()

    def clear(self):
        if self._cadata: self._cadata.close()
        idx0 = self.index(0, 0)
        idx1 = self.index(len(self._data) - 1, self.columnCount() - 1)
        self._data = []
        self._pvidx = {}
        self._pvlst = []
        self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), idx0, idx1)

    def loadElements(self, rows):
        """
        elemplist - a list of (elem obj, field). *field=None* means separator.
        """
        self.beginResetModel()
        self.clear()
        for i, (elem, fld) in enumerate(rows):
            pvsp = elem.pv(field=fld, handle="setpoint")
            for j, pv in enumerate(pvsp):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i, C_VAL_SP, j))
            pvrb = elem.pv(field=fld, handle="readback")
            for j, pv in enumerate(pvrb):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i, C_VAL_RB, j))

            # one data record, pvs are all list
            rec = [elem, fld, [None] * len(pvsp), [None] * len(pvrb)]
            for j, s in enumerate(self._unitsys):
                rec.append([None] * len(pvrb))
            self._data.append(tuple(rec))
            self._pvlst.append(pvsp + pvrb)

        self._block = [0]
        k = 0
        for i in range(1, len(rows)):
            elem, fld = rows[i]
            if elem != rows[i - 1][0]:
                k += 1
            self._block.append(k)

        self._cadata = CaDataMonitor(wait=0.0)
        for pv in self._pvidx.keys():
            #self._cadata.addHook(pv, self._ca_update)
            self._cadata.addHook(pv, self._ca_update)
        self._cadata.addPv(self._pvidx.keys())

        self.endResetModel()
        self._cadata.start()

    def _ca_update(self, val, idx=None):
        #print val.name, val
        for i, j, k in self._pvidx[val.name]:
            self._data[i][j][k] = val
        t1 = datetime.now()
        if (t1 - self._t0).total_seconds() > 1:
            idx0 = self.index(0, C_VAL_SP)
            idx1 = self.index(len(self._data) - 1, self.columnCount() - 1)
            self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), idx0,
                      idx1)
            self._t0 = datetime.now()

    def getElementField(self, row):
        return self._data[row][:2]

    def checkDeadPvs(self):
        if len(self._deadpvs) == 0: return
        pvs = list(self._deadpvs)
        vals = aphla.catools.caget(pvs, timeout=2)
        for i, val in enumerate(vals):
            if val.ok: self._deadpvs.remove(pvs[i])

    def updateData(self, row0, row1):
        pvs = reduce(lambda a, b: a + b,
                     [self._pvlst[i] for i in range(row0, row1)])
        pvs = [pv for pv in pvs if pv not in self._deadpvs]
        vals = aphla.catools.caget(pvs)
        for ipv, pv in enumerate(pvs):
            if not vals[ipv].ok:
                self._deadpvs.add(pv)
                continue
            for i, j, k in self._pvidx[pv]:
                self._data[i][j][k] = vals[ipv]
                if j == C_VAL_RB:
                    elem, fld = self._data[i][:2]
                    for isys, usys in enumerate(self._unitsys):
                        if usys not in elem.getUnitSystems(field=fld):
                            self._data[i][j + isys + 1][k] = ''
                            continue
                        self._data[i][j+isys+1][k] = \
                            elem.convertUnit(fld, val, None, usys)
        print("Updated")
        idx0 = self.index(row0, C_VAL_SP)
        idx1 = self.index(row1 - 1, self.columnCount() - 1)
        self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), idx0, idx1)
        #QtGui.qApp.processEvents()

    def _cadata_to_qv(self, vals):
        """
        this is cadata, it is a list even for scalar
        """
        # assume it is a cadata, must be a list
        if len(vals) == 0:
            return QVariant()
        elif len(vals) > 1:
            return QVariant("...")

        # size 1
        val = vals[0]
        if val is None:
            return QVariant()
        elif isinstance(val, (float, np.float32)):
            return QVariant(float(val))
        elif isinstance(val, str):
            return QVariant(QString(val))
        elif isinstance(val, int):
            return QVariant(int(val))
        elif isinstance(val, (list, tuple)):
            return [self._cadata_to_qvariant(v) for v in val]
        elif isinstance(val, cothread.dbr.ca_array):
            return [self._cadata_to_qvariant(v) for v in val]
        elif not val.ok:
            return QVariant(QString("Disconnected"))
        else:
            raise RuntimeError("Unknow data type: {0} ({1})".format(
                type(val), val))

    def isSubHeader(self, i):
        return self._data[i][1] is None

    def data(self, index, role=Qt.DisplayRole):
        """return data as a QVariant"""
        #print "data model=",role
        if not index.isValid() or index.row() >= len(self._data):
            return QVariant()

        r, col = index.row(), index.column()
        elem, fld = self._data[r][:2]
        if role == Qt.DisplayRole:
            #if r == 0: print r, col, elem.name, fld, self._data[r][col], "//"
            if col == C_ELEM:
                return QVariant(QString(elem.name))
            elif col == C_FIELD:
                return QVariant(QString(fld))
            elif col == C_VAL_SP or col == C_VAL_RB:
                return self._cadata_to_qv(self._data[r][col])
            # other unit system
            unitsys = self._unitsys[col - C_VAL_RB - 1]
            try:
                vals = elem.convertUnit(fld, self._data[r][C_VAL_RB], None,
                                        unitsys)
                return self._cadata_to_qv(vals)
            except:
                return QVariant()
        #elif role == Qt.EditRole:
        #    if col == C_FIELD:
        #        raise RuntimeError("what is this ?")
        #        return QVariant(self._field[r]+self._fieldpfx[r])
        #    #print r, col, self._field[r], self._value[r]
        #    if vals is None: return QVariant()
        #    if isinstance(vals[col-1], (tuple, list)):
        #        return QVariant.fromList([QVariant(v) for v in vals[col-1]])
        #    elif vals[col-1] is not None:
        #        return QVariant(vals[col-1])
        elif role == Qt.TextAlignmentRole:
            if col == C_FIELD: return QVariant(Qt.AlignLeft | Qt.AlignVCenter)
            else: return QVariant(Qt.AlignRight | Qt.AlignBottom)
        elif role == Qt.ToolTipRole:
            if col == C_ELEM or col == C_FIELD:
                return QVariant("{0}, sb={1}, L={2}".format(
                    elem.family, elem.sb, elem.length))
            elif col == C_VAL_SP:
                pv = elem.pv(field=fld, handle="setpoint")
                return QVariant(", ".join(pv))
            elif col == C_VAL_RB:
                pv = elem.pv(field=fld, handle="readback")
                return QVariant(", ".join(pv))
            elif col > C_VAL_RB:
                unitsys = self._unitsys[col - C_VAL_RB - 1]
                #print "Checking the unit:", unitsys, elem.getUnit(fld, unitsys)
                return QVariant(str(elem.getUnit(fld, unitsys)))
        elif role == Qt.ForegroundRole:
            #if idx == 0: return QColor(Qt.darkGray)
            #if r in self._inactive and self.isHeadIndex(r):
            #    return QColor(Qt.darkGray)
            #elif r in self._inactive:
            #    return QColor(Qt.lightGray)
            #else: return QColor(Qt.black)
            return QVariant()
        elif role == Qt.BackgroundRole:
            if self._block[r] % 2 == 0: return QVariant()
            else: return QColor(0xE0, 0xE0, 0xE0)
        elif role == Qt.CheckStateRole:
            #if vals is not None: return QVariant()
            #elif r in self._inactive: return Qt.Unchecked
            #else: return Qt.Checked
            #if idx == 0 and col == C_FIELD: return Qt.Checked
            return QVariant()
        else:
            return QVariant()
        #print "Asking data role=", role
        return QVariant()

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.TextAlignmentRole:
            if orientation == Qt.Horizontal:
                return QVariant(int(Qt.AlignLeft | Qt.AlignVCenter))
            return QVariant(int(Qt.AlignRight | Qt.AlignVCenter))
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            #print "Section:", section, C_VAL_RB
            if section == C_FIELD: return QVariant("Field")
            elif section == C_VAL_SP: return QVariant("Setpoint")
            elif section == C_VAL_RB: return QVariant("Readback")
            elif section > C_VAL_RB and section < C_VAL_RB + len(
                    self._unitsys):
                return QVariant(self._unitsys[section - 1 - C_VAL_RB])
            else:
                return QVariant()
        elif orientation == Qt.Vertical:
            #if self._value[section] is not None: return QVariant()
            #idx = [k for k in range(section+1) if self._value[k] is None]
            #return QVariant(len(idx))
            return QVariant(section)

        #return QVariant(int(section+1))
        return QVariant()

    def flags(self, index):
        #print "flags:",
        if not index.isValid():
            return Qt.ItemIsEnabled
        row, col = index.row(), index.column()
        elem, fld = self._data[row][:2]

        if col == C_VAL_SP and fld is not None:
            return Qt.ItemFlags(
                QAbstractTableModel.flags(self, index) | Qt.ItemIsSelectable)
            #return Qt.ItemFlags(QAbstractTableModel.flags(self, index) |
            #    Qt.ItemIsEditable)
        return Qt.ItemIsEnabled

    def rowCount(self, index=QModelIndex()):
        return len(self._data)

    def columnCount(self, index=QModelIndex()):
        return C_VAL_RB + len(self._unitsys) + 1

    def setElementActive(self, irow, active=True):
        rows = self._element_block(irow)
        if active:
            for i in rows:
                if i not in self._inactive: continue
                self._inactive.remove(i)
        else:
            for i in rows:
                if i in self._inactive: continue
                self._inactive.add(i)

    def isActive(self, irow):
        return irow not in self._inactive
示例#4
0
class ElementPropertyTableModel(QAbstractTableModel):
    def __init__(self, **kwargs):
        super(ElementPropertyTableModel, self).__init__()
        # elem obj, idx, name/fld
        self._unitsys  = ['phy']
        self._unitsymb = []
        self._data     = []
        self._block    = [] # block of fields for one element
        self._inactive = []
        self._pvidx = {} # map pv to row,column,idx
        self._pvlst = [] # map row to pv list
        self._cadata = None
        self._t0 = datetime.now()

    def clear(self):
        if self._cadata: self._cadata.close()
        idx0 = self.index(0, 0)
        idx1 = self.index(len(self._data) - 1, self.columnCount()-1)
        self._data   = []
        self._pvidx  = {}
        self._pvlst  = []
        self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
                  idx0, idx1)

    def loadElements(self, rows):
        """
        elemplist - a list of (elem obj, field). *field=None* means separator.
        """
        self.beginResetModel()
        self.clear()
        for i, (elem, fld) in enumerate(rows):
            pvsp = elem.pv(field=fld, handle="setpoint")
            for j,pv in enumerate(pvsp):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i,C_VAL_SP,j))
            pvrb = elem.pv(field=fld, handle="readback")
            for j,pv in enumerate(pvrb):
                self._pvidx.setdefault(pv, [])
                self._pvidx[pv].append((i,C_VAL_RB,j))

            # one data record, pvs are all list
            rec = [elem, fld, [None] * len(pvsp), [None] * len(pvrb)]
            for j,s in enumerate(self._unitsys):
                rec.append([None] * len(pvrb))
            self._data.append(tuple(rec))
            self._pvlst.append(pvsp + pvrb)

        self._block = [0]
        k = 0
        for i in range(1, len(rows)):
            elem, fld = rows[i]
            if elem != rows[i-1][0]:
                k += 1
            self._block.append(k)

        self._cadata = CaDataMonitor(wait=0.0)
        for pv in self._pvidx.keys():
            #self._cadata.addHook(pv, self._ca_update)
            self._cadata.addHook(pv, self._ca_update)
        self._cadata.addPv(self._pvidx.keys())

        self.endResetModel()
        self._cadata.start()

    def _ca_update(self, val, idx = None):
        #print val.name, val
        for i,j,k in self._pvidx[val.name]:
            self._data[i][j][k] = val
        t1 = datetime.now()
        if (t1-self._t0).total_seconds() > 1:
            idx0 = self.index(0, C_VAL_SP)
            idx1 = self.index(len(self._data)-1, self.columnCount()-1)
            self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
                      idx0, idx1)
            self._t0 = datetime.now()

    def getElementField(self, row):
        return self._data[row][:2]

    def checkDeadPvs(self):
        if len(self._deadpvs) == 0: return
        pvs = list(self._deadpvs)
        vals = aphla.catools.caget(pvs, timeout=2)
        for i,val in enumerate(vals):
            if val.ok: self._deadpvs.remove(pvs[i])

    def updateData(self, row0, row1):
        pvs = reduce(lambda a,b: a + b,
                     [self._pvlst[i] for i in range(row0, row1)])
        pvs = [pv for pv in pvs if pv not in self._deadpvs]
        vals = aphla.catools.caget(pvs)
        for ipv,pv in enumerate(pvs):
            if not vals[ipv].ok:
                self._deadpvs.add(pv)
                continue
            for i,j,k in self._pvidx[pv]:
                self._data[i][j][k] = vals[ipv]
                if j == C_VAL_RB:
                    elem, fld = self._data[i][:2]
                    for isys, usys in enumerate(self._unitsys):
                        if usys not in elem.getUnitSystems(field=fld):
                            self._data[i][j+isys+1][k] = ''
                            continue
                        self._data[i][j+isys+1][k] = \
                            elem.convertUnit(fld, val, None, usys)
        print "Updated"
        idx0 = self.index(row0, C_VAL_SP)
        idx1 = self.index(row1-1, self.columnCount()-1)
        self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
                  idx0, idx1)
        #QtGui.qApp.processEvents()

    def _cadata_to_qv(self, vals):
        """
        this is cadata, it is a list even for scalar
        """
        # assume it is a cadata, must be a list
        if len(vals) == 0:
            return QVariant()
        elif len(vals) > 1:
            return QVariant("...")

        # size 1
        val = vals[0]
        if val is None:
            return QVariant()
        elif isinstance(val, (float, np.float32)):
            return QVariant(float(val))
        elif isinstance(val, str):
            return QVariant(QString(val))
        elif isinstance(val, int):
            return QVariant(int(val))
        elif isinstance(val, (list, tuple)):
            return [self._cadata_to_qvariant(v) for v in val]
        elif isinstance(val, cothread.dbr.ca_array):
            return [self._cadata_to_qvariant(v) for v in val]
        elif not val.ok:
            return QVariant(QString("Disconnected"))
        else:
            raise RuntimeError("Unknow data type: {0} ({1})".format(
                    type(val), val))


    def isSubHeader(self, i):
        return self._data[i][1] is None

        
    def data(self, index, role=Qt.DisplayRole):
        """return data as a QVariant"""
        #print "data model=",role
        if not index.isValid() or index.row() >= len(self._data):
            return QVariant()

        r, col  = index.row(), index.column()
        elem, fld = self._data[r][:2]
        if role == Qt.DisplayRole:
            #if r == 0: print r, col, elem.name, fld, self._data[r][col], "//"
            if col == C_ELEM:
                return QVariant(QString(elem.name))
            elif col == C_FIELD:
                return QVariant(QString(fld))
            elif col == C_VAL_SP or col == C_VAL_RB:
                return self._cadata_to_qv(self._data[r][col])
            # other unit system
            unitsys = self._unitsys[col - C_VAL_RB - 1]
            try:
                vals = elem.convertUnit(fld, self._data[r][C_VAL_RB],
                                        None, unitsys)
                return self._cadata_to_qv(vals)
            except:
                return QVariant()
        #elif role == Qt.EditRole:
        #    if col == C_FIELD: 
        #        raise RuntimeError("what is this ?")
        #        return QVariant(self._field[r]+self._fieldpfx[r])
        #    #print r, col, self._field[r], self._value[r]
        #    if vals is None: return QVariant()
        #    if isinstance(vals[col-1], (tuple, list)):
        #        return QVariant.fromList([QVariant(v) for v in vals[col-1]])
        #    elif vals[col-1] is not None:
        #        return QVariant(vals[col-1])
        elif role == Qt.TextAlignmentRole:
            if col == C_FIELD: return QVariant(Qt.AlignLeft | Qt.AlignVCenter)
            else: return QVariant(Qt.AlignRight | Qt.AlignBottom)
        elif role == Qt.ToolTipRole:
            if col == C_ELEM or col == C_FIELD:
                return QVariant("{0}, sb={1}, L={2}".format(
                    elem.family, elem.sb, elem.length))
            elif col == C_VAL_SP:
                pv = elem.pv(field=fld, handle="setpoint")
                return QVariant(", ".join(pv))
            elif col == C_VAL_RB:
                pv = elem.pv(field=fld, handle="readback")
                return QVariant(", ".join(pv))
            elif col > C_VAL_RB:
                unitsys = self._unitsys[col - C_VAL_RB - 1]
                #print "Checking the unit:", unitsys, elem.getUnit(fld, unitsys)
                return QVariant(str(elem.getUnit(fld, unitsys)))
        elif role == Qt.ForegroundRole:
            #if idx == 0: return QColor(Qt.darkGray)
            #if r in self._inactive and self.isHeadIndex(r):
            #    return QColor(Qt.darkGray)
            #elif r in self._inactive:
            #    return QColor(Qt.lightGray)
            #else: return QColor(Qt.black)
            return QVariant()
        elif role == Qt.BackgroundRole:
            if self._block[r] % 2 == 0: return QVariant()
            else: return QColor(0xE0, 0xE0, 0xE0)
        elif role == Qt.CheckStateRole:
            #if vals is not None: return QVariant()
            #elif r in self._inactive: return Qt.Unchecked
            #else: return Qt.Checked 
            #if idx == 0 and col == C_FIELD: return Qt.Checked
            return QVariant()
        else:
            return QVariant()
        #print "Asking data role=", role
        return QVariant()

    def headerData(self, section, orientation, role=Qt.DisplayRole):
        if role == Qt.TextAlignmentRole:
            if orientation == Qt.Horizontal:
                return QVariant(int(Qt.AlignLeft|Qt.AlignVCenter))
            return QVariant(int(Qt.AlignRight|Qt.AlignVCenter))
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            #print "Section:", section, C_VAL_RB
            if section == C_FIELD: return QVariant("Field")
            elif section == C_VAL_SP: return QVariant("Setpoint")
            elif section == C_VAL_RB: return QVariant("Readback")
            elif section > C_VAL_RB and section < C_VAL_RB + len(self._unitsys):
                return QVariant(self._unitsys[section-1-C_VAL_RB])
            else:
                return QVariant()
        elif orientation == Qt.Vertical:
            #if self._value[section] is not None: return QVariant()
            #idx = [k for k in range(section+1) if self._value[k] is None]
            #return QVariant(len(idx))
            return QVariant(section)

        #return QVariant(int(section+1))
        return QVariant()

    def flags(self, index):
        #print "flags:", 
        if not index.isValid():
            return Qt.ItemIsEnabled
        row, col = index.row(), index.column()
        elem, fld = self._data[row][:2]

        if col == C_VAL_SP and fld is not None:
            return Qt.ItemFlags(QAbstractTableModel.flags(self, index) |
                                Qt.ItemIsSelectable)
            #return Qt.ItemFlags(QAbstractTableModel.flags(self, index) |
            #    Qt.ItemIsEditable)
        return Qt.ItemIsEnabled
        
    def rowCount(self, index=QModelIndex()):
        return len(self._data)
    
    def columnCount(self, index=QModelIndex()):
        return C_VAL_RB + len(self._unitsys) + 1


    def setElementActive(self, irow, active = True):
        rows = self._element_block(irow)
        if active:
            for i in rows:
                if i not in self._inactive: continue
                self._inactive.remove(i)
        else:
            for i in rows:
                if i in self._inactive: continue
                self._inactive.add(i)

    def isActive(self, irow):
        return irow not in self._inactive