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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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