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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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