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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 351 - (show annotations) (download) (as text)
Fri Mar 3 04:45:19 2006 UTC (13 years, 11 months ago) by johnpye
File MIME type: text/x-python
File size: 33005 byte(s)
Added windows-friendly application icon
Moved all references to GLADE_FILE to the new config.py arrangement.
First commit after the repository was broken...
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]
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 i = i + 1
316 self.moduleview.connect("row-activated", self.module_activated )
317
318 #--------------------
319 # set up the methods combobox
320
321 self.methodstore = gtk.ListStore(str)
322 self.methodsel.set_model(self.methodstore)
323 _methodrenderer = gtk.CellRendererText()
324 self.methodsel.pack_start(_methodrenderer, True)
325 self.methodsel.add_attribute(_methodrenderer, 'text',0)
326
327 #--------
328 # set up the instance browser view
329
330 self.otank = {}
331 self.treeview = glade.get_widget("browserview")
332
333 # name, type, value, foreground, weight, editable, status-icon
334 columns = [str,str,str,str,int,bool,gtk.gdk.Pixbuf]
335 self.treestore = gtk.TreeStore(*columns)
336 titles = ["Name","Type","Value"];
337 self.treeview.set_model(self.treestore)
338 self.tvcolumns = [ gtk.TreeViewColumn() for _type in columns[:len(titles)] ]
339
340 self.treeview.connect("row-expanded", self.row_expanded )
341 self.treeview.connect("button-press-event", self.on_treeview_event )
342 self.treeview.connect("key-press-event",self.on_treeview_event )
343
344 # data columns are: name type value colour weight editable
345
346 i = 0
347 for tvcolumn in self.tvcolumns[:len(titles)]:
348 tvcolumn.set_title(titles[i])
349 self.treeview.append_column(tvcolumn)
350
351 if(i==2):
352 # add status icon
353 renderer1 = gtk.CellRendererPixbuf()
354 tvcolumn.pack_start(renderer1, False)
355 tvcolumn.add_attribute(renderer1, 'pixbuf', 6)
356
357 renderer = gtk.CellRendererText()
358 tvcolumn.pack_start(renderer, True)
359 tvcolumn.add_attribute(renderer, 'text', i)
360 tvcolumn.add_attribute(renderer, 'foreground', 3)
361 tvcolumn.add_attribute(renderer, 'weight', 4)
362 if(i==2):
363 tvcolumn.add_attribute(renderer, 'editable', 5)
364 renderer.connect('edited',self.cell_edited_callback)
365 i = i + 1
366
367
368 if(len(args)==1):
369 self.do_open(args[0])
370
371 print "Options: ",options
372
373 if options.model:
374 try:
375 _t =self.library.findType(options.model);
376 self.do_sim(_t);
377 except RuntimeError, e:
378 self.reporter.reportError("Failed to create instance of '%s': %s" %(options.model, str(e)));
379
380
381 def run(self):
382 self.window.show()
383 gtk.main()
384
385 # --------------------------------------------
386 # MAJOR GUI COMMANDS
387
388
389 def do_open(self,filename):
390 # TODO does the user want to lose their work?
391 # TODO do we need to chdir?
392
393 _context = self.statusbar.get_context_id("do_open")
394
395 self.errorstore.clear()
396
397 self.treestore.clear()
398 self.otank = {}
399
400 # self.library.clear()
401
402 self.statusbar.push(_context,"Loading '"+filename+"'")
403 self.library.load(filename)
404 self.statusbar.pop(_context)
405
406 self.filename = filename
407
408 # Load the current list of modules into self.modules
409 self.modtank = {}
410 self.modulestore.clear()
411 modules = self.library.getModules()
412 self.library.listModules()
413 try:
414 _lll=len(modules)
415 except:
416 _msg = "UNABLE TO ACCESS MODULES LIST. This is bad.\n"+\
417 "Check your SWIG configuration (check for warnings during build)."+\
418 "\nThis is a known problem with the MinGW build at present."
419
420 self.reporter.reportError(_msg)
421 raise RuntimeError(_msg)
422
423 for m in reversed(modules):
424 _n = str( m.getName() )
425 _f = str( m.getFilename() )
426 #print "ADDING ROW name %s, file = %s" % (_n, _f)
427 _r = self.modulestore.append(None, [ _n, _f ])
428 for t in self.library.getModuleTypes(m):
429 _n = t.getName()
430 #print "ADDING TYPE %s" % _n
431 _piter = self.modulestore.append(_r , [ _n, "" ])
432 _path = self.modulestore.get_path(_piter)
433 self.modtank[_path]=t
434
435 #print "DONE ADDING MODULES"
436
437 self.sim = None;
438 self.maintabs.set_current_page(0);
439
440 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
441 # for details on how the 'wait cursor' is done.
442 def start_waiting(self, message):
443 self.waitcontext = self.statusbar.get_context_id("waiting")
444 self.statusbar.push(self.waitcontext,message)
445
446 if self.waitwin:
447 self.waitwin.show()
448
449 while gtk.events_pending():
450 gtk.main_iteration()
451
452 def stop_waiting(self):
453 if self.waitwin:
454 self.statusbar.pop(self.waitcontext)
455 self.waitwin.hide()
456
457 def do_sim(self, type_object):
458 self.sim = None;
459 # TODO: clear out old simulation first!
460
461 print "DO_SIM(%s)" % str(type_object.getName())
462 self.start_waiting("Compiling...")
463
464 try:
465 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim")
466 except RuntimeError, e:
467 self.stop_waiting()
468 self.reporter.reportError(str(e))
469 return
470
471 print "...DONE 'getSimulation'"
472 self.stop_waiting()
473
474 self.start_waiting("Building simulation...")
475 print "BUILDING SIMULATION"
476
477 try:
478 self.sim.build()
479 except RuntimeError, e:
480 self.stop_waiting()
481 self.reporter.reportError(str(e))
482 return;
483
484 print "DONE BUILDING"
485 self.stop_waiting()
486
487 self.sim.setSolver(ascend.Solver("QRSlv"))
488
489 # empty things out first
490 self.methodstore.clear()
491 self.treestore.clear()
492
493 # methods
494 _methods = self.sim.getType().getMethods()
495 _activemethod = None;
496 for _m in _methods:
497 _i = self.methodstore.append([_m.getName()])
498 if _m.getName()=="default_self":
499 self.methodsel.set_active_iter(_i)
500
501 # instance hierarchy
502 self.otank = {} # map path -> (name,value)
503 self.make( self.sim.getName(),self.sim.getModel() )
504 self.maintabs.set_current_page(1);
505
506 def do_solve_if_auto(self):
507 if self.is_auto:
508 self.sim.check()
509 self.do_solve()
510 else:
511 self.sim.processVarStatus()
512 self.refreshtree()
513
514 self.sync_observers()
515
516 def do_solve(self):
517 if not self.sim:
518 self.reporter.reportError("No model selected yet")
519 return;
520
521 self.start_waiting("Solving...")
522
523 if self.prefs.getBoolPref("SolverReporter","show_popup",True):
524 reporter = PopupSolverReporter(self,self.sim.getNumVars())
525 else:
526 reporter = SimpleSolverReporter(self)
527
528 self.sim.solve(ascend.Solver("QRSlv"),reporter)
529
530 self.stop_waiting()
531
532 self.sim.processVarStatus()
533 self.refreshtree()
534
535 def do_check(self):
536 if not self.sim:
537 self.reporter.reportError("No model selected yet")
538
539 self.start_waiting("Checking system...")
540
541 try:
542 if self.sim.check():
543 self.reporter.reportNote("System check OK")
544 self.sim.checkDoF()
545 except RuntimeError, e:
546 self.stop_waiting()
547 self.reporter.reportError(str(e))
548 return
549
550 self.stop_waiting()
551
552 self.refreshtree()
553
554 def do_method(self,method):
555 if not self.sim:
556 self.reporter.reportError("No model selected yet")
557
558 self.sim.run(method)
559 self.refreshtree()
560
561 def do_quit(self):
562 self.reporter.clearPythonErrorCallback()
563 _w,_h = self.window.get_size()
564 _t,_l = self.window.get_position()
565 _display = self.window.get_screen().get_display().get_name()
566 self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
567
568 _p = self.browserpaned.get_position()
569 self.prefs.setGeometryValue(_display,"browserpaned",_p);
570
571 # causes prefs to be saved unless they are still being used elsewher
572 del(self.prefs)
573
574 gtk.main_quit()
575 print "GTK QUIT"
576 return False
577
578 def on_tools_sparsity_click(self,*args):
579
580 self.reporter.reportNote("Preparing incidence matrix...")
581 _im = self.sim.getIncidenceMatrix();
582
583 self.reporter.reportNote("Plotting incidence matrix...")
584
585 _sp = IncidenceMatrixWindow(_im);
586 _sp.run();
587
588 def on_diagnose_blocks_click(self,*args):
589 try:
590 _bl = self.sim.getActiveBlock()
591 except RuntimeError, e:
592 self.reporter.reportError(str(e))
593 return
594 _db = DiagnoseWindow(self,_bl)
595 _db.run();
596
597 def on_add_observer_click(self,*args):
598 if len(self.observers) >= 1:
599 self.reporter.reportError("Not supported: multiple observers")
600 return
601 self.observers.append(self.create_observer())
602
603 def on_keep_observed_click(self,*args):
604 if len(self.observers) > 1:
605 self.reporter.reportError("Not supported: multiple observers")
606 return
607 if len(self.observers) <= 0:
608 self.reporter.reportError("No observer defined!")
609 return
610 self.observers[0].do_add_row()
611
612 def on_copy_observer_matrix_click(self,*args):
613 if self.clip == None:
614 self.clip = gtk.Clipboard()
615
616 if len(self.observers) > 1:
617 self.reporter.reportError("Not supported: multiple observers")
618 return
619 if len(self.observers) <= 0:
620 self.reporter.reportError("No observer defined!")
621 return
622 self.observers[0].copy_to_clipboard(self.clip)
623
624 def on_fix_variable_activate(self,*args):
625 _path,_col = self.treeview.get_cursor()
626 _instance = self.otank[_path][1]
627 self.set_fixed(_instance,True)
628
629 def on_free_variable_activate(self,*args):
630 _path,_col = self.treeview.get_cursor()
631 _instance = self.otank[_path][1]
632 self.set_fixed(_instance,False)
633
634 def set_fixed(self,instance,val):
635 if instance.getType().isRefinedSolverVar():
636 f = instance.isFixed();
637 if (f and not val) or (not f and val):
638 instance.setFixed(val)
639 self.do_solve_if_auto()
640
641 def on_show_solving_popup_toggle(self,checkmenuitem,*args):
642 _v = checkmenuitem.get_active()
643 self.prefs.setBoolPref("SolverReporter","show_popup",_v)
644 print "SET TO",_v
645
646 def on_close_on_converged_toggle(self,checkmenuitem,*args):
647 _v = checkmenuitem.get_active()
648 self.prefs.setBoolPref("SolverReporter","close_on_converged",_v)
649
650 def on_close_on_nonconverged_toggle(self,checkmenuitem,*args):
651 _v = checkmenuitem.get_active()
652 self.prefs.setBoolPref("SolverReporter","close_on_nonconverged",_v)
653
654 def on_show_variables_near_bounds_activate(self,*args):
655 _epsilon = 1e-4;
656 _vars = self.sim.getVariablesNearBounds(_epsilon)
657 print "VARIABLES NEAR BOUNDS"
658 for _v in _vars:
659 print _v.getName();
660
661 # --------------------------------------------
662 # MODULE LIST
663
664 def module_activated(self, treeview, path, column, *args):
665 modules = self.library.getModules()
666 print "PATH",path
667 if len(path)==1:
668 self.reporter.reportNote("Launching of external editor not yet implemented")
669 elif len(path)==2:
670 if(self.modtank.has_key(path)):
671 _type = self.modtank[path];
672 self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
673 self.do_sim(_type)
674 else:
675 self.reporter.reportError("Didn't find type corresponding to row")
676
677 # --------------------------------------------
678 # INSTANCE TREE
679
680 def get_tree_row_data(self,instance): # for instance browser
681 _value = str(instance.getValue())
682 _type = str(instance.getType())
683 _name = str(instance.getName())
684 _fgcolor = "black"
685 _fontweight = pango.WEIGHT_NORMAL
686 _editable = False
687 _statusicon = None
688 if instance.getType().isRefinedSolverVar():
689 _editable = True
690 _fontweight = pango.WEIGHT_BOLD
691 if instance.isFixed():
692 _fgcolor = BROWSER_FIXED_COLOR
693 else:
694 _fgcolor = BROWSER_FREE_COLOR
695 _fontweight = pango.WEIGHT_BOLD
696 _status = instance.getVarStatus();
697 _statusicon = self.statusicons[_status]
698
699 elif instance.isBool() or instance.isReal() or instance.isInt():
700 # TODO can't edit constants that have already been refined
701 _editable = True
702
703 #if(len(_value) > 80):
704 # _value = _value[:80] + "..."
705
706 return [_name, _type, _value, _fgcolor, _fontweight, _editable, _statusicon]
707
708 def make_row( self, piter, name, value ): # for instance browser
709
710 _piter = self.treestore.append( piter, self.get_tree_row_data(value) )
711 return _piter
712
713 def refreshtree(self):
714 # @TODO FIXME use a better system than colour literals!
715 for _path in self.otank: # { path : (name,value) }
716 _iter = self.treestore.get_iter(_path)
717 _name, _instance = self.otank[_path]
718 self.treestore.set_value(_iter, 2, _instance.getValue())
719 if _instance.getType().isRefinedSolverVar():
720 if _instance.isFixed() and self.treestore.get_value(_iter,3)==BROWSER_FREE_COLOR:
721 self.treestore.set_value(_iter,3,BROWSER_FIXED_COLOR)
722 elif not _instance.isFixed() and self.treestore.get_value(_iter,3)==BROWSER_FIXED_COLOR:
723 self.treestore.set_value(_iter,3,BROWSER_FREE_COLOR)
724 self.treestore.set_value(_iter, 6, self.statusicons[_instance.getVarStatus()])
725
726 def cell_edited_callback(self, renderer, path, newtext, **kwargs):
727 # get back the Instance object we just edited (having to use this seems like a bug)
728 path = tuple( map(int,path.split(":")) )
729
730 if not self.otank.has_key(path):
731 raise RuntimeError("cell_edited_callback: invalid path '%s'" % path)
732 return
733
734 _name, _instance = self.otank[path]
735
736 if _instance.isReal():
737 # only real-valued things can have units
738
739 _e = RealAtomEntry(_instance,newtext);
740 try:
741 _e.checkEntry()
742 _e.setValue()
743 _e.exportPreferredUnits(self.prefs)
744 except InputError, e:
745 self.reporter.reportError(str(e))
746 return;
747
748 else:
749 if _instance.isBool():
750 _lower = newtext.lower();
751 if _lower.startswith("t") or _lower.startswith("y") or _lower.strip()=="1":
752 newtext = 1
753 elif _lower.startswith("f") or _lower.startswith("n") or _lower.strip()=="0":
754 newtext = 0
755 else:
756 self.reporter.reportError("Invalid entry for a boolean variable: '%s'" % newtext)
757 return
758 _val = bool(newtext);
759 if _val == _instance.getValue():
760 self.reporter.reportNote("Boolean atom '%s' was not altered" % _instance.getName())
761 return
762 _instance.setBoolValue(_val)
763
764 elif _instance.isInt():
765 _val = int(newtext)
766 if _val == _instance.getValue():
767 self.reporter.reportNote("Integer atom '%s' was not altered" % _instance.getName())
768 return
769 _instance.setIntValue(_val)
770 else:
771 self.reporter.reportError("Attempt to set a non-real, non-boolean, non-integer value!")
772 return
773
774 # now that the variable is set, update the GUI and re-solve if desired
775 _iter = self.treestore.get_iter(path)
776 self.treestore.set_value(_iter,2,_instance.getValue())
777
778 if _instance.getType().isRefinedSolverVar():
779 self.treestore.set_value(_iter,3,BROWSER_FIXED_COLOR) # set the row green as fixed
780
781 self.do_solve_if_auto()
782
783 def make_children(self, value, piter ):
784 if value.isCompound():
785 children=value.getChildren();
786 for child in children:
787 _name = child.getName();
788 _piter = self.make_row(piter,_name,child)
789 _path = self.treestore.get_path(_piter)
790 self.otank[_path]=(_name,child)
791 #self.reporter.reportError("2 Added %s at path %s" % (_name,repr(_path)))
792
793 def make(self, name=None, value=None, path=None, depth=1):
794 if path is None:
795 # make root node
796 piter = self.make_row( None, name, value )
797 path = self.treestore.get_path( piter )
798 self.otank[ path ] = (name, value)
799 #self.reporter.reportError("4 Added %s at path %s" % (name, path))
800 else:
801 name, value = self.otank[ path ]
802
803 piter = self.treestore.get_iter( path )
804 if not self.treestore.iter_has_child( piter ):
805 self.make_children(value,piter)
806
807 if depth:
808 for i in range( self.treestore.iter_n_children( piter ) ):
809 self.make( path = path+(i,), depth = depth - 1 )
810 else:
811 self.treeview.expand_row("0",False)
812
813 def row_expanded( self, treeview, piter, path ):
814 self.make( path = path )
815
816 # ----------------------------------
817 # ERROR PANEL
818
819 def get_error_row_data(self,sev,filename,line,msg):
820 _sevicon = {
821 0: self.iconok
822 ,1: self.iconinfo
823 ,2: self.iconwarning
824 ,3: self.iconerror
825 ,4: self.iconinfo
826 ,5: self.iconwarning
827 ,6: self.iconerror
828 }[sev]
829
830 _fontweight = pango.WEIGHT_NORMAL
831 if sev==6:
832 _fontweight = pango.WEIGHT_BOLD
833
834 _fgcolor = "black"
835 if sev==4:
836 _fgcolor = "#888800"
837 elif sev==5:
838 _fgcolor = "#884400"
839 elif sev==6:
840 _fgcolor = "#880000"
841 elif sev==0:
842 _fgcolor = BROWSER_FIXED_COLOR
843
844 if not filename and not line:
845 _fileline = ""
846 else:
847 if(len(filename) > 25):
848 filename = "..."+filename[-22:]
849 _fileline = filename + ":" + str(line)
850
851 _res = [_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight]
852 #print _res
853 return _res
854
855 def error_callback(self,sev,filename,line,msg):
856 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
857 path = self.errorstore.get_path(pos)
858 col = self.errorview.get_column(3)
859 self.errorview.scroll_to_cell(path,col)
860
861 return 0;
862
863 # --------------------------------
864 # BUTTON METHODS
865
866 def open_click(self,*args):
867 dialog = gtk.FileChooserDialog("Open file...",
868 None,
869 gtk.FILE_CHOOSER_ACTION_OPEN,
870 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
871 gtk.STOCK_OPEN, gtk.RESPONSE_OK))
872 dialog.set_default_response(gtk.RESPONSE_OK)
873 dialog.set_transient_for(self.window)
874 dialog.set_modal(True)
875
876 filter = gtk.FileFilter()
877 filter.set_name("*.a4c, *.a4l")
878 filter.add_pattern("*.[Aa]4[Cc]")
879 filter.add_pattern("*.[Aa]4[Ll]")
880 dialog.add_filter(filter)
881
882 filter = gtk.FileFilter()
883 filter.set_name("All files")
884 filter.add_pattern("*")
885 dialog.add_filter(filter)
886
887 response = dialog.run()
888 _filename = dialog.get_filename()
889 print "FILENAME SELECTED:",_filename
890 dialog.hide()
891
892 if response == gtk.RESPONSE_OK:
893 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
894 self.library.clear()
895 self.do_open( _filename)
896
897 def reload_click(self,*args):
898 _type = None
899 if(self.sim):
900 _type = self.sim.getType().getName().toString();
901
902 self.library.clear()
903 self.do_open(self.filename)
904
905 if _type:
906 _t = self.library.findType(_type)
907 self.do_sim(_t)
908
909 def solve_click(self,*args):
910 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
911 self.do_solve()
912
913 def check_click(self,*args):
914 self.do_check()
915 #self.reporter.reportError("CHECK clicked")
916
917 def preferences_click(self,*args):
918 if not self.sim:
919 self.reporter.reportError("No simulation created yet!");
920
921 _paramswin = SolverParametersWindow(self)
922 _paramswin.show()
923
924 def methodrun_click(self,*args):
925 _sel = self.methodsel.get_active_text()
926 if _sel:
927 _method = None
928 _methods = self.sim.getType().getMethods()
929 for _m in _methods:
930 if _m.getName()==_sel:
931 _method = _m
932 if not _method:
933 self.reporter.reportError("Method is not valid")
934 return
935 self.do_method(_method)
936 else:
937 self.reporter.reportError("No method selected")
938
939 def auto_toggle(self,button,*args):
940 self.is_auto = button.get_active()
941 self.automenu.set_active(self.is_auto)
942
943 if self.is_auto:
944 self.reporter.reportSuccess("Auto mode is now ON")
945 else:
946 self.reporter.reportSuccess("Auto mode is now OFF")
947
948 def on_file_quit_click(self,*args):
949 self.do_quit()
950
951 def on_tools_auto_toggle(self,checkmenuitem,*args):
952 self.is_auto = checkmenuitem.get_active()
953 self.autotoggle.set_active(self.is_auto)
954
955 def on_help_about_click(self,*args):
956 _xml = gtk.glade.XML(config.GLADE_FILE,"aboutdialog")
957 _about = _xml.get_widget("aboutdialog")
958 _about.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
959 _about.set_transient_for(self.window);
960 _about.set_version(VERSION)
961 _about.run()
962 _about.destroy()
963
964 def on_help_contents_click(self,*args):
965 _help = Help(HELP_ROOT)
966 _help.run()
967
968 def on_find_fixable_variables_activate(self,*args):
969 v = self.sim.getFixableVariables()
970 for var in v:
971 print "FIXABLE:",var
972
973 def create_observer(self,name=None):
974 if name==None:
975 name="New Observer"
976
977 _xml = gtk.glade.XML(config.GLADE_FILE,"observervbox");
978 _label = gtk.Label();
979 _label.set_text(name)
980 _tab = self.maintabs.append_page(_xml.get_widget("observervbox"),_label);
981 self.observers.append(ObserverTab(_xml, name, self, _tab))
982
983 def sync_observers(self):
984 for _o in self.observers:
985 _o.sync()
986
987 # ------------------------------
988 # CONTEXT MENU
989
990 def on_treeview_event(self,widget,event):
991 _contextmenu = False;
992 if event.type==gtk.gdk.KEY_PRESS and gtk.gdk.keyval_name(event.keyval)=='Menu':
993 _contextmenu = True
994 _path, _col = self.treeview.get_cursor()
995 _button = 3;
996 elif event.type==gtk.gdk.BUTTON_PRESS:
997 if event.button == 3:
998 _contextmenu = True
999 _x = int(event.x)
1000 _y = int(event.y)
1001 _button = event.button
1002 _pthinfo = self.treeview.get_path_at_pos(_x, _y)
1003 if _pthinfo == None:
1004 return
1005 _path, _col, _cellx, _celly = _pthinfo
1006
1007 # which button was clicked?
1008 if not _contextmenu:
1009 return
1010
1011 _canpop = False;
1012 # self.reporter.reportError("Right click on %s" % self.otank[_path][0])
1013 _instance = self.otank[_path][1]
1014 if _instance.getType().isRefinedSolverVar():
1015 _canpop = True;
1016 self.observemenuitem.set_sensitive(True)
1017 if _instance.isFixed():
1018 self.fixmenuitem.set_sensitive(False)
1019 self.freemenuitem.set_sensitive(True)
1020 else:
1021 self.fixmenuitem.set_sensitive(True)
1022 self.freemenuitem.set_sensitive(False)
1023 elif _instance.isRelation():
1024 _canpop = True;
1025 self.propsmenuitem.set_sensitive(True)
1026
1027 if _instance.isPlottable():
1028 self.plotmenuitem.set_sensitive(True)
1029 _canpop = True;
1030 else:
1031 self.plotmenuitem.set_sensitive(False)
1032
1033 if not _canpop:
1034 return
1035
1036 self.treeview.grab_focus()
1037 self.treeview.set_cursor( _path, _col, 0)
1038 self.treecontext.popup( None, None, None, _button, event.time)
1039 return 1
1040
1041 def fix_activate(self,widget):
1042 _path,_col = self.treeview.get_cursor()
1043 _name, _instance = self.otank[_path]
1044 self.set_fixed(_instance,True);
1045 _instance.setFixed(True)
1046 return 1
1047
1048 def free_activate(self,widget):
1049 _path,_col = self.treeview.get_cursor()
1050 _instance = self.otank[_path][1]
1051 self.set_fixed(_instance,False)
1052 return 1
1053
1054 def plot_activate(self,widget):
1055 self.reporter.reportNote("plot_activate...");
1056 _path,_col = self.treeview.get_cursor()
1057 _instance = self.otank[_path][1]
1058 if not _instance.isPlottable():
1059 self.reporter.reportError("Can't plot instance %s" % _instance.getName().toString())
1060 return
1061 else:
1062 self.reporter.reportNote("Instance %s about to be plotted..." % _instance.getName().toString())
1063
1064 print("Plotting instance '%s'..." % _instance.getName().toString())
1065
1066 _plot = _instance.getPlot()
1067
1068 print "Title: ", _plot.getTitle()
1069 _plot.show(True)
1070
1071 return 1
1072
1073 def props_activate(self,widget):
1074 _path,_col = self.treeview.get_cursor()
1075 _instance = self.otank[_path][1]
1076 if _instance.isRelation():
1077 print "Relation '"+_instance.getName().toString()+"':", \
1078 _instance.getRelationAsString(self.sim.getModel())
1079 _dia = RelPropsWin(self,_instance);
1080 _dia.run();
1081 elif _instance.getType().isRefinedSolverVar():
1082 _dia = VarPropsWin(self,_instance);
1083 _dia.run();
1084 else:
1085 self.reporter.reportWarning("Select a variable first...")
1086
1087 def observe_activate(self,widget):
1088 _path,_col = self.treeview.get_cursor()
1089 _instance = self.otank[_path][1]
1090 if _instance.getType().isRefinedSolverVar():
1091 print "OBSERVING",_instance.getName().toString()
1092 if len(self.observers) > 1:
1093 self.reporter.reportError("Not implemented: multiple observers")
1094 return
1095 if len(self.observers) ==0:
1096 self.create_observer()
1097 _observer = self.observers[0]
1098 _observer.add_instance(_instance)
1099
1100 def delete_event(self, widget, event):
1101 self.do_quit()
1102 return False
1103
1104 def test():
1105 import ascend
1106 b = Browser();
1107 b.run()
1108
1109 if __name__ == "__main__":
1110 test()

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