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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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