'r is a numpy record array
formatd is a dict mapping dtype name to mlab.FormatObj instances
stringd, if not None, is a dict mapping dtype names to a list of
valid strings for a combo drop down editor'

def __init__(self, r, formatd=None, stringd=None):

    if (stringd is None):
        stringd = dict()
    if (formatd is None):
        formatd = mlab.get_formatd(r)
    self.stringd = stringd
    self.callbacks = cbook.CallbackRegistry()
    self.r = r
    self.headers = r.dtype.names
    self.formats = [gtkformat_factory(formatd.get(name, mlab.FormatObj()), i) for (i, name) in enumerate(self.headers)]
    self.formatd = formatd = dict(zip(self.headers, self.formats))
    types = []
    for format in self.formats:
        if isinstance(format, mlab.FormatBool):
            types.append(gobject.TYPE_BOOLEAN)
        else:
            types.append(gobject.TYPE_STRING)
    self.combod = dict()
    if len(stringd):
        types.extend(([gobject.TYPE_INT] * len(stringd)))
        keys = sorted(stringd)
        valid = set(r.dtype.names)
        for (ikey, key) in enumerate(keys):
            assert (key in valid)
            combostore = gtk.ListStore(gobject.TYPE_STRING)
            for s in stringd[key]:
                combostore.append([s])
            self.combod[key] = (combostore, (len(self.headers) + ikey))
    gtk.ListStore.__init__(self, *types)
    for row in r:
        vals = []
        for (formatter, val) in zip(self.formats, row):
            if isinstance(formatter, mlab.FormatBool):
                vals.append(val)
            else:
                vals.append(formatter.tostr(val))
        if len(stringd):
            vals.extend(([0] * len(stringd)))
        self.append(vals)
