/[ascend]/trunk/pygtk/modelview.py
ViewVC logotype

Annotation of /trunk/pygtk/modelview.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 533 - (hide annotations) (download) (as text)
Mon Apr 24 05:54:11 2006 UTC (13 years, 11 months ago) by johnpye
File MIME type: text/x-python
File size: 12673 byte(s)
Starting to refactor the model browser as its own python class.
Fixed a bug with the 'diagnose' feature on linux due to failed loading of an icon.
1 johnpye 533 import gtk
2     import gtk.glade
3     import pango
4     import ascpy
5    
6     from varentry import *
7     from properties import *
8    
9     BROWSER_FIXED_COLOR = "#008800"
10     BROWSER_FREE_COLOR = "#000088"
11    
12     class ModelView:
13     def __init__(self,browser,glade):
14     self.browser = browser # the parent object: the entire ASCEND browser
15    
16     self.modelview = glade.get_widget("browserview")
17    
18     # name, type, value, foreground, weight, editable, status-icon
19     columns = [str,str,str,str,int,bool,gtk.gdk.Pixbuf]
20    
21     self.otank = {}
22    
23     # name, type, value, foreground, weight, editable, status-icon
24     columns = [str,str,str,str,int,bool,gtk.gdk.Pixbuf]
25     self.modelstore = gtk.TreeStore(*columns)
26     titles = ["Name","Type","Value"];
27     self.modelview.set_model(self.modelstore)
28     self.tvcolumns = [ gtk.TreeViewColumn() for _type in columns[:len(titles)] ]
29    
30     self.modelview.connect("row-expanded", self.row_expanded )
31     self.modelview.connect("button-press-event", self.on_treeview_event )
32     self.modelview.connect("key-press-event",self.on_treeview_event )
33    
34     # data columns are: name type value colour weight editable
35    
36     i = 0
37     for tvcolumn in self.tvcolumns[:len(titles)]:
38     tvcolumn.set_title(titles[i])
39     self.modelview.append_column(tvcolumn)
40    
41     if(i==2):
42     # add status icon
43     renderer1 = gtk.CellRendererPixbuf()
44     tvcolumn.pack_start(renderer1, False)
45     tvcolumn.add_attribute(renderer1, 'pixbuf', 6)
46    
47     renderer = gtk.CellRendererText()
48     tvcolumn.pack_start(renderer, True)
49     tvcolumn.add_attribute(renderer, 'text', i)
50     tvcolumn.add_attribute(renderer, 'foreground', 3)
51     tvcolumn.add_attribute(renderer, 'weight', 4)
52     if(i==2):
53     tvcolumn.add_attribute(renderer, 'editable', 5)
54     renderer.connect('edited',self.cell_edited_callback)
55     i = i + 1
56    
57     #--------------------
58     # set up the context menu for fixing/freeing vars
59    
60     # TODO import this menu from Glade (this code is a PITA)
61    
62     self.treecontext = gtk.Menu();
63     self.fixmenuitem = gtk.ImageMenuItem("_Fix",True);
64     self.fixmenuitem.set_image(self.browser.fixedimg)
65    
66     self.freemenuitem = gtk.ImageMenuItem("F_ree",True);
67     _img = gtk.Image()
68     _img.set_from_file(self.browser.options.assets_dir+'unlocked.png')
69     self.freemenuitem.set_image(_img)
70    
71     self.plotmenuitem = gtk.ImageMenuItem("P_lot",True);
72     _img = gtk.Image()
73     _img.set_from_file(self.browser.options.assets_dir+'plot.png')
74     self.plotmenuitem.set_image(_img)
75    
76     self.propsmenuitem = gtk.ImageMenuItem("_Properties",True);
77     _img = gtk.Image()
78     _img.set_from_file(self.browser.options.assets_dir+'properties.png')
79     self.propsmenuitem.set_image(_img)
80    
81     self.observemenuitem = gtk.ImageMenuItem("_Observe",True);
82     _img = gtk.Image()
83     _img.set_from_file(self.browser.options.assets_dir+'observe.png')
84     self.observemenuitem.set_image(_img)
85    
86     self.fixmenuitem.show(); self.fixmenuitem.set_sensitive(False)
87     self.freemenuitem.show(); self.freemenuitem.set_sensitive(False)
88     self.plotmenuitem.show(); self.plotmenuitem.set_sensitive(False)
89     self.observemenuitem.show(); self.observemenuitem.set_sensitive(False)
90     self.propsmenuitem.show()
91     self.treecontext.append(self.fixmenuitem)
92     self.treecontext.append(self.freemenuitem)
93     _sep = gtk.SeparatorMenuItem(); _sep.show()
94     self.treecontext.append(_sep);
95     self.treecontext.append(self.plotmenuitem)
96     self.treecontext.append(self.observemenuitem)
97     _sep = gtk.SeparatorMenuItem(); _sep.show()
98     self.treecontext.append(_sep)
99     self.treecontext.append(self.propsmenuitem)
100     self.fixmenuitem.connect("activate",self.fix_activate)
101     self.freemenuitem.connect("activate",self.free_activate)
102     self.plotmenuitem.connect("activate",self.plot_activate)
103     self.propsmenuitem.connect("activate",self.props_activate)
104     self.observemenuitem.connect("activate",self.observe_activate)
105    
106     if not self.treecontext:
107     raise RuntimeError("Couldn't create browsercontext")
108    
109     def setSimulation(self,sim):
110     # instance hierarchy
111     self.sim = sim
112     self.modelstore.clear()
113     self.otank = {} # map path -> (name,value)
114     self.make( self.sim.getName(),self.sim.getModel() )
115     self.browser.maintabs.set_current_page(1);
116    
117     def clear(self):
118     self.modelstore.clear()
119     self.otank = {}
120    
121     # --------------------------------------------
122     # INSTANCE TREE
123    
124     def get_tree_row_data(self,instance): # for instance browser
125     _value = str(instance.getValue())
126     _type = str(instance.getType())
127     _name = str(instance.getName())
128     _fgcolor = "black"
129     _fontweight = pango.WEIGHT_NORMAL
130     _editable = False
131     _statusicon = None
132     if instance.getType().isRefinedSolverVar():
133     _editable = True
134     _fontweight = pango.WEIGHT_BOLD
135     if instance.isFixed():
136     _fgcolor = BROWSER_FIXED_COLOR
137     else:
138     _fgcolor = BROWSER_FREE_COLOR
139     _fontweight = pango.WEIGHT_BOLD
140     _status = instance.getVarStatus();
141     _statusicon = self.browser.statusicons[_status]
142    
143     elif instance.isBool() or instance.isReal() or instance.isInt():
144     # TODO can't edit constants that have already been refined
145     _editable = True
146    
147     #if(len(_value) > 80):
148     # _value = _value[:80] + "..."
149    
150     return [_name, _type, _value, _fgcolor, _fontweight, _editable, _statusicon]
151    
152     def make_row( self, piter, name, value ): # for instance browser
153    
154     _piter = self.modelstore.append( piter, self.get_tree_row_data(value) )
155     return _piter
156    
157     def refreshtree(self):
158     # @TODO FIXME use a better system than colour literals!
159     for _path in self.otank: # { path : (name,value) }
160     _iter = self.modelstore.get_iter(_path)
161     _name, _instance = self.otank[_path]
162     self.modelstore.set_value(_iter, 2, _instance.getValue())
163     if _instance.getType().isRefinedSolverVar():
164     if _instance.isFixed() and self.modelstore.get_value(_iter,3)==BROWSER_FREE_COLOR:
165     self.modelstore.set_value(_iter,3,BROWSER_FIXED_COLOR)
166     elif not _instance.isFixed() and self.modelstore.get_value(_iter,3)==BROWSER_FIXED_COLOR:
167     self.modelstore.set_value(_iter,3,BROWSER_FREE_COLOR)
168     self.modelstore.set_value(_iter, 6, self.browser.statusicons[_instance.getVarStatus()])
169    
170     def cell_edited_callback(self, renderer, path, newtext, **kwargs):
171     # get back the Instance object we just edited (having to use this seems like a bug)
172     path = tuple( map(int,path.split(":")) )
173    
174     if not self.otank.has_key(path):
175     raise RuntimeError("cell_edited_callback: invalid path '%s'" % path)
176     return
177    
178     _name, _instance = self.otank[path]
179    
180     if _instance.isReal():
181     # only real-valued things can have units
182    
183     _e = RealAtomEntry(_instance,newtext);
184     try:
185     _e.checkEntry()
186     _e.setValue()
187     _e.exportPreferredUnits(self.browser.prefs)
188     except InputError, e:
189     self.reporter.reportError(str(e))
190     return;
191    
192     else:
193     if _instance.isBool():
194     _lower = newtext.lower();
195     if _lower.startswith("t") or _lower.startswith("y") or _lower.strip()=="1":
196     newtext = 1
197     elif _lower.startswith("f") or _lower.startswith("n") or _lower.strip()=="0":
198     newtext = 0
199     else:
200     self.reporter.reportError("Invalid entry for a boolean variable: '%s'" % newtext)
201     return
202     _val = bool(newtext);
203     if _val == _instance.getValue():
204     self.reporter.reportNote("Boolean atom '%s' was not altered" % _instance.getName())
205     return
206     _instance.setBoolValue(_val)
207    
208     elif _instance.isInt():
209     _val = int(newtext)
210     if _val == _instance.getValue():
211     self.reporter.reportNote("Integer atom '%s' was not altered" % _instance.getName())
212     return
213     _instance.setIntValue(_val)
214     else:
215     self.reporter.reportError("Attempt to set a non-real, non-boolean, non-integer value!")
216     return
217    
218     # now that the variable is set, update the GUI and re-solve if desired
219     _iter = self.modelstore.get_iter(path)
220     self.modelstore.set_value(_iter,2,_instance.getValue())
221    
222     if _instance.getType().isRefinedSolverVar():
223     self.modelstore.set_value(_iter,3,BROWSER_FIXED_COLOR) # set the row green as fixed
224    
225     self.browser.do_solve_if_auto()
226    
227     def make_children(self, value, piter ):
228     if value.isCompound():
229     children=value.getChildren();
230     for child in children:
231     _name = child.getName();
232     _piter = self.make_row(piter,_name,child)
233     _path = self.modelstore.get_path(_piter)
234     self.otank[_path]=(_name,child)
235     #self.reporter.reportError("2 Added %s at path %s" % (_name,repr(_path)))
236    
237     def make(self, name=None, value=None, path=None, depth=1):
238     if path is None:
239     # make root node
240     piter = self.make_row( None, name, value )
241     path = self.modelstore.get_path( piter )
242     self.otank[ path ] = (name, value)
243     #self.reporter.reportError("4 Added %s at path %s" % (name, path))
244     else:
245     name, value = self.otank[ path ]
246    
247     piter = self.modelstore.get_iter( path )
248     if not self.modelstore.iter_has_child( piter ):
249     self.make_children(value,piter)
250    
251     if depth:
252     for i in range( self.modelstore.iter_n_children( piter ) ):
253     self.make( path = path+(i,), depth = depth - 1 )
254     else:
255     self.modelview.expand_row("0",False)
256    
257     def row_expanded( self, modelview, piter, path ):
258     self.make( path = path )
259    
260    
261     # ------------------------------
262     # CONTEXT MENU
263    
264     def on_treeview_event(self,widget,event):
265     _contextmenu = False;
266     if event.type==gtk.gdk.KEY_PRESS and gtk.gdk.keyval_name(event.keyval)=='Menu':
267     _contextmenu = True
268     _path, _col = self.modelview.get_cursor()
269     _button = 3;
270     elif event.type==gtk.gdk.BUTTON_PRESS:
271     if event.button == 3:
272     _contextmenu = True
273     _x = int(event.x)
274     _y = int(event.y)
275     _button = event.button
276     _pthinfo = self.modelview.get_path_at_pos(_x, _y)
277     if _pthinfo == None:
278     return
279     _path, _col, _cellx, _celly = _pthinfo
280    
281     # which button was clicked?
282     if not _contextmenu:
283     return
284    
285     _canpop = False;
286     # self.reporter.reportError("Right click on %s" % self.otank[_path][0])
287     _instance = self.otank[_path][1]
288     if _instance.getType().isRefinedSolverVar():
289     _canpop = True;
290     self.observemenuitem.set_sensitive(True)
291     if _instance.isFixed():
292     self.fixmenuitem.set_sensitive(False)
293     self.freemenuitem.set_sensitive(True)
294     else:
295     self.fixmenuitem.set_sensitive(True)
296     self.freemenuitem.set_sensitive(False)
297     elif _instance.isRelation():
298     _canpop = True;
299     self.propsmenuitem.set_sensitive(True)
300    
301     if _instance.isPlottable():
302     self.plotmenuitem.set_sensitive(True)
303     _canpop = True;
304     else:
305     self.plotmenuitem.set_sensitive(False)
306    
307     if not _canpop:
308     return
309    
310     self.modelview.grab_focus()
311     self.modelview.set_cursor( _path, _col, 0)
312     self.treecontext.popup( None, None, None, _button, event.time)
313     return 1
314    
315     def fix_activate(self,widget):
316     _path,_col = self.modelview.get_cursor()
317     _name, _instance = self.otank[_path]
318     self.set_fixed(_instance,True);
319     _instance.setFixed(True)
320     return 1
321    
322     def free_activate(self,widget):
323     _path,_col = self.modelview.get_cursor()
324     _instance = self.otank[_path][1]
325     self.set_fixed(_instance,False)
326     return 1
327    
328     def plot_activate(self,widget):
329     self.reporter.reportNote("plot_activate...");
330     _path,_col = self.modelview.get_cursor()
331     _instance = self.otank[_path][1]
332     if not _instance.isPlottable():
333     self.reporter.reportError("Can't plot instance %s" % _instance.getName().toString())
334     return
335     else:
336     self.reporter.reportNote("Instance %s about to be plotted..." % _instance.getName().toString())
337    
338     print("Plotting instance '%s'..." % _instance.getName().toString())
339    
340     _plot = _instance.getPlot()
341    
342     print "Title: ", _plot.getTitle()
343     _plot.show(True)
344    
345     return 1
346    
347     def props_activate(self,widget,*args):
348     _path,_col = self.modelview.get_cursor()
349     _instance = self.otank[_path][1]
350     if _instance.isRelation():
351     print "Relation '"+_instance.getName().toString()+"':", \
352     _instance.getRelationAsString(self.sim.getModel())
353     _dia = RelPropsWin(self.browser,_instance);
354     _dia.run();
355     elif _instance.getType().isRefinedSolverVar():
356     _dia = VarPropsWin(self.browser,_instance);
357     _dia.run();
358     else:
359     self.reporter.reportWarning("Select a variable first...")
360    
361     def observe_activate(self,widget,*args):
362     _path,_col = self.modelview.get_cursor()
363     _instance = self.otank[_path][1]
364     if _instance.getType().isRefinedSolverVar():
365     print "OBSERVING",_instance.getName().toString()
366     self.browser.observe(_instance)
367    
368     def on_fix_variable_activate(self,*args):
369     _path,_col = self.modelview.get_cursor()
370     _instance = self.otank[_path][1]
371     self.set_fixed(_instance,True)
372    
373     def on_free_variable_activate(self,*args):
374     _path,_col = self.modelview.get_cursor()
375     _instance = self.otank[_path][1]
376     self.set_fixed(_instance,False)
377    
378     def set_fixed(self,instance,val):
379     if instance.getType().isRefinedSolverVar():
380     f = instance.isFixed();
381     if (f and not val) or (not f and val):
382     instance.setFixed(val)
383     self.browser.do_solve_if_auto()

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22