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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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