1 |
import pygtk |
2 |
pygtk.require('2.0') |
3 |
import gtk |
4 |
import gtk.glade |
5 |
import pango |
6 |
|
7 |
OBSERVER_EDIT_COLOR = "#008800" |
8 |
OBSERVER_NOEDIT_COLOR = "#000088" |
9 |
OBSERVER_NORMAL_COLOR = "black" |
10 |
|
11 |
# This code uses the technique described in |
12 |
# http://www.daa.com.au/pipermail/pygtk/2006-February/011777.html |
13 |
|
14 |
OBSERVER_NUM=0 |
15 |
|
16 |
class ObserverColumn: |
17 |
""" |
18 |
A class to identify the instance that relates to a specify column |
19 |
and the units of measurement and column title, etc. |
20 |
""" |
21 |
def __init__(self,instance,index,name=None,units=None,browser=None): |
22 |
self.instance = instance |
23 |
self.name = name |
24 |
self.index = index |
25 |
|
26 |
if name==None: |
27 |
if browser == None: |
28 |
name = "UNNAMED" |
29 |
else: |
30 |
name = browser.sim.getInstanceName(instance) |
31 |
|
32 |
if units == None: |
33 |
units = instance.getType().getPreferredUnits() |
34 |
if units == None: |
35 |
units = instance.getType().getDimensions().getDefaultUnits() |
36 |
|
37 |
uname = str(units.getName()) |
38 |
if uname.find("/")!=-1: |
39 |
uname = "["+uname+"]" |
40 |
|
41 |
if uname == "": |
42 |
_title = "%s" % (name) |
43 |
else: |
44 |
_title = "%s / %s" % (name, uname) |
45 |
|
46 |
self.title = _title |
47 |
self.units = units |
48 |
self.uname = uname |
49 |
self.name = name |
50 |
|
51 |
def __repr__(self): |
52 |
return "ObserverColumn(name="+self.name+")" |
53 |
|
54 |
def cellvalue(self, column, cell, model, iter): |
55 |
#print "RENDERING COLUMN",self.index |
56 |
_rowobject = model.get_value(iter,0) |
57 |
|
58 |
cell.set_property('editable',False) |
59 |
cell.set_property('weight',400) |
60 |
try: |
61 |
if _rowobject.active: |
62 |
_rawval = self.instance.getRealValue() |
63 |
if self.instance.getType().isRefinedSolverVar(): |
64 |
if self.instance.isFixed(): |
65 |
cell.set_property('editable',True) |
66 |
cell.set_property('weight',700) |
67 |
cell.set_property('foreground',OBSERVER_EDIT_COLOR) |
68 |
else: |
69 |
cell.set_property('foreground',OBSERVER_NOEDIT_COLOR) |
70 |
else: |
71 |
cell.set_property('foreground',OBSERVER_NORMAL_COLOR) |
72 |
_rawval = _rowobject.values[self.index] |
73 |
_dataval = _rawval / self.units.getConversion() |
74 |
except IndexError: |
75 |
_dataval = "" |
76 |
|
77 |
cell.set_property('text', _dataval) |
78 |
|
79 |
class ObserverRow: |
80 |
""" |
81 |
Just a container for a vector of values, but with columns that |
82 |
should correspond to those in the Observer object's vector of |
83 |
ObserverColumn objects. |
84 |
""" |
85 |
def __init__(self,values=None,active=True): |
86 |
if values==None: |
87 |
values=[] |
88 |
|
89 |
self.values = values |
90 |
self.active = active |
91 |
|
92 |
def make_static(self,table): |
93 |
self.active = False |
94 |
print "TABLE COLS:",table.cols |
95 |
print "ROW VALUES:",self.values |
96 |
_v = [] |
97 |
for col in table.cols.values(): |
98 |
_v.append( col.instance.getRealValue() ) |
99 |
self.values = _v |
100 |
print "Made static, values:",self.values |
101 |
|
102 |
def get_values(self,table): |
103 |
if not self.active: |
104 |
return self.values |
105 |
else: |
106 |
_v = [] |
107 |
for index,col in table.cols.iteritems(): |
108 |
_v.append( col.instance.getRealValue() ) |
109 |
return _v |
110 |
|
111 |
class ObserverTab: |
112 |
|
113 |
def __init__(self,xml,browser,tab,name=None,alive=True): |
114 |
global OBSERVER_NUM |
115 |
self.colindex = 0 |
116 |
if name==None: |
117 |
OBSERVER_NUM=OBSERVER_NUM+1 |
118 |
name = "Observer %d" % OBSERVER_NUM |
119 |
self.name = name |
120 |
self.browser=browser |
121 |
xml.signal_autoconnect(self) |
122 |
self.view = xml.get_widget('observerview') |
123 |
self.tab = tab |
124 |
self.alive=alive |
125 |
if self.alive: |
126 |
self.browser.reporter.reportNote("New observer is 'alive'") |
127 |
|
128 |
self.keptimg = gtk.Image() |
129 |
self.activeimg = gtk.Image() |
130 |
self.activeimg.set_from_file("glade/active.png") |
131 |
# create PixBuf objects from these? |
132 |
self.rows = [] |
133 |
_store = gtk.TreeStore(object) |
134 |
self.cols = {} |
135 |
|
136 |
# create the 'active' pixbuf column |
137 |
_renderer = gtk.CellRendererPixbuf() |
138 |
_col = gtk.TreeViewColumn() |
139 |
_col.set_title("") |
140 |
_col.pack_start(_renderer,False) |
141 |
_col.set_cell_data_func(_renderer, self.activepixbufvalue) |
142 |
self.view.append_column(_col); |
143 |
|
144 |
# initially there will not be any other columns |
145 |
|
146 |
if self.alive: |
147 |
# for a 'live' Observer, create the 'active' bottom row |
148 |
self.browser.reporter.reportNote("Adding empty row to store") |
149 |
_row = ObserverRow() |
150 |
self.activeiter = _store.append(None, [_row] ) |
151 |
self.rows.append(_row) |
152 |
|
153 |
self.view.set_model(_store) |
154 |
self.browser.reporter.reportNote("Created observer '%s'" % self.name) |
155 |
|
156 |
def activepixbufvalue(self,column,cell,model,iter): |
157 |
_rowobject = model.get_value(iter,0) |
158 |
if _rowobject.active: |
159 |
cell.set_property('pixbuf',self.activeimg.get_pixbuf()) |
160 |
else: |
161 |
cell.set_property('pixbuf',self.keptimg.get_pixbuf()) |
162 |
|
163 |
def on_add_clicked(self,*args): |
164 |
self.do_add_row() |
165 |
|
166 |
def on_clear_clicked(self,*args): |
167 |
_store = self.view.get_model() |
168 |
_store.clear(); |
169 |
self.rows = {} |
170 |
self.activeiter = _store.append(None, [ObserverRow()] ) |
171 |
|
172 |
def do_add_row(self,values=None): |
173 |
_store = self.view.get_model() |
174 |
if self.alive: |
175 |
_row = ObserverRow() |
176 |
self.rows.append(_row) |
177 |
_oldrow = _store.get_value(self.activeiter,0) |
178 |
_oldrow.make_static(self) |
179 |
self.activeiter = _store.append(None,[_row]) |
180 |
_path = _store.get_path(self.activeiter) |
181 |
_oldpath,_oldcol = self.view.get_cursor() |
182 |
self.view.set_cursor(_path, _oldcol) |
183 |
else: |
184 |
_row = ObserverRow(values=values,active=False) |
185 |
self.rows.append(_row) |
186 |
_store.append(None,[_row]) |
187 |
#self.browser.reporter.reportNote("Added data row") |
188 |
|
189 |
def on_view_cell_edited(self, renderer, path, newtext, col): |
190 |
# we can assume it's always the self.activeiter that is edited... |
191 |
if col.instance.isFixed(): |
192 |
val = float(newtext) * col.units.getConversion() |
193 |
col.instance.setRealValue( val ) |
194 |
self.browser.reporter.reportNote("Updated value to %f" % float(newtext)) |
195 |
else: |
196 |
self.browser.reporter.reportError("Can't set a FREE variable from the Observer") |
197 |
return |
198 |
self.browser.do_solve_if_auto() |
199 |
|
200 |
def sync(self): |
201 |
self.view.queue_draw() |
202 |
#self.browser.reporter.reportNote("SYNC performed") |
203 |
|
204 |
def add_instance(self,instance): |
205 |
_col = ObserverColumn(instance,self.colindex,browser=self.browser) |
206 |
self.cols[self.colindex] = _col |
207 |
self.colindex = self.colindex + 1 |
208 |
|
209 |
# create a new column |
210 |
_renderer = gtk.CellRendererText() |
211 |
_renderer.connect('edited',self.on_view_cell_edited, _col) |
212 |
_tvcol = gtk.TreeViewColumn() |
213 |
_tvcol.set_title(_col.title) |
214 |
_tvcol.pack_start(_renderer,False) |
215 |
_tvcol.set_cell_data_func(_renderer, _col.cellvalue) |
216 |
self.view.append_column(_tvcol); |
217 |
#self.browser.reporter.reportError("cols = "+str(self.cols)) |
218 |
|
219 |
def copy_to_clipboard(self,clip): |
220 |
_s = [] |
221 |
_s.append('\t'.join([_v.title for _k,_v in self.cols.iteritems()])) |
222 |
print "COPYING %d ROWS" % len(self.rows) |
223 |
for _r in self.rows: |
224 |
_s.append("\t".join([`_v` for _v in _r.get_values(self)])) |
225 |
|
226 |
clip.set_text('\n'.join(_s),-1) |
227 |
|
228 |
self.browser.reporter.reportNote("Observer '%s' data copied to clipboard" % self.name) |