|
1 import gtk, gobject, pango |
|
2 from cgi import escape |
|
3 |
|
4 |
|
5 class DataView(gtk.ScrolledWindow): |
|
6 def __init__(self): |
|
7 super(DataView, self).__init__() |
|
8 |
|
9 sw = self |
|
10 sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
|
11 sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) |
|
12 self.treeview = gtk.TreeView(gtk.ListStore(str)) |
|
13 self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) |
|
14 self.treeview.set_property("rubber-banding", True) |
|
15 sw.add(self.treeview) |
|
16 |
|
17 |
|
18 def load_data(self, names, rows): |
|
19 x = [str] * (len(names) + 1) |
|
20 liststore = gtk.ListStore(*x) |
|
21 |
|
22 for c in self.treeview.get_columns(): |
|
23 self.treeview.remove_column(c) |
|
24 |
|
25 tvcolumn = gtk.TreeViewColumn() |
|
26 cell = DataViewCellRenderer() |
|
27 cell.set_property('head', True) |
|
28 tvcolumn.pack_start(cell, True) |
|
29 tvcolumn.set_property('resizable', True) |
|
30 #tvcolumn.set_property('sizing', gtk.TREE_VIEW_COLUMN_FIXED) |
|
31 tvcolumn.set_attributes(cell, text=0) |
|
32 tvcolumn.set_min_width(2) |
|
33 self.treeview.append_column(tvcolumn) |
|
34 |
|
35 i = 0 |
|
36 for c in names: |
|
37 i += 1 |
|
38 typename = c[1] |
|
39 title = '<b>%s</b>' % escape(c[0]) |
|
40 if typename: |
|
41 title += '\n<span size="small">%s</span>' % typename |
|
42 |
|
43 tvcolumn = gtk.TreeViewColumn() |
|
44 cell = DataViewCellRenderer() |
|
45 |
|
46 lab = gtk.Label() |
|
47 lab.set_use_underline(False) |
|
48 lab.set_markup(title) |
|
49 lab.show() |
|
50 tvcolumn.set_widget(lab) |
|
51 tvcolumn.set_property('resizable', True) |
|
52 tvcolumn.pack_start(cell, True) |
|
53 tvcolumn.set_attributes(cell, text=i) |
|
54 |
|
55 self.treeview.append_column(tvcolumn) |
|
56 |
|
57 self.treeview.set_model(liststore) |
|
58 |
|
59 i = 0 |
|
60 for row in rows: |
|
61 i += 1 |
|
62 liststore.append([i]+list(row)) |
|
63 |
|
64 |
|
65 |
|
66 class DataViewCellRenderer(gtk.GenericCellRenderer): |
|
67 __gtype_name__ = 'DataViewCellRenderer' |
|
68 __gproperties__ = { |
|
69 'text': (gobject.TYPE_STRING, None, None, '', gobject.PARAM_READWRITE), |
|
70 'head': (gobject.TYPE_BOOLEAN, None, None, False, gobject.PARAM_READWRITE)} |
|
71 |
|
72 |
|
73 def __init__(self): |
|
74 gtk.GenericCellRenderer.__init__(self) |
|
75 self._props = {'text' : '', 'head' : False} |
|
76 |
|
77 |
|
78 def do_set_property(self, pspec, value): |
|
79 if not pspec.name in self._props: |
|
80 raise AttributeError, 'Unknown property: %s' % pspec.name |
|
81 self._props[pspec.name] = value |
|
82 |
|
83 |
|
84 def do_get_property(self, pspec): |
|
85 return self._props[pspec.name] |
|
86 |
|
87 |
|
88 def on_get_size(self, widget, cell_area): |
|
89 if cell_area == None: |
|
90 pangoctx = widget.get_pango_context() |
|
91 layout = pango.Layout(pangoctx) |
|
92 layout.set_width(-1) |
|
93 layout.set_text(self.get_property('text') or 'NULL') |
|
94 w,h = layout.get_pixel_size() |
|
95 return (0, 0, w+5, 20) |
|
96 x = cell_area.x |
|
97 y = cell_area.x |
|
98 w = cell_area.width |
|
99 h = cell_area.height |
|
100 |
|
101 return (x,y,w,h) |
|
102 |
|
103 |
|
104 def on_render(self, window, widget, background_area, cell_area, expose_area, flags): |
|
105 x = background_area.x |
|
106 y = background_area.y |
|
107 w = background_area.width |
|
108 h = background_area.height |
|
109 |
|
110 ctx = window.cairo_create() |
|
111 ctx.set_line_width(0.4) |
|
112 ctx.set_source_rgb(0, 0, 0) |
|
113 ctx.move_to(x+w-1.5, y-0.5) |
|
114 ctx.line_to(x+w-1.5, y+h-0.5) |
|
115 ctx.line_to(x-0.5, y+h-0.5) |
|
116 ctx.stroke() |
|
117 ctx.set_source_rgb(1, 1, 1) |
|
118 ctx.move_to(x+w-0.5, y-0.5) |
|
119 ctx.line_to(x+w-0.5, y+h-0.5) |
|
120 ctx.stroke() |
|
121 |
|
122 pangoctx = widget.get_pango_context() |
|
123 layout = pango.Layout(pangoctx) |
|
124 text = self.get_property('text') |
|
125 head = self.get_property('head') |
|
126 |
|
127 if head: |
|
128 layout.set_markup('<b>%s</b>' % text) |
|
129 else: |
|
130 if text is None: |
|
131 layout.set_markup('<span foreground="gray">NULL</span>') |
|
132 else: |
|
133 layout.set_text(text) |
|
134 |
|
135 widget.style.paint_layout(window, gtk.STATE_NORMAL, True, |
|
136 cell_area, widget, '', |
|
137 cell_area.x, cell_area.y, |
|
138 layout) |
|
139 |