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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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