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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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