/[ascend]/trunk/pygtk/interface/gtkbrowser.py
ViewVC logotype

Annotation of /trunk/pygtk/interface/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 223 - (hide annotations) (download) (as text)
Fri Jan 27 08:18:43 2006 UTC (18 years, 5 months ago) by johnpye
File MIME type: text/x-python
File size: 28661 byte(s)
Some progress on editable solver parameters
1 johnpye 132 #!/usr/bin/env python
2    
3     import pygtk
4     pygtk.require('2.0')
5     import gtk
6     import gtk.glade
7     import pango
8     import re
9     import preferences
10     import urlparse
11     import optparse
12    
13     import sys, dl
14     # This sets the flags for dlopen used by python so that the symbols in the
15     # ascend library are made available to libraries dlopened within ASCEND:
16     sys.setdlopenflags(dl.RTLD_GLOBAL|dl.RTLD_NOW)
17     import ascend
18    
19     # This is my first ever GUI code so please be nice :)
20    
21     # The fancy tree-view gizmo is the GtkTreeView object. See the article
22     # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/300304
23     # for the original source code on which my implementation was based.
24    
25     GLADE_FILE = "/home/john/src/ascend/trunk/pygtk/interface/ascend.glade"
26    
27 johnpye 223 #======================================
28     # Browser is the main ASCEND library/model browser window
29    
30 johnpye 132 class Browser:
31    
32     # ---------------------------------
33     # SETUP
34    
35     def __init__(self):
36     #--------
37     # load the file referenced in the command line, if any
38    
39     parser = optparse.OptionParser(usage="%prog [[-m typename] file]", version="gtkbrowser $rev$" )
40     # add options here if we want
41    
42 johnpye 160 parser.add_option("-m", "--model"
43     ,action="store", type="string", dest="model"
44     ,help="specify the model to instantiate upon loading modules")
45 johnpye 132 (options, args) = parser.parse_args()
46    
47     #print "OPTIONS_______________:",options
48    
49     #--------
50     # load up the preferences ini file
51    
52     self.prefs = preferences.Preferences()
53    
54     #--------
55     # initialise ASCEND
56    
57     self.library = ascend.Library()
58    
59     self.sim = None
60    
61     #-------------------
62     # Set up the window and main widget actions
63    
64     glade = gtk.glade.XML(GLADE_FILE,"browserwin")
65    
66     self.window = glade.get_widget("browserwin")
67 johnpye 208
68 johnpye 132 if not self.window:
69     raise RuntimeError("Couldn't load window from glade file")
70 johnpye 172
71 johnpye 173 _display = self.window.get_screen().get_display().get_name();
72     _geom=self.prefs.getGeometrySizePosition(_display,"browserwin")
73 johnpye 172 if _geom:
74     self.window.resize(_geom[0],_geom[1]);
75     self.window.move(_geom[2],_geom[3]);
76 johnpye 173
77 johnpye 132 self.window.connect("delete_event", self.delete_event)
78    
79 johnpye 173 self.browserpaned=glade.get_widget("browserpaned");
80     _geom2=self.prefs.getGeometryValue(_display,"browserpaned");
81     if _geom2:
82     self.browserpaned.set_position(_geom2);
83    
84 johnpye 132 self.openbutton=glade.get_widget("openbutton")
85     self.openbutton.connect("clicked",self.open_click)
86    
87     self.reloadbutton=glade.get_widget("reloadbutton")
88     self.reloadbutton.connect("clicked",self.reload_click)
89    
90     self.solvebutton=glade.get_widget("solvebutton")
91     self.solvebutton.connect("clicked",self.solve_click)
92    
93     self.checkbutton=glade.get_widget("checkbutton")
94     self.checkbutton.connect("clicked",self.check_click)
95    
96     self.autotoggle=glade.get_widget("autotoggle")
97     self.autotoggle.connect("toggled",self.auto_toggle)
98    
99     self.methodrunbutton=glade.get_widget("methodrunbutton")
100     self.methodrunbutton.connect("clicked",self.methodrun_click)
101    
102     self.methodsel=glade.get_widget("methodsel")
103    
104     self.maintabs = glade.get_widget("maintabs")
105    
106 johnpye 164 self.statusbar = glade.get_widget("statusbar")
107    
108 johnpye 208 self.menu = glade.get_widget("browsermenu")
109     glade.signal_autoconnect(self)
110    
111 johnpye 132 #-------------------
112 johnpye 164 # waitwin
113    
114     self.waitwin = gtk.gdk.Window(self.window.window,
115     gtk.gdk.screen_width(),
116     gtk.gdk.screen_height(),
117     gtk.gdk.WINDOW_CHILD,
118     0,
119     gtk.gdk.INPUT_ONLY)
120    
121     _cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
122     self.waitwin.set_cursor(_cursor)
123    
124     #-------------------
125 johnpye 132 # pixbufs to be used in the error listing
126    
127     self.iconok = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
128     self.iconinfo = self.window.render_icon(gtk.STOCK_DIALOG_INFO,gtk.ICON_SIZE_MENU)
129     self.iconwarning = self.window.render_icon(gtk.STOCK_DIALOG_WARNING,gtk.ICON_SIZE_MENU)
130     self.iconerror = self.window.render_icon(gtk.STOCK_DIALOG_ERROR,gtk.ICON_SIZE_MENU)
131    
132     #--------------------
133     # set up the context menu for fixing/freeing vars
134    
135     self.treecontext = gtk.Menu();
136 johnpye 181 self.fixmenuitem = gtk.ImageMenuItem("_Fix",True);
137     _img = gtk.Image()
138     _img.set_from_file('icons/locked.png')
139     self.fixmenuitem.set_image(_img)
140    
141     self.freemenuitem = gtk.ImageMenuItem("F_ree",True);
142     _img = gtk.Image()
143     _img.set_from_file('icons/unlocked.png')
144     self.freemenuitem.set_image(_img)
145    
146     self.plotmenuitem = gtk.ImageMenuItem("P_lot",True);
147     _img = gtk.Image()
148     _img.set_from_file('icons/plot.png')
149     self.plotmenuitem.set_image(_img)
150    
151     self.propsmenuitem = gtk.ImageMenuItem("_Properties",True);
152     _img = gtk.Image()
153     _img.set_from_file('icons/properties.png')
154     self.propsmenuitem.set_image(_img)
155    
156 johnpye 207 self.fixmenuitem.show(); self.fixmenuitem.set_sensitive(False)
157     self.freemenuitem.show(); self.freemenuitem.set_sensitive(False)
158     self.plotmenuitem.show(); self.plotmenuitem.set_sensitive(False)
159 johnpye 181 self.propsmenuitem.show()
160 johnpye 132 self.treecontext.append(self.fixmenuitem);
161     self.treecontext.append(self.freemenuitem);
162 johnpye 181 _sep = gtk.SeparatorMenuItem(); _sep.show()
163     self.treecontext.append(_sep);
164 johnpye 172 self.treecontext.append(self.plotmenuitem);
165 johnpye 181 _sep = gtk.SeparatorMenuItem(); _sep.show()
166     self.treecontext.append(_sep);
167     self.treecontext.append(self.propsmenuitem);
168 johnpye 132 self.fixmenuitem.connect("activate",self.fix_activate)
169     self.freemenuitem.connect("activate",self.free_activate)
170 johnpye 175 self.plotmenuitem.connect("activate",self.plot_activate)
171 johnpye 181 self.propsmenuitem.connect("activate",self.props_activate)
172 johnpye 132 if not self.treecontext:
173     raise RuntimeError("Couldn't create browsercontext")
174     #--------------------
175     # set up the error view
176    
177 johnpye 168 self.errorview = glade.get_widget("errorview")
178 johnpye 132 errstorecolstypes = [gtk.gdk.Pixbuf,str,str,str,int]
179     self.errorstore = gtk.TreeStore(*errstorecolstypes)
180     errtitles = ["","Location","Message"];
181     self.errorview.set_model(self.errorstore)
182     self.errcols = [ gtk.TreeViewColumn() for _type in errstorecolstypes]
183    
184     i = 0
185     for tvcolumn in self.errcols[:len(errtitles)]:
186     tvcolumn.set_title(errtitles[i])
187     self.errorview.append_column(tvcolumn)
188    
189     if i>0:
190     _renderer = gtk.CellRendererText()
191     tvcolumn.pack_start(_renderer, True)
192     tvcolumn.add_attribute(_renderer, 'text', i)
193     if(i==2):
194     tvcolumn.add_attribute(_renderer, 'foreground', 3)
195     tvcolumn.add_attribute(_renderer, 'weight', 4)
196     else:
197     _renderer1 = gtk.CellRendererPixbuf()
198     tvcolumn.pack_start(_renderer1, False)
199     tvcolumn.add_attribute(_renderer1, 'pixbuf', int(0))
200    
201     i = i + 1
202    
203    
204     #--------------------
205     # set up the error reporter callback
206     self.reporter = ascend.getReporter()
207     self.reporter.setPythonErrorCallback(self.error_callback)
208    
209     #-------------------
210     # set up the module view
211    
212     self.modtank = {}
213     self.moduleview = glade.get_widget("moduleview")
214     modulestorecoltypes = [str, str]
215     self.modulestore = gtk.TreeStore(*modulestorecoltypes)
216     moduleviewtitles = ["Module name", "Filename"]
217     self.moduleview.set_model(self.modulestore)
218     self.modcols = [ gtk.TreeViewColumn() for _type in modulestorecoltypes]
219     i = 0
220     for modcol in self.modcols[:len(moduleviewtitles)]:
221     modcol.set_title(moduleviewtitles[i])
222     self.moduleview.append_column(modcol)
223     _renderer = gtk.CellRendererText()
224     modcol.pack_start(_renderer, True)
225     modcol.add_attribute(_renderer, 'text', i)
226     i = i + 1
227     self.moduleview.connect("row-activated", self.module_activated )
228    
229     #-------------------
230     # RE for units matching
231     self.units_re = re.compile("([-+]?(\d+(\.\d*)?|\d*\.d+)([eE][-+]?\d+)?)\s*(.*)");
232    
233     #--------------------
234     # set up the methods combobox
235    
236     self.methodstore = gtk.ListStore(str)
237     self.methodsel.set_model(self.methodstore)
238     _methodrenderer = gtk.CellRendererText()
239     self.methodsel.pack_start(_methodrenderer, True)
240     self.methodsel.add_attribute(_methodrenderer, 'text',0)
241    
242     #--------
243     # set up the instance browser view
244    
245     self.otank = {}
246     self.treeview = glade.get_widget("browserview")
247     columns = [str,str,str,str,int,bool]
248     self.treestore = gtk.TreeStore(*columns)
249     titles = ["Name","Type","Value"];
250     self.treeview.set_model(self.treestore)
251     self.tvcolumns = [ gtk.TreeViewColumn() for _type in columns[:len(titles)] ]
252    
253     self.treeview.connect("row-expanded", self.row_expanded )
254     self.treeview.connect("button-press-event", self.tree_click )
255    
256     # data columns are: name type value colour weight editable
257    
258     i = 0
259     for tvcolumn in self.tvcolumns[:len(titles)]:
260     tvcolumn.set_title(titles[i])
261     self.treeview.append_column(tvcolumn)
262    
263     renderer = gtk.CellRendererText()
264     tvcolumn.pack_start(renderer, True)
265     tvcolumn.add_attribute(renderer, 'text', i)
266     tvcolumn.add_attribute(renderer, 'foreground', 3)
267     tvcolumn.add_attribute(renderer, 'weight', 4)
268     if(i==2):
269     tvcolumn.add_attribute(renderer, 'editable', 5)
270     renderer.connect('edited',self.cell_edited_callback)
271     i = i + 1
272    
273    
274     if(len(args)==1):
275     self.do_open(args[0])
276    
277     print "Options: ",options
278    
279     if options.model:
280     try:
281     _t =self.library.findType(options.model);
282     self.do_sim(_t);
283     except RuntimeError, e:
284     self.reporter.reportError("Failed to create instance of '%s': %s" %(options.model, str(e)));
285    
286 johnpye 223
287 johnpye 132 def run(self):
288     self.window.show()
289     gtk.main()
290    
291     # --------------------------------------------
292     # MAJOR GUI COMMANDS
293    
294    
295     def do_open(self,filename):
296     # TODO does the user want to lose their work?
297     # TODO do we need to chdir?
298    
299 johnpye 164 _context = self.statusbar.get_context_id("do_open")
300    
301 johnpye 132 self.errorstore.clear()
302    
303     self.treestore.clear()
304     self.otank = {}
305    
306 johnpye 175 # self.library.clear()
307 johnpye 164
308     self.statusbar.push(_context,"Loading '"+filename+"'")
309 johnpye 132 self.library.load(filename)
310 johnpye 164 self.statusbar.pop(_context)
311 johnpye 132
312     self.filename = filename
313    
314     # Load the current list of modules into self.modules
315     self.modtank = {}
316     self.modulestore.clear()
317     modules = self.library.getModules()
318     for m in reversed(modules):
319     _n = str( m.getName() )
320     _f = str( m.getFilename() )
321     #print "ADDING ROW name %s, file = %s" % (_n, _f)
322     _r = self.modulestore.append(None, [ _n, _f ])
323     for t in self.library.getModuleTypes(m):
324     _n = t.getName()
325     #print "ADDING TYPE %s" % _n
326     _piter = self.modulestore.append(_r , [ _n, "" ])
327     _path = self.modulestore.get_path(_piter)
328     self.modtank[_path]=t
329    
330     #print "DONE ADDING MODULES"
331    
332     self.sim = None;
333     self.maintabs.set_current_page(0);
334 johnpye 164
335 johnpye 168 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
336     # for details on how the 'wait cursor' is done.
337 johnpye 164 def start_waiting(self, message):
338     self.waitcontext = self.statusbar.get_context_id("waiting")
339     self.statusbar.push(self.waitcontext,message)
340    
341     if self.waitwin:
342     self.waitwin.show()
343    
344     while gtk.events_pending():
345     gtk.main_iteration()
346 johnpye 132
347 johnpye 164 def stop_waiting(self):
348     if self.waitwin:
349     self.statusbar.pop(self.waitcontext)
350     self.waitwin.hide()
351    
352 johnpye 132 def do_sim(self, type_object):
353     self.sim = None;
354     # TODO: clear out old simulation first!
355    
356     print "DO_SIM(%s)" % str(type_object.getName())
357 johnpye 164 self.start_waiting("Compiling...")
358    
359 johnpye 132 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim")
360     print "...DONE 'getSimulation'"
361 johnpye 164 self.stop_waiting()
362 johnpye 132
363 johnpye 164 self.start_waiting("Building simulation...")
364 johnpye 132 print "BUILDING SIMULATION"
365 johnpye 164 self.sim.build()
366 johnpye 132 print "DONE BUILDING"
367 johnpye 164 self.stop_waiting()
368 johnpye 132
369 johnpye 223 self.sim.setSolver(ascend.Solver("QRSlv"))
370    
371 johnpye 132 # empty things out first
372     self.methodstore.clear()
373     self.treestore.clear()
374    
375     # methods
376     _methods = self.sim.getType().getMethods()
377 johnpye 160 _activemethod = None;
378 johnpye 132 for _m in _methods:
379 johnpye 160 _i = self.methodstore.append([_m.getName()])
380     if _m.getName()=="default_self":
381     self.methodsel.set_active_iter(_i)
382 johnpye 132
383     # instance hierarchy
384     self.otank = {} # map path -> (name,value)
385     self.make( self.sim.getName(),self.sim.getModel() )
386     self.maintabs.set_current_page(1);
387    
388     def do_solve(self):
389     if not self.sim:
390     self.reporter.reportError("No model selected yet")
391 johnpye 171 return;
392 johnpye 132
393 johnpye 168 self.start_waiting("Solving...")
394 johnpye 164
395 johnpye 154 self.sim.solve(ascend.Solver("QRSlv"))
396 johnpye 164
397 johnpye 168 self.stop_waiting()
398 johnpye 132 self.refreshtree()
399    
400     def do_check(self):
401     if not self.sim:
402     self.reporter.reportError("No model selected yet")
403    
404 johnpye 171 self.start_waiting("Checking system...")
405    
406 johnpye 132 if self.sim.check():
407     self.reporter.reportNote("System check OK")
408 johnpye 171
409 johnpye 132 self.sim.checkDoF()
410    
411 johnpye 171 self.stop_waiting()
412    
413 johnpye 132 self.refreshtree()
414    
415     def do_method(self,method):
416     if not self.sim:
417     self.reporter.reportError("No model selected yet")
418    
419     self.sim.run(method)
420     self.refreshtree()
421    
422     # --------------------------------------------
423     # MODULE LIST
424    
425     def module_activated(self, treeview, path, column, *args):
426     modules = self.library.getModules()
427     print "PATH",path
428     if len(path)==1:
429     self.reporter.reportNote("Launching of external editor not yet implemented")
430     elif len(path)==2:
431     if(self.modtank.has_key(path)):
432     _type = self.modtank[path];
433     self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
434     self.do_sim(_type)
435     else:
436     self.reporter.reportError("Didn't find type corresponding to row")
437    
438     # --------------------------------------------
439     # INSTANCE TREE
440    
441     def get_tree_row_data(self,instance):
442     _value = str(instance.getValue())
443     _type = str(instance.getType())
444     _name = str(instance.getName())
445     _fgcolor = "black"
446     _fontweight = pango.WEIGHT_NORMAL
447     _editable = False
448     if instance.getType().isRefinedSolverVar():
449     _editable = True
450     if instance.isFixed():
451     _fgcolor = "#008800"
452     _fontweight = pango.WEIGHT_BOLD
453     else:
454     _fgcolor = "#000088"
455     _fontweight = pango.WEIGHT_BOLD
456     elif instance.isBool() or instance.isReal() or instance.isInt():
457     # TODO can't edit constants that have already been refined
458     _editable = True
459    
460     #if(len(_value) > 80):
461     # _value = _value[:80] + "..."
462    
463     return [_name, _type, _value, _fgcolor, _fontweight, _editable]
464    
465     def get_error_row_data(self,sev,filename,line,msg):
466     _sevicon = {
467     0: self.iconok
468     ,1: self.iconinfo
469     ,2: self.iconwarning
470     ,3: self.iconerror
471     ,4: self.iconinfo
472     ,5: self.iconwarning
473     ,6: self.iconerror
474     }[sev]
475    
476     _fontweight = pango.WEIGHT_NORMAL
477     if sev==6:
478     _fontweight = pango.WEIGHT_BOLD
479    
480     _fgcolor = "black"
481     if sev==4:
482     _fgcolor = "#888800"
483     elif sev==5:
484     _fgcolor = "#884400"
485     elif sev==6:
486     _fgcolor = "#880000"
487     elif sev==0:
488     _fgcolor = "#008800"
489    
490     if not filename and not line:
491     _fileline = ""
492     else:
493     if(len(filename) > 25):
494     filename = "..."+filename[-22:]
495     _fileline = filename + ":" + str(line)
496    
497     _res = [_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight]
498     #print _res
499     return _res
500    
501     def make_row( self, piter, name, value ):
502    
503     _piter = self.treestore.append( piter, self.get_tree_row_data(value) )
504     return _piter
505    
506     def refreshtree(self):
507     # @TODO FIXME use a better system than colour literals!
508     for _path in self.otank: # { path : (name,value) }
509     _iter = self.treestore.get_iter(_path)
510     _name, _instance = self.otank[_path]
511     self.treestore.set_value(_iter, 2, _instance.getValue())
512     if _instance.getType().isRefinedSolverVar():
513     if _instance.isFixed() and self.treestore.get_value(_iter,3)=="#000088":
514     self.treestore.set_value(_iter,3,"#008800")
515     elif not _instance.isFixed() and self.treestore.get_value(_iter,3)=="#008800":
516     self.treestore.set_value(_iter,3,"#000088")
517    
518     def cell_edited_callback(self, renderer, path, newtext, **kwargs):
519     # get back the Instance object we just edited (having to use this seems like a bug)
520     path = tuple( map(int,path.split(":")) )
521    
522     if not self.otank.has_key(path):
523     raise RuntimeError("cell_edited_callback: invalid path '%s'" % path)
524     return
525    
526     _name, _instance = self.otank[path]
527    
528     if _instance.isReal():
529     # only real-valued things can have units
530    
531     try:
532     # match a float with option text afterwards, optionally separated by whitespace
533     _match = re.match(self.units_re,newtext)
534     if not _match:
535     self.reporter.reportError("Not a valid value-and-optional-units")
536     return
537    
538     _val = _match.group(1)
539     _units = _match.group(5)
540     #_val, _units = re.split("[ \t]+",newtext,2);
541     except RuntimeError:
542     self.reporter.reportError("Unable to split value and units")
543     return
544     print "val = ",_val
545     print "units = ",_units
546    
547     # parse the units, throw an error if no good
548     try:
549     _val = float(_val)
550     except RuntimeError:
551     self.reporter.reportError("Unable to convert number part '%s' to float" % _val)
552    
553     if _units.strip() == "":
554     _u = _instance.getType().getPreferredUnits()
555     if _u == None:
556     _u = _instance.getDimensions().getDefaultUnits()
557     self.reporter.reportNote("Assuming units '%s'" % _u.getName().toString() )
558     else:
559     try:
560     _u = ascend.Units(_units)
561     self.reporter.reportNote("Parsed units %s" % _units)
562     except RuntimeError:
563     self.reporter.reportError("Unrecognisable units '%s'" % _units)
564     return
565    
566     if _instance.getDimensions() != _u.getDimensions():
567    
568     if _u.getDimensions().isDimensionless():
569     _units = "[dimensionless]"
570    
571     _my_dims = _instance.getDimensions().getDefaultUnits()
572     if _instance.getDimensions().isDimensionless():
573     _my_dims = "[dimensionless]"
574    
575     self.reporter.reportError("Incompatible units '%s' (must fit with '%s')"
576     % (_units, _my_dims) )
577     return
578    
579     if _units.strip() != "" and not _instance.getDimensions().isDimensionless():
580     self.prefs.setPreferredUnits(str(_instance.getType().getName()), _units);
581    
582     _conv = float(_u.getConversion())
583     # self.reporter.reportNote("Converting: multiplying '%s %s' by factor %s to get SI units" % (_val, _units, _conv) )
584     _val = _val * _conv;
585    
586     self.reporter.reportNote("Setting '%s' to '%f'" % (_name, _val))
587    
588     if _instance.getType().isRefinedSolverVar():
589     # set the 'fixed' flag as well
590     _instance.setFixedValue(float(_val))
591     else:
592     _instance.setRealValue(float(_val))
593     else:
594     if _instance.isBool():
595     _lower = newtext.lower();
596     if _lower.startswith("t") or _lower.startswith("y") or _lower.strip()=="1":
597     newtext = 1
598     elif _lower.startswith("f") or _lower.startswith("n") or _lower.strip()=="0":
599     newtext = 0
600     else:
601     self.reporter.reportError("Invalid entry for a boolean variable: '%s'" % newtext)
602     return
603     _val = bool(newtext);
604     if _val == _instance.getValue():
605     self.reporter.reportNote("Boolean atom '%s' was not altered" % _instance.getName())
606     return
607     _instance.setBoolValue(_val)
608    
609     elif _instance.isInt():
610     _val = int(newtext)
611     if _val == _instance.getValue():
612     self.reporter.reportNote("Integer atom '%s' was not altered" % _instance.getName())
613     return
614     _instance.setIntValue(_val)
615     else:
616     self.reporter.reportError("Attempt to set a non-real, non-boolean, non-integer value!")
617     return
618    
619     # now that the variable is set, update the GUI and re-solve if desired
620     _iter = self.treestore.get_iter(path)
621     self.treestore.set_value(_iter,2,_instance.getValue())
622    
623     if _instance.getType().isRefinedSolverVar():
624     self.treestore.set_value(_iter,3,"#008800") # set the row green as fixed
625    
626     if self.autotoggle.get_active():
627     self.sim.check()
628     self.do_solve()
629     #self.reporter.reportError("SOLVER completed")
630    
631    
632     def make_children(self, value, piter ):
633     if value.isCompound():
634     children=value.getChildren();
635     for child in children:
636     _name = child.getName();
637     _piter = self.make_row(piter,_name,child)
638     _path = self.treestore.get_path(_piter)
639     self.otank[_path]=(_name,child)
640     #self.reporter.reportError("2 Added %s at path %s" % (_name,repr(_path)))
641    
642     def make(self, name=None, value=None, path=None, depth=1):
643     if path is None:
644     # make root node
645     piter = self.make_row( None, name, value )
646     path = self.treestore.get_path( piter )
647     self.otank[ path ] = (name, value)
648     #self.reporter.reportError("4 Added %s at path %s" % (name, path))
649     else:
650     name, value = self.otank[ path ]
651    
652     piter = self.treestore.get_iter( path )
653     if not self.treestore.iter_has_child( piter ):
654     self.make_children(value,piter)
655    
656     if depth:
657     for i in range( self.treestore.iter_n_children( piter ) ):
658     self.make( path = path+(i,), depth = depth - 1 )
659 johnpye 160 else:
660     self.treeview.expand_row("0",False)
661 johnpye 132
662     def row_expanded( self, treeview, piter, path ):
663     self.make( path = path )
664    
665     # ----------------------------------
666     # ERROR PANEL
667    
668     def error_callback(self,sev,filename,line,msg):
669     pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
670     path = self.errorstore.get_path(pos)
671     col = self.errorview.get_column(3)
672     self.errorview.scroll_to_cell(path,col)
673    
674     return 0;
675    
676     # --------------------------------
677     # BUTTON METHODS
678    
679     def open_click(self,*args):
680     dialog = gtk.FileChooserDialog("Open file...",
681 johnpye 160 None,
682     gtk.FILE_CHOOSER_ACTION_OPEN,
683     (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
684     gtk.STOCK_OPEN, gtk.RESPONSE_OK))
685 johnpye 132 dialog.set_default_response(gtk.RESPONSE_OK)
686    
687     filter = gtk.FileFilter()
688     filter.set_name("*.a4c, *.a4l")
689     filter.add_pattern("*.[Aa]4[Cc]")
690     filter.add_pattern("*.[Aa]4[Ll]")
691     dialog.add_filter(filter)
692    
693     filter = gtk.FileFilter()
694     filter.set_name("All files")
695     filter.add_pattern("*")
696     dialog.add_filter(filter)
697    
698     response = dialog.run()
699     _filename = dialog.get_filename()
700     dialog.destroy()
701    
702     if response == gtk.RESPONSE_OK:
703     self.reporter.reportNote("File %s selected." % dialog.get_filename() )
704 johnpye 185 self.library.clear()
705 johnpye 132 self.do_open( _filename)
706    
707    
708     def reload_click(self,*args):
709     _type = None
710     if(self.sim):
711     _type = self.sim.getType().getName().toString();
712    
713 johnpye 185 self.library.clear()
714 johnpye 132 self.do_open(self.filename)
715    
716     if _type:
717     _t = self.library.findType(_type)
718     self.do_sim(_t)
719    
720     def solve_click(self,*args):
721     #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
722     self.do_solve()
723    
724     def check_click(self,*args):
725     self.do_check()
726     #self.reporter.reportError("CHECK clicked")
727    
728 johnpye 208 def preferences_click(self,*args):
729     if not self.sim:
730     self.reporter.reportError("No simulation created yet!");
731    
732 johnpye 223 _paramswin = SolverParametersWindow(self.sim, self.reporter)
733     _paramswin.show()
734 johnpye 221
735 johnpye 132 def methodrun_click(self,*args):
736     _sel = self.methodsel.get_active_text()
737     if _sel:
738     _method = None
739     _methods = self.sim.getType().getMethods()
740     for _m in _methods:
741     if _m.getName()==_sel:
742     _method = _m
743     if not _method:
744     self.reporter.reportError("Method is not valid")
745     return
746     self.do_method(_method)
747     else:
748     self.reporter.reportError("No method selected")
749    
750     def auto_toggle(self,button,*args):
751     if button.get_active():
752 johnpye 168 self.reporter.reportSuccess("Auto mode is now ON")
753 johnpye 132 else:
754 johnpye 168 self.reporter.reportSuccess("Auto mode is now OFF")
755 johnpye 132
756     # ------------------------------
757     # CONTEXT MENU
758    
759     def tree_click(self,widget,event):
760     # which button was clicked?
761     if event.button == 3:
762     _x = int(event.x)
763     _y = int(event.y)
764     _time = event.time
765     _pthinfo = self.treeview.get_path_at_pos(_x, _y)
766     if _pthinfo != None:
767 johnpye 172 _canpop = False;
768 johnpye 132 _path, _col, _cellx, _celly = _pthinfo
769     # self.reporter.reportError("Right click on %s" % self.otank[_path][0])
770     _instance = self.otank[_path][1]
771     if _instance.getType().isRefinedSolverVar():
772 johnpye 172 _canpop = True;
773 johnpye 132 if _instance.isFixed():
774 johnpye 181 self.fixmenuitem.set_sensitive(False)
775     self.freemenuitem.set_sensitive(True)
776 johnpye 132 else:
777 johnpye 181 self.fixmenuitem.set_sensitive(True)
778     self.freemenuitem.set_sensitive(False)
779 johnpye 207 elif _instance.isRelation():
780     _canpop = True;
781     self.propsmenuitem.set_sensitive(True)
782 johnpye 175 else:
783 johnpye 181 self.fixmenuitem.set_sensitive(False)
784     self.freemenuitem.set_sensitive(False)
785 johnpye 172
786     if _instance.isPlottable():
787 johnpye 181 self.plotmenuitem.set_sensitive(True)
788 johnpye 172 _canpop = True;
789     else:
790 johnpye 181 self.plotmenuitem.set_sensitive(False)
791 johnpye 172
792     if _canpop:
793     self.treeview.grab_focus()
794     self.treeview.set_cursor( _path, _col, 0)
795 johnpye 132 self.treecontext.popup( None, None, None, event.button, _time)
796     return 1
797    
798     def fix_activate(self,widget):
799     _path,_col = self.treeview.get_cursor()
800     _name, _instance = self.otank[_path]
801     _instance.setFixed(True)
802     self.reporter.reportNote("Fixed variable %s" % _instance.getName().toString())
803     if self.autotoggle.get_active():
804     self.sim.check()
805     self.do_solve()
806     else:
807     self.refreshtree()
808     return 1
809    
810     def free_activate(self,widget):
811     _path,_col = self.treeview.get_cursor()
812     _instance = self.otank[_path][1]
813     _instance.setFixed(False)
814     self.reporter.reportNote("Freed variable %s" % _instance.getName().toString())
815     if self.autotoggle.get_active():
816     self.sim.check()
817     self.do_solve()
818     else:
819     self.refreshtree()
820     return 1
821    
822 johnpye 172 def plot_activate(self,widget):
823 johnpye 175 self.reporter.reportNote("plot_activate...");
824 johnpye 172 _path,_col = self.treeview.get_cursor()
825     _instance = self.otank[_path][1]
826     if not _instance.isPlottable():
827 johnpye 175 self.reporter.reportError("Can't plot instance %s" % _instance.getName().toString())
828 johnpye 172 return
829 johnpye 175 else:
830     self.reporter.reportNote("Instance %s about to be plotted..." % _instance.getName().toString())
831 johnpye 172
832 johnpye 175 print("Plotting instance '%s'..." % _instance.getName().toString())
833    
834 johnpye 176 _plot = _instance.getPlot()
835 johnpye 175
836 johnpye 176 print "Title: ", _plot.getTitle()
837 johnpye 180 _plot.show(True)
838 johnpye 176
839 johnpye 172 return 1
840    
841 johnpye 181 def props_activate(self,widget):
842 johnpye 207 _path,_col = self.treeview.get_cursor()
843     _instance = self.otank[_path][1]
844     if _instance.isRelation():
845 johnpye 215 print "Relation '"+_instance.getName().toString()+"':", \
846     _instance.getRelationAsString(self.sim.getModel())
847 johnpye 207 else:
848     self.reporter.reportWarning("props_activate not implemented")
849 johnpye 172
850    
851 johnpye 132 # ---------------------------------
852     # WINDOW-LEVEL ACTIONS
853    
854     def delete_event(self, widget, event, data=None):
855     self.reporter.clearPythonErrorCallback()
856 johnpye 172 _w,_h = self.window.get_size()
857     _t,_l = self.window.get_position()
858 johnpye 173 _display = self.window.get_screen().get_display().get_name()
859     self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
860 johnpye 132
861 johnpye 173 _p = self.browserpaned.get_position()
862     self.prefs.setGeometryValue(_display,"browserpaned",_p);
863    
864 johnpye 132 # causes prefs to be saved unless they are still being used elsewher
865     del(self.prefs)
866    
867     gtk.main_quit()
868     print "GTK QUIT"
869     return False
870    
871 johnpye 223 #======================================================
872     # SOLVER PARAMETERS WINDOW
873    
874     class SolverParametersWindow:
875     def __init__(self,sim,reporter):
876     self.sim = sim
877     self.params = self.sim.getSolverParameters();
878    
879     self.reporter = reporter
880    
881     _xml = gtk.glade.XML(GLADE_FILE,"paramswin")
882     self.window = _xml.get_widget("paramswin")
883     _xml.signal_autoconnect(self)
884    
885     self.paramsview = _xml.get_widget("paramsview")
886     self.otank = {}
887     self.paramstore = gtk.TreeStore(str,str,str,bool)
888     self.paramsview.set_model(self.paramstore)
889    
890     # name column
891     _renderer0 = gtk.CellRendererText()
892     _col0 = gtk.TreeViewColumn("Name", _renderer0, text=0)
893     self.paramsview.append_column(_col0)
894    
895     # value column: 'editable' set by column 3 of the model data.
896     _renderer1 = gtk.CellRendererText()
897     _col1 = gtk.TreeViewColumn("Value", _renderer1, text=1, editable=3)
898     self.paramsview.append_column(_col1)
899    
900     # range column
901     _renderer2 = gtk.CellRendererText()
902     _col2 = gtk.TreeViewColumn("Range", _renderer2, text=2)
903     self.paramsview.append_column(_col2)
904    
905     self.populate()
906    
907     def create_row_data(self,p):
908     _row = [p.getLabel()];
909     if p.isStr():
910     _row.extend([p.getStrValue(), str(len(p.getStrOptions()))+" options", True]);
911     elif p.isBool():
912     if p.getBoolValue():
913     _val = 'True'
914     else:
915     _val = 'False'
916     _row.extend([_val,"",False])
917     elif p.isReal():
918     if p.getRealLowerBound()==0 and p.getRealUpperBound():
919     _row.extend([str(p.getRealValue()), "",True])
920     else:
921     _row.extend([str(p.getRealValue()), "[ "+str(p.getRealLowerBound())+", "+str(p.getRealUpperBound())+" ]",True])
922     elif p.isInt():
923     if p.getIntLowerBound()==0 and p.getIntUpperBound():
924     _row.extend([str(p.getIntValue()), "", True])
925     else:
926     _row.extend([str(p.getIntValue()), "[ "+str(p.getIntLowerBound())+", "+str(p.getIntLowerBound())+" ]", True])
927    
928     else:
929     raise RuntimeError("invalid type")
930     return _row;
931    
932     def populate(self):
933     # Fill the paramstore with data
934    
935     for i in self.params:
936     _piter = self.paramstore.append( None, self.create_row_data(i) )
937    
938     _path = self.paramstore.get_path(_piter)
939     self.otank[ _path ] = i
940    
941     def on_paramsview_row_activated(self,*args,**kwargs):
942     print "EDITED"
943    
944     def show(self):
945     self.window.show()
946    
947     def on_paramscancel_activate(self,*args,**kwargs):
948     self.do_destroy()
949    
950     def on_paramsapply_activate(self,*args,**kwargs):
951     print "SAVE"
952    
953     def on_paramswin_destroy(self,*args,**kwargs):
954     self.do_destroy()
955    
956     def do_destroy(self):
957     print "DESTROY PARAMS WIN"
958     self.window.hide()
959     del(self.window)
960     del(self.params)
961    
962 johnpye 132 def test():
963     import ascend
964     b = Browser();
965     b.run()
966    
967     if __name__ == "__main__":
968     test()

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