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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 231 - (show annotations) (download) (as text)
Sun Jan 29 14:15:44 2006 UTC (18 years, 4 months ago) by johnpye
File MIME type: text/x-python
File size: 27232 byte(s)
Moved some incidence matrix routines to generic/solver from tcltk98.
Documentation changes.
Added (inactive) incidence matrix menu item to PyGTK interface
Fixed autotools make for above changed (need to fix for Jam as well)
1 #!/usr/bin/env python
2
3 import pygtk
4 pygtk.require('2.0')
5 import gtk
6 import gtk.glade
7 import pango
8 import re
9 import preferences # loading/saving of .ini options
10 import urlparse
11 import optparse
12
13 from solverparameters import * # 'solver parameters' window
14 from help import * # viewing help files
15
16 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 CHANGED_COLOR = "#FFFF88"
31 SOLVERPARAM_BOOL_TRUE = "Yes"
32 SOLVERPARAM_BOOL_FALSE = "No"
33
34 ESCAPE_KEY = 65307
35
36 HELP_ROOT = None
37
38 #======================================
39 # Browser is the main ASCEND library/model browser window
40
41 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 parser.add_option("-m", "--model"
54 ,action="store", type="string", dest="model"
55 ,help="specify the model to instantiate upon loading modules")
56 (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
79 if not self.window:
80 raise RuntimeError("Couldn't load window from glade file")
81
82 _display = self.window.get_screen().get_display().get_name();
83 _geom=self.prefs.getGeometrySizePosition(_display,"browserwin")
84 if _geom:
85 self.window.resize(_geom[0],_geom[1]);
86 self.window.move(_geom[2],_geom[3]);
87
88 self.window.connect("delete_event", self.delete_event)
89
90 self.browserpaned=glade.get_widget("browserpaned");
91 _geom2=self.prefs.getGeometryValue(_display,"browserpaned");
92 if _geom2:
93 self.browserpaned.set_position(_geom2);
94
95 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 self.is_auto = self.autotoggle.get_active()
111
112 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 self.statusbar = glade.get_widget("statusbar")
120
121 self.menu = glade.get_widget("browsermenu")
122 glade.signal_autoconnect(self)
123
124 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 #-------------------
130 # 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 # 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 # TODO import this menu from Glade (this code is a PITA)
154
155 self.treecontext = gtk.Menu();
156 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 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 self.propsmenuitem.show()
180 self.treecontext.append(self.fixmenuitem);
181 self.treecontext.append(self.freemenuitem);
182 _sep = gtk.SeparatorMenuItem(); _sep.show()
183 self.treecontext.append(_sep);
184 self.treecontext.append(self.plotmenuitem);
185 _sep = gtk.SeparatorMenuItem(); _sep.show()
186 self.treecontext.append(_sep);
187 self.treecontext.append(self.propsmenuitem);
188 self.fixmenuitem.connect("activate",self.fix_activate)
189 self.freemenuitem.connect("activate",self.free_activate)
190 self.plotmenuitem.connect("activate",self.plot_activate)
191 self.propsmenuitem.connect("activate",self.props_activate)
192 if not self.treecontext:
193 raise RuntimeError("Couldn't create browsercontext")
194 #--------------------
195 # set up the error view
196
197 self.errorview = glade.get_widget("errorview")
198 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
307 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 _context = self.statusbar.get_context_id("do_open")
320
321 self.errorstore.clear()
322
323 self.treestore.clear()
324 self.otank = {}
325
326 # self.library.clear()
327
328 self.statusbar.push(_context,"Loading '"+filename+"'")
329 self.library.load(filename)
330 self.statusbar.pop(_context)
331
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
355 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
356 # for details on how the 'wait cursor' is done.
357 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
367 def stop_waiting(self):
368 if self.waitwin:
369 self.statusbar.pop(self.waitcontext)
370 self.waitwin.hide()
371
372 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 self.start_waiting("Compiling...")
378
379 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim")
380 print "...DONE 'getSimulation'"
381 self.stop_waiting()
382
383 self.start_waiting("Building simulation...")
384 print "BUILDING SIMULATION"
385 self.sim.build()
386 print "DONE BUILDING"
387 self.stop_waiting()
388
389 self.sim.setSolver(ascend.Solver("QRSlv"))
390
391 # empty things out first
392 self.methodstore.clear()
393 self.treestore.clear()
394
395 # methods
396 _methods = self.sim.getType().getMethods()
397 _activemethod = None;
398 for _m in _methods:
399 _i = self.methodstore.append([_m.getName()])
400 if _m.getName()=="default_self":
401 self.methodsel.set_active_iter(_i)
402
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 return;
412
413 self.start_waiting("Solving...")
414
415 self.sim.solve(ascend.Solver("QRSlv"))
416
417 self.stop_waiting()
418 self.refreshtree()
419
420 def do_check(self):
421 if not self.sim:
422 self.reporter.reportError("No model selected yet")
423
424 self.start_waiting("Checking system...")
425
426 if self.sim.check():
427 self.reporter.reportNote("System check OK")
428
429 self.sim.checkDoF()
430
431 self.stop_waiting()
432
433 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 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 def on_tools_sparsity_click(self,*args):
460 self.reporter.reportNote("Preparing sparsity matrix...")
461
462 # --------------------------------------------
463 # MODULE LIST
464
465 def module_activated(self, treeview, path, column, *args):
466 modules = self.library.getModules()
467 print "PATH",path
468 if len(path)==1:
469 self.reporter.reportNote("Launching of external editor not yet implemented")
470 elif len(path)==2:
471 if(self.modtank.has_key(path)):
472 _type = self.modtank[path];
473 self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
474 self.do_sim(_type)
475 else:
476 self.reporter.reportError("Didn't find type corresponding to row")
477
478 # --------------------------------------------
479 # INSTANCE TREE
480
481 def get_tree_row_data(self,instance):
482 _value = str(instance.getValue())
483 _type = str(instance.getType())
484 _name = str(instance.getName())
485 _fgcolor = "black"
486 _fontweight = pango.WEIGHT_NORMAL
487 _editable = False
488 if instance.getType().isRefinedSolverVar():
489 _editable = True
490 if instance.isFixed():
491 _fgcolor = "#008800"
492 _fontweight = pango.WEIGHT_BOLD
493 else:
494 _fgcolor = "#000088"
495 _fontweight = pango.WEIGHT_BOLD
496 elif instance.isBool() or instance.isReal() or instance.isInt():
497 # TODO can't edit constants that have already been refined
498 _editable = True
499
500 #if(len(_value) > 80):
501 # _value = _value[:80] + "..."
502
503 return [_name, _type, _value, _fgcolor, _fontweight, _editable]
504
505 def get_error_row_data(self,sev,filename,line,msg):
506 _sevicon = {
507 0: self.iconok
508 ,1: self.iconinfo
509 ,2: self.iconwarning
510 ,3: self.iconerror
511 ,4: self.iconinfo
512 ,5: self.iconwarning
513 ,6: self.iconerror
514 }[sev]
515
516 _fontweight = pango.WEIGHT_NORMAL
517 if sev==6:
518 _fontweight = pango.WEIGHT_BOLD
519
520 _fgcolor = "black"
521 if sev==4:
522 _fgcolor = "#888800"
523 elif sev==5:
524 _fgcolor = "#884400"
525 elif sev==6:
526 _fgcolor = "#880000"
527 elif sev==0:
528 _fgcolor = "#008800"
529
530 if not filename and not line:
531 _fileline = ""
532 else:
533 if(len(filename) > 25):
534 filename = "..."+filename[-22:]
535 _fileline = filename + ":" + str(line)
536
537 _res = [_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight]
538 #print _res
539 return _res
540
541 def make_row( self, piter, name, value ):
542
543 _piter = self.treestore.append( piter, self.get_tree_row_data(value) )
544 return _piter
545
546 def refreshtree(self):
547 # @TODO FIXME use a better system than colour literals!
548 for _path in self.otank: # { path : (name,value) }
549 _iter = self.treestore.get_iter(_path)
550 _name, _instance = self.otank[_path]
551 self.treestore.set_value(_iter, 2, _instance.getValue())
552 if _instance.getType().isRefinedSolverVar():
553 if _instance.isFixed() and self.treestore.get_value(_iter,3)=="#000088":
554 self.treestore.set_value(_iter,3,"#008800")
555 elif not _instance.isFixed() and self.treestore.get_value(_iter,3)=="#008800":
556 self.treestore.set_value(_iter,3,"#000088")
557
558 def cell_edited_callback(self, renderer, path, newtext, **kwargs):
559 # get back the Instance object we just edited (having to use this seems like a bug)
560 path = tuple( map(int,path.split(":")) )
561
562 if not self.otank.has_key(path):
563 raise RuntimeError("cell_edited_callback: invalid path '%s'" % path)
564 return
565
566 _name, _instance = self.otank[path]
567
568 if _instance.isReal():
569 # only real-valued things can have units
570
571 try:
572 # match a float with option text afterwards, optionally separated by whitespace
573 _match = re.match(self.units_re,newtext)
574 if not _match:
575 self.reporter.reportError("Not a valid value-and-optional-units")
576 return
577
578 _val = _match.group(1)
579 _units = _match.group(5)
580 #_val, _units = re.split("[ \t]+",newtext,2);
581 except RuntimeError:
582 self.reporter.reportError("Unable to split value and units")
583 return
584 print "val = ",_val
585 print "units = ",_units
586
587 # parse the units, throw an error if no good
588 try:
589 _val = float(_val)
590 except RuntimeError:
591 self.reporter.reportError("Unable to convert number part '%s' to float" % _val)
592
593 if _units.strip() == "":
594 _u = _instance.getType().getPreferredUnits()
595 if _u == None:
596 _u = _instance.getDimensions().getDefaultUnits()
597 self.reporter.reportNote("Assuming units '%s'" % _u.getName().toString() )
598 else:
599 try:
600 _u = ascend.Units(_units)
601 self.reporter.reportNote("Parsed units %s" % _units)
602 except RuntimeError:
603 self.reporter.reportError("Unrecognisable units '%s'" % _units)
604 return
605
606 if _instance.getDimensions() != _u.getDimensions():
607
608 if _u.getDimensions().isDimensionless():
609 _units = "[dimensionless]"
610
611 _my_dims = _instance.getDimensions().getDefaultUnits()
612 if _instance.getDimensions().isDimensionless():
613 _my_dims = "[dimensionless]"
614
615 self.reporter.reportError("Incompatible units '%s' (must fit with '%s')"
616 % (_units, _my_dims) )
617 return
618
619 if _units.strip() != "" and not _instance.getDimensions().isDimensionless():
620 self.prefs.setPreferredUnits(str(_instance.getType().getName()), _units);
621
622 _conv = float(_u.getConversion())
623 # self.reporter.reportNote("Converting: multiplying '%s %s' by factor %s to get SI units" % (_val, _units, _conv) )
624 _val = _val * _conv;
625
626 self.reporter.reportNote("Setting '%s' to '%f'" % (_name, _val))
627
628 if _instance.getType().isRefinedSolverVar():
629 # set the 'fixed' flag as well
630 _instance.setFixedValue(float(_val))
631 else:
632 _instance.setRealValue(float(_val))
633 else:
634 if _instance.isBool():
635 _lower = newtext.lower();
636 if _lower.startswith("t") or _lower.startswith("y") or _lower.strip()=="1":
637 newtext = 1
638 elif _lower.startswith("f") or _lower.startswith("n") or _lower.strip()=="0":
639 newtext = 0
640 else:
641 self.reporter.reportError("Invalid entry for a boolean variable: '%s'" % newtext)
642 return
643 _val = bool(newtext);
644 if _val == _instance.getValue():
645 self.reporter.reportNote("Boolean atom '%s' was not altered" % _instance.getName())
646 return
647 _instance.setBoolValue(_val)
648
649 elif _instance.isInt():
650 _val = int(newtext)
651 if _val == _instance.getValue():
652 self.reporter.reportNote("Integer atom '%s' was not altered" % _instance.getName())
653 return
654 _instance.setIntValue(_val)
655 else:
656 self.reporter.reportError("Attempt to set a non-real, non-boolean, non-integer value!")
657 return
658
659 # now that the variable is set, update the GUI and re-solve if desired
660 _iter = self.treestore.get_iter(path)
661 self.treestore.set_value(_iter,2,_instance.getValue())
662
663 if _instance.getType().isRefinedSolverVar():
664 self.treestore.set_value(_iter,3,"#008800") # set the row green as fixed
665
666 if self.is_auto:
667 self.sim.check()
668 self.do_solve()
669 #self.reporter.reportError("SOLVER completed")
670
671
672 def make_children(self, value, piter ):
673 if value.isCompound():
674 children=value.getChildren();
675 for child in children:
676 _name = child.getName();
677 _piter = self.make_row(piter,_name,child)
678 _path = self.treestore.get_path(_piter)
679 self.otank[_path]=(_name,child)
680 #self.reporter.reportError("2 Added %s at path %s" % (_name,repr(_path)))
681
682 def make(self, name=None, value=None, path=None, depth=1):
683 if path is None:
684 # make root node
685 piter = self.make_row( None, name, value )
686 path = self.treestore.get_path( piter )
687 self.otank[ path ] = (name, value)
688 #self.reporter.reportError("4 Added %s at path %s" % (name, path))
689 else:
690 name, value = self.otank[ path ]
691
692 piter = self.treestore.get_iter( path )
693 if not self.treestore.iter_has_child( piter ):
694 self.make_children(value,piter)
695
696 if depth:
697 for i in range( self.treestore.iter_n_children( piter ) ):
698 self.make( path = path+(i,), depth = depth - 1 )
699 else:
700 self.treeview.expand_row("0",False)
701
702 def row_expanded( self, treeview, piter, path ):
703 self.make( path = path )
704
705 # ----------------------------------
706 # ERROR PANEL
707
708 def error_callback(self,sev,filename,line,msg):
709 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
710 path = self.errorstore.get_path(pos)
711 col = self.errorview.get_column(3)
712 self.errorview.scroll_to_cell(path,col)
713
714 return 0;
715
716 # --------------------------------
717 # BUTTON METHODS
718
719 def open_click(self,*args):
720 dialog = gtk.FileChooserDialog("Open file...",
721 None,
722 gtk.FILE_CHOOSER_ACTION_OPEN,
723 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
724 gtk.STOCK_OPEN, gtk.RESPONSE_OK))
725 dialog.set_default_response(gtk.RESPONSE_OK)
726
727 filter = gtk.FileFilter()
728 filter.set_name("*.a4c, *.a4l")
729 filter.add_pattern("*.[Aa]4[Cc]")
730 filter.add_pattern("*.[Aa]4[Ll]")
731 dialog.add_filter(filter)
732
733 filter = gtk.FileFilter()
734 filter.set_name("All files")
735 filter.add_pattern("*")
736 dialog.add_filter(filter)
737
738 response = dialog.run()
739 _filename = dialog.get_filename()
740 dialog.destroy()
741
742 if response == gtk.RESPONSE_OK:
743 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
744 self.library.clear()
745 self.do_open( _filename)
746
747
748 def reload_click(self,*args):
749 _type = None
750 if(self.sim):
751 _type = self.sim.getType().getName().toString();
752
753 self.library.clear()
754 self.do_open(self.filename)
755
756 if _type:
757 _t = self.library.findType(_type)
758 self.do_sim(_t)
759
760 def solve_click(self,*args):
761 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
762 self.do_solve()
763
764 def check_click(self,*args):
765 self.do_check()
766 #self.reporter.reportError("CHECK clicked")
767
768 def preferences_click(self,*args):
769 if not self.sim:
770 self.reporter.reportError("No simulation created yet!");
771
772 _paramswin = SolverParametersWindow(self.sim, self.reporter)
773 _paramswin.show()
774
775 def methodrun_click(self,*args):
776 _sel = self.methodsel.get_active_text()
777 if _sel:
778 _method = None
779 _methods = self.sim.getType().getMethods()
780 for _m in _methods:
781 if _m.getName()==_sel:
782 _method = _m
783 if not _method:
784 self.reporter.reportError("Method is not valid")
785 return
786 self.do_method(_method)
787 else:
788 self.reporter.reportError("No method selected")
789
790 def auto_toggle(self,button,*args):
791 self.is_auto = button.get_active()
792 self.automenu.set_active(self.is_auto)
793
794 if self.is_auto:
795 self.reporter.reportSuccess("Auto mode is now ON")
796 else:
797 self.reporter.reportSuccess("Auto mode is now OFF")
798
799 def on_file_quit_click(self,*args):
800 self.do_quit()
801
802 def on_tools_auto_toggle(self,checkmenuitem,*args):
803 self.is_auto = checkmenuitem.get_active()
804 self.autotoggle.set_active(self.is_auto)
805
806 def on_help_about_click(self,*args):
807 _xml = gtk.glade.XML(GLADE_FILE,"aboutdialog");
808 _dialog = _xml.get_widget("aboutdialog")
809 _dialog.run()
810 _dialog.destroy()
811
812 def on_help_contents_click(self,*args):
813 _help = Help(HELP_ROOT)
814 _help.run()
815
816 # ------------------------------
817 # CONTEXT MENU
818
819 def tree_click(self,widget,event):
820 # which button was clicked?
821 if event.button == 3:
822 _x = int(event.x)
823 _y = int(event.y)
824 _time = event.time
825 _pthinfo = self.treeview.get_path_at_pos(_x, _y)
826 if _pthinfo != None:
827 _canpop = False;
828 _path, _col, _cellx, _celly = _pthinfo
829 # self.reporter.reportError("Right click on %s" % self.otank[_path][0])
830 _instance = self.otank[_path][1]
831 if _instance.getType().isRefinedSolverVar():
832 _canpop = True;
833 if _instance.isFixed():
834 self.fixmenuitem.set_sensitive(False)
835 self.freemenuitem.set_sensitive(True)
836 else:
837 self.fixmenuitem.set_sensitive(True)
838 self.freemenuitem.set_sensitive(False)
839 elif _instance.isRelation():
840 _canpop = True;
841 self.propsmenuitem.set_sensitive(True)
842 else:
843 self.fixmenuitem.set_sensitive(False)
844 self.freemenuitem.set_sensitive(False)
845
846 if _instance.isPlottable():
847 self.plotmenuitem.set_sensitive(True)
848 _canpop = True;
849 else:
850 self.plotmenuitem.set_sensitive(False)
851
852 if _canpop:
853 self.treeview.grab_focus()
854 self.treeview.set_cursor( _path, _col, 0)
855 self.treecontext.popup( None, None, None, event.button, _time)
856 return 1
857
858 def fix_activate(self,widget):
859 _path,_col = self.treeview.get_cursor()
860 _name, _instance = self.otank[_path]
861 _instance.setFixed(True)
862 self.reporter.reportNote("Fixed variable %s" % _instance.getName().toString())
863 if self.is_auto:
864 self.sim.check()
865 self.do_solve()
866 else:
867 self.refreshtree()
868 return 1
869
870 def free_activate(self,widget):
871 _path,_col = self.treeview.get_cursor()
872 _instance = self.otank[_path][1]
873 _instance.setFixed(False)
874 self.reporter.reportNote("Freed variable %s" % _instance.getName().toString())
875 if self.is_auto:
876 self.sim.check()
877 self.do_solve()
878 else:
879 self.refreshtree()
880 return 1
881
882 def plot_activate(self,widget):
883 self.reporter.reportNote("plot_activate...");
884 _path,_col = self.treeview.get_cursor()
885 _instance = self.otank[_path][1]
886 if not _instance.isPlottable():
887 self.reporter.reportError("Can't plot instance %s" % _instance.getName().toString())
888 return
889 else:
890 self.reporter.reportNote("Instance %s about to be plotted..." % _instance.getName().toString())
891
892 print("Plotting instance '%s'..." % _instance.getName().toString())
893
894 _plot = _instance.getPlot()
895
896 print "Title: ", _plot.getTitle()
897 _plot.show(True)
898
899 return 1
900
901 def props_activate(self,widget):
902 _path,_col = self.treeview.get_cursor()
903 _instance = self.otank[_path][1]
904 if _instance.isRelation():
905 print "Relation '"+_instance.getName().toString()+"':", \
906 _instance.getRelationAsString(self.sim.getModel())
907 else:
908 self.reporter.reportWarning("props_activate not implemented")
909
910
911 # ---------------------------------
912 # WINDOW-LEVEL ACTIONS
913
914 def delete_event(self, widget, event, data=None):
915 self.do_quit()
916 return False
917
918 def test():
919 import ascend
920 b = Browser();
921 b.run()
922
923 if __name__ == "__main__":
924 test()

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