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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 164 - (show annotations) (download) (as text)
Tue Jan 3 09:54:43 2006 UTC (14 years, 1 month ago) by johnpye
Original Path: trunk/pygtk/interface/gtkbrowser.py
File MIME type: text/x-python
File size: 22496 byte(s)
Added wait-cursor during compile/build, started working
on correct destruction of Simulation objects.
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 self.window.connect("delete_event", self.delete_event)
68
69 self.openbutton=glade.get_widget("openbutton")
70 self.openbutton.connect("clicked",self.open_click)
71
72 self.reloadbutton=glade.get_widget("reloadbutton")
73 self.reloadbutton.connect("clicked",self.reload_click)
74
75 self.solvebutton=glade.get_widget("solvebutton")
76 self.solvebutton.connect("clicked",self.solve_click)
77
78 self.checkbutton=glade.get_widget("checkbutton")
79 self.checkbutton.connect("clicked",self.check_click)
80
81 self.autotoggle=glade.get_widget("autotoggle")
82 self.autotoggle.connect("toggled",self.auto_toggle)
83
84 self.methodrunbutton=glade.get_widget("methodrunbutton")
85 self.methodrunbutton.connect("clicked",self.methodrun_click)
86
87 self.methodsel=glade.get_widget("methodsel")
88
89 self.maintabs = glade.get_widget("maintabs")
90
91 self.statusbar = glade.get_widget("statusbar")
92
93 #-------------------
94 # waitwin
95
96 self.waitwin = gtk.gdk.Window(self.window.window,
97 gtk.gdk.screen_width(),
98 gtk.gdk.screen_height(),
99 gtk.gdk.WINDOW_CHILD,
100 0,
101 gtk.gdk.INPUT_ONLY)
102
103 _cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
104 self.waitwin.set_cursor(_cursor)
105
106 #-------------------
107 # pixbufs to be used in the error listing
108
109 self.iconok = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
110 self.iconinfo = self.window.render_icon(gtk.STOCK_DIALOG_INFO,gtk.ICON_SIZE_MENU)
111 self.iconwarning = self.window.render_icon(gtk.STOCK_DIALOG_WARNING,gtk.ICON_SIZE_MENU)
112 self.iconerror = self.window.render_icon(gtk.STOCK_DIALOG_ERROR,gtk.ICON_SIZE_MENU)
113
114 #--------------------
115 # set up the context menu for fixing/freeing vars
116
117 self.treecontext = gtk.Menu();
118 self.fixmenuitem = gtk.MenuItem("Fix");
119 self.freemenuitem = gtk.MenuItem("Free");
120 self.fixmenuitem.show()
121 self.freemenuitem.show()
122 self.treecontext.append(self.fixmenuitem);
123 self.treecontext.append(self.freemenuitem);
124 self.fixmenuitem.connect("activate",self.fix_activate)
125 self.freemenuitem.connect("activate",self.free_activate)
126 if not self.treecontext:
127 raise RuntimeError("Couldn't create browsercontext")
128 #--------------------
129 # set up the error view
130
131 self.errorview = glade.get_widget("errorview")
132 errstorecolstypes = [gtk.gdk.Pixbuf,str,str,str,int]
133 self.errorstore = gtk.TreeStore(*errstorecolstypes)
134 errtitles = ["","Location","Message"];
135 self.errorview.set_model(self.errorstore)
136 self.errcols = [ gtk.TreeViewColumn() for _type in errstorecolstypes]
137
138 i = 0
139 for tvcolumn in self.errcols[:len(errtitles)]:
140 tvcolumn.set_title(errtitles[i])
141 self.errorview.append_column(tvcolumn)
142
143 if i>0:
144 _renderer = gtk.CellRendererText()
145 tvcolumn.pack_start(_renderer, True)
146 tvcolumn.add_attribute(_renderer, 'text', i)
147 if(i==2):
148 tvcolumn.add_attribute(_renderer, 'foreground', 3)
149 tvcolumn.add_attribute(_renderer, 'weight', 4)
150 else:
151 _renderer1 = gtk.CellRendererPixbuf()
152 tvcolumn.pack_start(_renderer1, False)
153 tvcolumn.add_attribute(_renderer1, 'pixbuf', int(0))
154
155 i = i + 1
156
157
158 #--------------------
159 # set up the error reporter callback
160 self.reporter = ascend.getReporter()
161 self.reporter.setPythonErrorCallback(self.error_callback)
162
163 #-------------------
164 # set up the module view
165
166 self.modtank = {}
167 self.moduleview = glade.get_widget("moduleview")
168 modulestorecoltypes = [str, str]
169 self.modulestore = gtk.TreeStore(*modulestorecoltypes)
170 moduleviewtitles = ["Module name", "Filename"]
171 self.moduleview.set_model(self.modulestore)
172 self.modcols = [ gtk.TreeViewColumn() for _type in modulestorecoltypes]
173 i = 0
174 for modcol in self.modcols[:len(moduleviewtitles)]:
175 modcol.set_title(moduleviewtitles[i])
176 self.moduleview.append_column(modcol)
177 _renderer = gtk.CellRendererText()
178 modcol.pack_start(_renderer, True)
179 modcol.add_attribute(_renderer, 'text', i)
180 i = i + 1
181 self.moduleview.connect("row-activated", self.module_activated )
182
183 #-------------------
184 # RE for units matching
185 self.units_re = re.compile("([-+]?(\d+(\.\d*)?|\d*\.d+)([eE][-+]?\d+)?)\s*(.*)");
186
187 #--------------------
188 # set up the methods combobox
189
190 self.methodstore = gtk.ListStore(str)
191 self.methodsel.set_model(self.methodstore)
192 self.methodsel.set_text_column(0)
193 _methodrenderer = gtk.CellRendererText()
194 self.methodsel.pack_start(_methodrenderer, True)
195 self.methodsel.add_attribute(_methodrenderer, 'text',0)
196
197 #--------
198 # set up the instance browser view
199
200 self.otank = {}
201 self.treeview = glade.get_widget("browserview")
202 columns = [str,str,str,str,int,bool]
203 self.treestore = gtk.TreeStore(*columns)
204 titles = ["Name","Type","Value"];
205 self.treeview.set_model(self.treestore)
206 self.tvcolumns = [ gtk.TreeViewColumn() for _type in columns[:len(titles)] ]
207
208 self.treeview.connect("row-expanded", self.row_expanded )
209 self.treeview.connect("button-press-event", self.tree_click )
210
211 # data columns are: name type value colour weight editable
212
213 i = 0
214 for tvcolumn in self.tvcolumns[:len(titles)]:
215 tvcolumn.set_title(titles[i])
216 self.treeview.append_column(tvcolumn)
217
218 renderer = gtk.CellRendererText()
219 tvcolumn.pack_start(renderer, True)
220 tvcolumn.add_attribute(renderer, 'text', i)
221 tvcolumn.add_attribute(renderer, 'foreground', 3)
222 tvcolumn.add_attribute(renderer, 'weight', 4)
223 if(i==2):
224 tvcolumn.add_attribute(renderer, 'editable', 5)
225 renderer.connect('edited',self.cell_edited_callback)
226 i = i + 1
227
228
229 if(len(args)==1):
230 self.do_open(args[0])
231
232 print "Options: ",options
233
234 if options.model:
235 try:
236 _t =self.library.findType(options.model);
237 self.do_sim(_t);
238 except RuntimeError, e:
239 self.reporter.reportError("Failed to create instance of '%s': %s" %(options.model, str(e)));
240
241 def run(self):
242 self.window.show()
243 gtk.main()
244
245 # --------------------------------------------
246 # MAJOR GUI COMMANDS
247
248
249 def do_open(self,filename):
250 # TODO does the user want to lose their work?
251 # TODO do we need to chdir?
252
253 _context = self.statusbar.get_context_id("do_open")
254
255 self.errorstore.clear()
256
257 self.treestore.clear()
258 self.otank = {}
259
260 self.library.clear()
261
262 self.statusbar.push(_context,"Loading '"+filename+"'")
263 self.library.load(filename)
264 self.statusbar.pop(_context)
265
266 self.filename = filename
267
268 # Load the current list of modules into self.modules
269 self.modtank = {}
270 self.modulestore.clear()
271 modules = self.library.getModules()
272 for m in reversed(modules):
273 _n = str( m.getName() )
274 _f = str( m.getFilename() )
275 #print "ADDING ROW name %s, file = %s" % (_n, _f)
276 _r = self.modulestore.append(None, [ _n, _f ])
277 for t in self.library.getModuleTypes(m):
278 _n = t.getName()
279 #print "ADDING TYPE %s" % _n
280 _piter = self.modulestore.append(_r , [ _n, "" ])
281 _path = self.modulestore.get_path(_piter)
282 self.modtank[_path]=t
283
284 #print "DONE ADDING MODULES"
285
286 self.sim = None;
287 self.maintabs.set_current_page(0);
288
289 def start_waiting(self, message):
290 self.waitcontext = self.statusbar.get_context_id("waiting")
291 self.statusbar.push(self.waitcontext,message)
292
293 if self.waitwin:
294 self.waitwin.show()
295
296 while gtk.events_pending():
297 gtk.main_iteration()
298
299 def stop_waiting(self):
300 if self.waitwin:
301 self.statusbar.pop(self.waitcontext)
302 self.waitwin.hide()
303
304 def do_sim(self, type_object):
305 self.sim = None;
306 # TODO: clear out old simulation first!
307
308 print "DO_SIM(%s)" % str(type_object.getName())
309 self.start_waiting("Compiling...")
310
311 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim")
312 print "...DONE 'getSimulation'"
313 self.stop_waiting()
314
315 self.start_waiting("Building simulation...")
316 print "BUILDING SIMULATION"
317 self.sim.build()
318 print "DONE BUILDING"
319 self.stop_waiting()
320
321 # empty things out first
322 self.methodstore.clear()
323 self.treestore.clear()
324
325 # methods
326 _methods = self.sim.getType().getMethods()
327 _activemethod = None;
328 for _m in _methods:
329 _i = self.methodstore.append([_m.getName()])
330 if _m.getName()=="default_self":
331 self.methodsel.set_active_iter(_i)
332
333 # instance hierarchy
334 self.otank = {} # map path -> (name,value)
335 self.make( self.sim.getName(),self.sim.getModel() )
336 self.maintabs.set_current_page(1);
337
338 def do_solve(self):
339 if not self.sim:
340 self.reporter.reportError("No model selected yet")
341
342 _context = self.statusbar.get_context_id("do_solve")
343 self.statusbar.push(_context,"Solving...")
344 while gtk.events_pending():
345 gtk.main_iteration()
346
347 self.sim.solve(ascend.Solver("QRSlv"))
348
349 self.statusbar.pop(_context)
350 self.refreshtree()
351
352 def do_check(self):
353 if not self.sim:
354 self.reporter.reportError("No model selected yet")
355
356 if self.sim.check():
357 self.reporter.reportNote("System check OK")
358 self.sim.checkDoF()
359
360 self.refreshtree()
361
362 def do_method(self,method):
363 if not self.sim:
364 self.reporter.reportError("No model selected yet")
365
366 self.sim.run(method)
367 self.refreshtree()
368
369 # --------------------------------------------
370 # MODULE LIST
371
372 def module_activated(self, treeview, path, column, *args):
373 modules = self.library.getModules()
374 print "PATH",path
375 if len(path)==1:
376 self.reporter.reportNote("Launching of external editor not yet implemented")
377 elif len(path)==2:
378 if(self.modtank.has_key(path)):
379 _type = self.modtank[path];
380 self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
381 self.do_sim(_type)
382 else:
383 self.reporter.reportError("Didn't find type corresponding to row")
384
385 # --------------------------------------------
386 # INSTANCE TREE
387
388 def get_tree_row_data(self,instance):
389 _value = str(instance.getValue())
390 _type = str(instance.getType())
391 _name = str(instance.getName())
392 _fgcolor = "black"
393 _fontweight = pango.WEIGHT_NORMAL
394 _editable = False
395 if instance.getType().isRefinedSolverVar():
396 _editable = True
397 if instance.isFixed():
398 _fgcolor = "#008800"
399 _fontweight = pango.WEIGHT_BOLD
400 else:
401 _fgcolor = "#000088"
402 _fontweight = pango.WEIGHT_BOLD
403 elif instance.isBool() or instance.isReal() or instance.isInt():
404 # TODO can't edit constants that have already been refined
405 _editable = True
406
407 #if(len(_value) > 80):
408 # _value = _value[:80] + "..."
409
410 return [_name, _type, _value, _fgcolor, _fontweight, _editable]
411
412 def get_error_row_data(self,sev,filename,line,msg):
413 _sevicon = {
414 0: self.iconok
415 ,1: self.iconinfo
416 ,2: self.iconwarning
417 ,3: self.iconerror
418 ,4: self.iconinfo
419 ,5: self.iconwarning
420 ,6: self.iconerror
421 }[sev]
422
423 _fontweight = pango.WEIGHT_NORMAL
424 if sev==6:
425 _fontweight = pango.WEIGHT_BOLD
426
427 _fgcolor = "black"
428 if sev==4:
429 _fgcolor = "#888800"
430 elif sev==5:
431 _fgcolor = "#884400"
432 elif sev==6:
433 _fgcolor = "#880000"
434 elif sev==0:
435 _fgcolor = "#008800"
436
437 if not filename and not line:
438 _fileline = ""
439 else:
440 if(len(filename) > 25):
441 filename = "..."+filename[-22:]
442 _fileline = filename + ":" + str(line)
443
444 _res = [_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight]
445 #print _res
446 return _res
447
448 def make_row( self, piter, name, value ):
449
450 _piter = self.treestore.append( piter, self.get_tree_row_data(value) )
451 return _piter
452
453 def refreshtree(self):
454 # @TODO FIXME use a better system than colour literals!
455 for _path in self.otank: # { path : (name,value) }
456 _iter = self.treestore.get_iter(_path)
457 _name, _instance = self.otank[_path]
458 self.treestore.set_value(_iter, 2, _instance.getValue())
459 if _instance.getType().isRefinedSolverVar():
460 if _instance.isFixed() and self.treestore.get_value(_iter,3)=="#000088":
461 self.treestore.set_value(_iter,3,"#008800")
462 elif not _instance.isFixed() and self.treestore.get_value(_iter,3)=="#008800":
463 self.treestore.set_value(_iter,3,"#000088")
464
465 def cell_edited_callback(self, renderer, path, newtext, **kwargs):
466 # get back the Instance object we just edited (having to use this seems like a bug)
467 path = tuple( map(int,path.split(":")) )
468
469 if not self.otank.has_key(path):
470 raise RuntimeError("cell_edited_callback: invalid path '%s'" % path)
471 return
472
473 _name, _instance = self.otank[path]
474
475 if _instance.isReal():
476 # only real-valued things can have units
477
478 try:
479 # match a float with option text afterwards, optionally separated by whitespace
480 _match = re.match(self.units_re,newtext)
481 if not _match:
482 self.reporter.reportError("Not a valid value-and-optional-units")
483 return
484
485 _val = _match.group(1)
486 _units = _match.group(5)
487 #_val, _units = re.split("[ \t]+",newtext,2);
488 except RuntimeError:
489 self.reporter.reportError("Unable to split value and units")
490 return
491 print "val = ",_val
492 print "units = ",_units
493
494 # parse the units, throw an error if no good
495 try:
496 _val = float(_val)
497 except RuntimeError:
498 self.reporter.reportError("Unable to convert number part '%s' to float" % _val)
499
500 if _units.strip() == "":
501 _u = _instance.getType().getPreferredUnits()
502 if _u == None:
503 _u = _instance.getDimensions().getDefaultUnits()
504 self.reporter.reportNote("Assuming units '%s'" % _u.getName().toString() )
505 else:
506 try:
507 _u = ascend.Units(_units)
508 self.reporter.reportNote("Parsed units %s" % _units)
509 except RuntimeError:
510 self.reporter.reportError("Unrecognisable units '%s'" % _units)
511 return
512
513 if _instance.getDimensions() != _u.getDimensions():
514
515 if _u.getDimensions().isDimensionless():
516 _units = "[dimensionless]"
517
518 _my_dims = _instance.getDimensions().getDefaultUnits()
519 if _instance.getDimensions().isDimensionless():
520 _my_dims = "[dimensionless]"
521
522 self.reporter.reportError("Incompatible units '%s' (must fit with '%s')"
523 % (_units, _my_dims) )
524 return
525
526 if _units.strip() != "" and not _instance.getDimensions().isDimensionless():
527 self.prefs.setPreferredUnits(str(_instance.getType().getName()), _units);
528
529 _conv = float(_u.getConversion())
530 # self.reporter.reportNote("Converting: multiplying '%s %s' by factor %s to get SI units" % (_val, _units, _conv) )
531 _val = _val * _conv;
532
533 self.reporter.reportNote("Setting '%s' to '%f'" % (_name, _val))
534
535 if _instance.getType().isRefinedSolverVar():
536 # set the 'fixed' flag as well
537 _instance.setFixedValue(float(_val))
538 else:
539 _instance.setRealValue(float(_val))
540 else:
541 if _instance.isBool():
542 _lower = newtext.lower();
543 if _lower.startswith("t") or _lower.startswith("y") or _lower.strip()=="1":
544 newtext = 1
545 elif _lower.startswith("f") or _lower.startswith("n") or _lower.strip()=="0":
546 newtext = 0
547 else:
548 self.reporter.reportError("Invalid entry for a boolean variable: '%s'" % newtext)
549 return
550 _val = bool(newtext);
551 if _val == _instance.getValue():
552 self.reporter.reportNote("Boolean atom '%s' was not altered" % _instance.getName())
553 return
554 _instance.setBoolValue(_val)
555
556 elif _instance.isInt():
557 _val = int(newtext)
558 if _val == _instance.getValue():
559 self.reporter.reportNote("Integer atom '%s' was not altered" % _instance.getName())
560 return
561 _instance.setIntValue(_val)
562 else:
563 self.reporter.reportError("Attempt to set a non-real, non-boolean, non-integer value!")
564 return
565
566 # now that the variable is set, update the GUI and re-solve if desired
567 _iter = self.treestore.get_iter(path)
568 self.treestore.set_value(_iter,2,_instance.getValue())
569
570 if _instance.getType().isRefinedSolverVar():
571 self.treestore.set_value(_iter,3,"#008800") # set the row green as fixed
572
573 if self.autotoggle.get_active():
574 self.sim.check()
575 self.do_solve()
576 #self.reporter.reportError("SOLVER completed")
577
578
579 def make_children(self, value, piter ):
580 if value.isCompound():
581 children=value.getChildren();
582 for child in children:
583 _name = child.getName();
584 _piter = self.make_row(piter,_name,child)
585 _path = self.treestore.get_path(_piter)
586 self.otank[_path]=(_name,child)
587 #self.reporter.reportError("2 Added %s at path %s" % (_name,repr(_path)))
588
589 def make(self, name=None, value=None, path=None, depth=1):
590 if path is None:
591 # make root node
592 piter = self.make_row( None, name, value )
593 path = self.treestore.get_path( piter )
594 self.otank[ path ] = (name, value)
595 #self.reporter.reportError("4 Added %s at path %s" % (name, path))
596 else:
597 name, value = self.otank[ path ]
598
599 piter = self.treestore.get_iter( path )
600 if not self.treestore.iter_has_child( piter ):
601 self.make_children(value,piter)
602
603 if depth:
604 for i in range( self.treestore.iter_n_children( piter ) ):
605 self.make( path = path+(i,), depth = depth - 1 )
606 else:
607 self.treeview.expand_row("0",False)
608
609 def row_expanded( self, treeview, piter, path ):
610 self.make( path = path )
611
612 # ----------------------------------
613 # ERROR PANEL
614
615 def error_callback(self,sev,filename,line,msg):
616 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
617 path = self.errorstore.get_path(pos)
618 col = self.errorview.get_column(3)
619 self.errorview.scroll_to_cell(path,col)
620
621 return 0;
622
623 # --------------------------------
624 # BUTTON METHODS
625
626 def open_click(self,*args):
627 dialog = gtk.FileChooserDialog("Open file...",
628 None,
629 gtk.FILE_CHOOSER_ACTION_OPEN,
630 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
631 gtk.STOCK_OPEN, gtk.RESPONSE_OK))
632 dialog.set_default_response(gtk.RESPONSE_OK)
633
634 filter = gtk.FileFilter()
635 filter.set_name("*.a4c, *.a4l")
636 filter.add_pattern("*.[Aa]4[Cc]")
637 filter.add_pattern("*.[Aa]4[Ll]")
638 dialog.add_filter(filter)
639
640 filter = gtk.FileFilter()
641 filter.set_name("All files")
642 filter.add_pattern("*")
643 dialog.add_filter(filter)
644
645 response = dialog.run()
646 _filename = dialog.get_filename()
647 dialog.destroy()
648
649 if response == gtk.RESPONSE_OK:
650 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
651 self.do_open( _filename)
652
653
654 def reload_click(self,*args):
655 _type = None
656 if(self.sim):
657 _type = self.sim.getType().getName().toString();
658
659 self.do_open(self.filename)
660
661 if _type:
662 _t = self.library.findType(_type)
663 self.do_sim(_t)
664
665 def solve_click(self,*args):
666 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
667 self.do_solve()
668
669 def check_click(self,*args):
670 self.do_check()
671 #self.reporter.reportError("CHECK clicked")
672
673 def methodrun_click(self,*args):
674 _sel = self.methodsel.get_active_text()
675 if _sel:
676 _method = None
677 _methods = self.sim.getType().getMethods()
678 for _m in _methods:
679 if _m.getName()==_sel:
680 _method = _m
681 if not _method:
682 self.reporter.reportError("Method is not valid")
683 return
684 self.do_method(_method)
685 else:
686 self.reporter.reportError("No method selected")
687
688 def auto_toggle(self,button,*args):
689 if button.get_active():
690 self.reporter.reportError("Auto mode is now ON")
691 else:
692 self.reporter.reportError("Auto mode is now OFF")
693
694 # ------------------------------
695 # CONTEXT MENU
696
697 def tree_click(self,widget,event):
698 # which button was clicked?
699 if event.button == 3:
700 _x = int(event.x)
701 _y = int(event.y)
702 _time = event.time
703 _pthinfo = self.treeview.get_path_at_pos(_x, _y)
704 if _pthinfo != None:
705 _path, _col, _cellx, _celly = _pthinfo
706 # self.reporter.reportError("Right click on %s" % self.otank[_path][0])
707 _instance = self.otank[_path][1]
708 if _instance.getType().isRefinedSolverVar():
709 self.treeview.grab_focus()
710 self.treeview.set_cursor( _path, _col, 0)
711 if _instance.isFixed():
712 self.fixmenuitem.hide()
713 self.freemenuitem.show()
714 else:
715 self.fixmenuitem.show()
716 self.freemenuitem.hide()
717 self.treecontext.popup( None, None, None, event.button, _time)
718 return 1
719 else:
720 self.reporter.reportError("Invalid selection for right-click")
721
722 def fix_activate(self,widget):
723 _path,_col = self.treeview.get_cursor()
724 _name, _instance = self.otank[_path]
725 _instance.setFixed(True)
726 self.reporter.reportNote("Fixed variable %s" % _instance.getName().toString())
727 if self.autotoggle.get_active():
728 self.sim.check()
729 self.do_solve()
730 else:
731 self.refreshtree()
732 return 1
733
734 def free_activate(self,widget):
735 _path,_col = self.treeview.get_cursor()
736 _instance = self.otank[_path][1]
737 _instance.setFixed(False)
738 self.reporter.reportNote("Freed variable %s" % _instance.getName().toString())
739 if self.autotoggle.get_active():
740 self.sim.check()
741 self.do_solve()
742 else:
743 self.refreshtree()
744 return 1
745
746 # ---------------------------------
747 # WINDOW-LEVEL ACTIONS
748
749 def delete_event(self, widget, event, data=None):
750 self.reporter.clearPythonErrorCallback()
751
752 # causes prefs to be saved unless they are still being used elsewher
753 del(self.prefs)
754
755 gtk.main_quit()
756 print "GTK QUIT"
757 return False
758
759 def test():
760 import ascend
761 b = Browser();
762 b.run()
763
764 if __name__ == "__main__":
765 test()

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