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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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