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

Annotation of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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