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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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