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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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