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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 215 - (show annotations) (download) (as text)
Wed Jan 25 02:08:29 2006 UTC (13 years, 8 months ago) by johnpye
File MIME type: text/x-python
File size: 26012 byte(s)
Improved display of relations by adding getRelationAsString(relative_to)
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()+"':", \
841 _instance.getRelationAsString(self.sim.getModel())
842 else:
843 self.reporter.reportWarning("props_activate not implemented")
844
845
846 # ---------------------------------
847 # WINDOW-LEVEL ACTIONS
848
849 def delete_event(self, widget, event, data=None):
850 self.reporter.clearPythonErrorCallback()
851 _w,_h = self.window.get_size()
852 _t,_l = self.window.get_position()
853 _display = self.window.get_screen().get_display().get_name()
854 self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
855
856 _p = self.browserpaned.get_position()
857 self.prefs.setGeometryValue(_display,"browserpaned",_p);
858
859 # causes prefs to be saved unless they are still being used elsewher
860 del(self.prefs)
861
862 gtk.main_quit()
863 print "GTK QUIT"
864 return False
865
866 def test():
867 import ascend
868 b = Browser();
869 b.run()
870
871 if __name__ == "__main__":
872 test()

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