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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1006 - (show annotations) (download) (as text)
Tue Jan 2 11:13:34 2007 UTC (15 years, 6 months ago) by johnpye
File MIME type: text/x-python
File size: 34768 byte(s)
Fixed hourglass cursor on exit 'check' dialog with fixable variables
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+"...\r")
9 sys.stderr.flush()
10
11 try:
12 #print_loading_status("Loading PSYCO")
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 import os.path
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 LIBASCEND/ascpy")
37 import ascpy
38
39 print_loading_status("Loading PyGTK, glade, pango")
40
41 import pygtk
42 pygtk.require('2.0')
43 import gtk
44 import gtk.glade
45 import pango
46
47 print_loading_status("Loading python matplotlib")
48 try:
49 import matplotlib
50 matplotlib.use('GTKAgg')
51
52 try:
53 print_loading_status("Trying python numarray")
54 import numarray
55 matplotlib.rcParams['numerix'] = 'numarray'
56 print_loading_status("","Using python module numarray")
57 except ImportError:
58 try:
59 print_loading_status("Trying python numpy")
60 import numpy
61 matplotlib.rcParams['numerix'] = 'numpy'
62 print_loading_status("","Using python module numpy")
63 except ImportError:
64 try:
65 print_loading_status("Trying python Numeric")
66 import Numeric
67 matplotlib.rcParams['numerix'] = 'Numeric'
68 print_loading_status("","Using python module Numeric")
69 except ImportError:
70 print_loading_status("","FAILED TO LOAD A NUMERIC MODULE FOR PYTHON")
71
72 except ImportError,e:
73 print_loading_status("","FAILED TO LOAD MATPLOTLIB")
74 raise RuntimeError("Failed to load MATPLOTLIB (is it installed?). Details:"+str(e))
75
76 print_loading_status("Loading IPython")
77 import console;
78 if not console.have_ipython:
79 print_loading_status("","IPython couldn't be loaded")
80
81 print_loading_status("Loading ASCEND python modules")
82 from preferences import * # loading/saving of .ini options
83 from solverparameters import * # 'solver parameters' window
84 from help import * # viewing help files
85 from incidencematrix import * # incidence/sparsity matrix matplotlib window
86 from observer import * # observer tab support
87 from properties import * # solver_var properties dialog
88 from varentry import * # for inputting of variables with units
89 from diagnose import * # for diagnosing block non-convergence
90 from solverreporter import * # solver status reporting
91 from modelview import * # model browser
92 from integrator import * # integrator dialog
93 from infodialog import * # general-purpose textual information dialog
94 from versioncheck import * # version check (contacts ascend.cruncher2.dyndns.org)
95 import config
96
97 except RuntimeError, e:
98 print "ASCEND had problems starting up. Please report the following"
99 print "error message at http://mantis.cruncher2.dyndns.org/."
100 print "\n\nFull error message:",str(e)
101 print "\n\nPress ENTER to close this window."
102 sys.stdout.flush()
103 sys.stdin.readline();
104 sys.exit();
105
106 except ImportError, e:
107 print "\n\n------------------ ERROR ---------------------"
108 print "ASCEND had problems importing required models."
109 print "\nPlease ensure you have all the runtime prerequisites installed."
110 print "Please then report a bug if you continue to have problems."
111 print "\nFull error message:",str(e)
112 if platform.system()=="Windows":
113 print "\nYou will also need to report the contents of any popup error"
114 print "messages from Windows if any were shown."
115 print "\n\nPress ENTER to close this window."
116 sys.stdout.flush()
117 sys.stdin.readline();
118 sys.exit();
119
120 print_loading_status("Starting GUI")
121
122 # This is my first ever GUI code so please be nice :)
123 # But I *have* at least read
124 # http://www.joelonsoftware.com/uibook/chapters/fog0000000057.html
125 # and leafed through
126 # http://developer.gnome.org/projects/gup/hig/
127
128 # The fancy tree-view gizmo is the GtkTreeView object. See the article
129 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/300304
130 # for the original source code on which my implementation was based.
131
132 ESCAPE_KEY = 65307
133
134 HELP_ROOT = None
135
136 #======================================
137 # Browser is the main ASCEND library/model browser window
138
139 class Browser:
140
141 # ---------------------------------
142 # SETUP
143
144 def __init__(self,librarypath=None,assetspath=None):
145
146 if assetspath==None:
147 assetspath=config.PYGTK_ASSETS
148
149 #--------
150 # load the file referenced in the command line, if any
151
152 print_loading_status("Parsing options","CONFIG = %s"%config.VERSION)
153
154 parser = optparse.OptionParser(usage="%prog [[-m typename] file]", version="gtkbrowser $rev$" )
155 # add options here if we want
156
157 parser.add_option("-m", "--model"
158 ,action="store", type="string", dest="model"
159 ,help="specify the model to instantiate upon loading modules")
160
161 parser.add_option("--pygtk-assets"
162 ,action="store", type="string", dest="assets_dir"
163 ,help="override the configuration value for the location of assets"\
164 +" required by PyGTK for the ASCEND GUI, optional"
165 ,default=assetspath
166 )
167
168 parser.add_option("--library"
169 ,action="store", type="string", dest="library_path"
170 ,help="override the configuration value for the library path"
171 ,default=librarypath
172 )
173
174 parser.add_option("--no-auto-sim"
175 ,action="store_false", dest="auto_sim"
176 ,help="disable auto-instantiation of MODEL named as the file stem"
177 ,default=True
178 )
179
180 (self.options, args) = parser.parse_args()
181
182 #print "OPTIONS_______________:",self.options
183
184 self.assets_dir = self.options.assets_dir
185
186 self.observers = []
187 self.clip = None
188
189 #--------
190 # load up the preferences ini file
191
192 print_loading_status("Loading preferences")
193
194 self.prefs = Preferences()
195
196 _prefpath = self.prefs.getStringPref("Directories","librarypath",None)
197 _preffileopenpath = self.prefs.getStringPref("Directories","fileopenpath",None)
198
199 #--------
200 # set up library path and the path to use for File->Open dialogs
201
202 if self.options.library_path != None:
203 _path = os.path.abspath(self.options.library_path)
204 _pathsrc = "command line options"
205 # when a special path is specified, use the last path component as the file-open location
206 if platform.system()=="Windows":
207 self.fileopenpath = _path.split(":").pop()
208 else:
209 self.fileopenpath = _path.split(":").pop()
210 else:
211 if _prefpath:
212 _path = _prefpath
213 _pathsrc = "user preferences"
214 else:
215 _path = config.LIBRARY_PATH
216 _pathsrc = "default (config.py)"
217
218 if _preffileopenpath:
219 self.fileopenpath = _preffileopenpath
220 else:
221 self.fileopenpath = _path
222
223 #--------
224 # Create the ASCXX 'Library' object
225
226 print_loading_status("Creating ASCEND 'Library' object","PATH = "+_path+" FROM "+_pathsrc)
227 self.library = ascpy.Library(_path)
228
229 self.sim = None
230
231 #-------------------
232 # Set up the window and main widget actions
233
234 self.glade_file = os.path.join(self.assets_dir,config.GLADE_FILE)
235
236 print_loading_status("Setting up windows") #,"GLADE_FILE = %s" % self.glade_file)
237
238 glade = gtk.glade.XML(self.glade_file,"browserwin")
239
240 self.window = glade.get_widget("browserwin")
241
242
243 if not self.window:
244 raise RuntimeError("Couldn't load window from glade file")
245
246 _display = self.window.get_screen().get_display().get_name()
247 _geom=self.prefs.getGeometrySizePosition(_display,"browserwin")
248 if _geom:
249 self.window.resize(_geom[0],_geom[1])
250 self.window.move(_geom[2],_geom[3])
251
252 self.window.connect("delete_event", self.delete_event)
253
254 self.browserpaned=glade.get_widget("browserpaned")
255 _geom2=self.prefs.getGeometryValue(_display,"browserpaned")
256 if _geom2:
257 self.browserpaned.set_position(_geom2)
258
259 self.openbutton=glade.get_widget("openbutton")
260 self.openbutton.connect("clicked",self.open_click)
261
262 self.reloadbutton=glade.get_widget("reloadbutton")
263 self.reloadbutton.connect("clicked",self.reload_click)
264
265 self.solvebutton=glade.get_widget("solvebutton")
266 self.solvebutton.connect("clicked",self.solve_click)
267
268 self.integratebutton=glade.get_widget("integratebutton")
269 self.integratebutton.connect("clicked",self.integrate_click)
270
271 self.checkbutton=glade.get_widget("checkbutton")
272 self.checkbutton.connect("clicked",self.check_click)
273
274 self.autotoggle=glade.get_widget("autotoggle")
275 self.automenu = glade.get_widget("automenu")
276 self.autotoggle.connect("toggled",self.auto_toggle)
277
278 self.methodrunbutton=glade.get_widget("methodrunbutton")
279 self.methodrunbutton.connect("clicked",self.methodrun_click)
280
281 self.methodsel=glade.get_widget("methodsel")
282
283 self.maintabs = glade.get_widget("maintabs")
284
285 self.statusbar = glade.get_widget("statusbar")
286
287 self.menu = glade.get_widget("browsermenu")
288
289 self.show_solving_popup=glade.get_widget("show_solving_popup")
290 self.show_solving_popup.set_active(self.prefs.getBoolPref("SolverReporter","show_popup",True))
291 self.close_on_converged=glade.get_widget("close_on_converged")
292 self.close_on_converged.set_active(self.prefs.getBoolPref("SolverReporter","close_on_converged",True))
293 self.close_on_nonconverged=glade.get_widget("close_on_nonconverged")
294 self.close_on_nonconverged.set_active(self.prefs.getBoolPref("SolverReporter","close_on_nonconverged",True))
295 self.solver_engine=glade.get_widget("solver_engine")
296
297 self.use_relation_sharing=glade.get_widget("use_relation_sharing")
298 self.use_relation_sharing.set_active(self.prefs.getBoolPref("Compiler","use_relation_sharing",True))
299
300 glade.signal_autoconnect(self)
301
302 #-------
303 # Status icons
304
305 self.fixedimg = gtk.Image()
306 self.fixedimg.set_from_file(os.path.join(self.options.assets_dir,'locked.png'))
307
308 self.iconstatusunknown = None
309 self.iconfixed = self.fixedimg.get_pixbuf()
310 self.iconsolved = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
311 self.iconactive = self.window.render_icon(gtk.STOCK_NO,gtk.ICON_SIZE_MENU)
312 self.iconunsolved = None
313
314 self.statusicons={
315 ascpy.ASCXX_VAR_STATUS_UNKNOWN: self.iconstatusunknown
316 ,ascpy.ASCXX_VAR_FIXED: self.iconfixed
317 ,ascpy.ASCXX_VAR_SOLVED: self.iconsolved
318 ,ascpy.ASCXX_VAR_ACTIVE: self.iconactive
319 ,ascpy.ASCXX_VAR_UNSOLVED: self.iconunsolved
320 }
321
322
323 self.statusmessages={
324 ascpy.ASCXX_VAR_STATUS_UNKNOWN: "Status unknown"
325 ,ascpy.ASCXX_VAR_FIXED: "Fixed"
326 ,ascpy.ASCXX_VAR_SOLVED: "Converged"
327 ,ascpy.ASCXX_VAR_ACTIVE: "Active (unconverged)"
328 ,ascpy.ASCXX_VAR_UNSOLVED: "Not yet visited"
329 }
330
331 #-------------------
332 # waitwin
333
334 self.waitwin = gtk.gdk.Window(self.window.window,
335 gtk.gdk.screen_width(),
336 gtk.gdk.screen_height(),
337 gtk.gdk.WINDOW_CHILD,
338 0,
339 gtk.gdk.INPUT_ONLY)
340
341 _cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
342 self.waitwin.set_cursor(_cursor)
343
344 #-------------------
345 # pixbufs to be used in the error listing
346
347 self.iconok = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
348 self.iconinfo = self.window.render_icon(gtk.STOCK_DIALOG_INFO,gtk.ICON_SIZE_MENU)
349 self.iconwarning = self.window.render_icon(gtk.STOCK_DIALOG_WARNING,gtk.ICON_SIZE_MENU)
350 self.iconerror = self.window.render_icon(gtk.STOCK_DIALOG_ERROR,gtk.ICON_SIZE_MENU)
351
352 #--------------------
353 # pixbufs for solver_var status
354
355 #--------------------
356 # set up the error view
357
358 self.errorview = glade.get_widget("errorview")
359 errstorecolstypes = [gtk.gdk.Pixbuf,str,str,str,int]
360 self.errorstore = gtk.TreeStore(*errstorecolstypes)
361 errtitles = ["","Location","Message"];
362 self.errorview.set_model(self.errorstore)
363 self.errcols = [ gtk.TreeViewColumn() for _type in errstorecolstypes]
364
365 i = 0
366 for tvcolumn in self.errcols[:len(errtitles)]:
367 tvcolumn.set_title(errtitles[i])
368 self.errorview.append_column(tvcolumn)
369
370 if i>0:
371 _renderer = gtk.CellRendererText()
372 tvcolumn.pack_start(_renderer, True)
373 tvcolumn.add_attribute(_renderer, 'text', i)
374 if(i==2):
375 tvcolumn.add_attribute(_renderer, 'foreground', 3)
376 tvcolumn.add_attribute(_renderer, 'weight', 4)
377 else:
378 _renderer1 = gtk.CellRendererPixbuf()
379 tvcolumn.pack_start(_renderer1, False)
380 tvcolumn.add_attribute(_renderer1, 'pixbuf', int(0))
381
382 i = i + 1
383
384
385 #--------------------
386 # set up the error reporter callback
387 self.reporter = ascpy.getReporter()
388 self.reporter.setPythonErrorCallback(self.error_callback)
389
390
391 #-------
392 # Solver engine list
393
394 _slvlist = ascpy.getSolvers()
395 self.solver_engine_menu = gtk.Menu()
396 self.solver_engine_menu.show()
397 self.solver_engine.set_submenu(self.solver_engine_menu)
398 self.solver_engine_menu_dict = {}
399 _fmi = None
400 for _s in _slvlist:
401 _mi = gtk.RadioMenuItem(_fmi,_s.getName(),False)
402 if _fmi==None:
403 _fmi = _mi
404 _mi.show()
405 _mi.connect('toggled',self.on_select_solver_toggled,_s.getName())
406 self.solver_engine_menu.append(_mi)
407 self.solver_engine_menu_dict[_s.getName()]=_mi
408
409 _pref_solver = self.prefs.getStringPref("Solver","engine","QRSlv")
410 _mi = self.solver_engine_menu_dict.get(_pref_solver)
411 if _mi:
412 _mi.set_active(1)
413
414 #--------
415 # Assign an icon to the main window
416
417 self.icon = None
418 if config.ICON_EXTENSION:
419 _iconpath = ""
420 try:
421 _icon = gtk.Image()
422 _iconpath = os.path.join(self.assets_dir,'ascend'+config.ICON_EXTENSION)
423 _icon.set_from_file(_iconpath)
424 _iconpbuf = _icon.get_pixbuf()
425 self.window.set_icon(_iconpbuf)
426 self.icon = _iconpbuf
427 except Exception, e:
428 print "FAILED TO SET APPLICATION ICON PATH '%s': %s" % (_iconpath,str(e))
429 self.reporter.reportError("FAILED to set application icon '%s': %s"
430 % (_iconpath,str(e))
431 )
432
433 #-------------------
434 # set up the module view
435
436 self.modtank = {}
437 self.moduleview = glade.get_widget("moduleview")
438 modulestorecoltypes = [str, str, int] # bool=can-be-instantiated
439 self.modulestore = gtk.TreeStore(*modulestorecoltypes)
440 moduleviewtitles = ["Module name", "Filename"]
441 self.moduleview.set_model(self.modulestore)
442 self.modcols = [ gtk.TreeViewColumn() for _type in modulestorecoltypes]
443 i = 0
444 for modcol in self.modcols[:len(moduleviewtitles)]:
445 modcol.set_title(moduleviewtitles[i])
446 self.moduleview.append_column(modcol)
447 _renderer = gtk.CellRendererText()
448 modcol.pack_start(_renderer, True)
449 modcol.add_attribute(_renderer, 'text', i)
450 modcol.add_attribute(_renderer,'weight',2)
451 i = i + 1
452 self.moduleview.connect("row-activated", self.module_activated )
453
454 #--------------------
455 # set up the methods combobox
456
457 self.methodstore = gtk.ListStore(str)
458 self.methodsel.set_model(self.methodstore)
459 _methodrenderer = gtk.CellRendererText()
460 self.methodsel.pack_start(_methodrenderer, True)
461 self.methodsel.add_attribute(_methodrenderer, 'text',0)
462
463 #--------
464 # set up the instance browser view
465
466 self.modelview = ModelView(self, glade)
467
468 #--------
469 # set up the tabs
470 self.tabs = {}
471 self.activetab = None # most recent observer tab
472
473 #--------
474 # set the state of the 'auto' toggle
475
476 self.is_auto = self.prefs.getBoolPref("Browser","auto_solve",True)
477 self.autotoggle.set_active(self.is_auto)
478 self.automenu.set_active(self.is_auto)
479
480 #--------
481 # tell libascend about this 'browser' object
482
483 print dir(ascpy.Registry())
484 ascpy.Registry().set("browser",self)
485
486 #--------
487 # options
488
489 if(len(args)==1):
490 self.do_open(args[0])
491
492 print "Options: ",self.options
493
494 _model = None
495 if self.options.model:
496 _model = self.options.model
497 print "MODEL: '%s'" % _model
498 elif self.options.auto_sim:
499 _head, _tail = os.path.split(args[0])
500 if(_tail):
501 _model, _ext = os.path.splitext(_tail)
502
503 if _model:
504 try:
505 _t=self.library.findType(_model)
506 try:
507 self.do_sim(_t)
508 if not self.options.model:
509 self.reporter.reportNote("Instantiated self-titled model '%s'" %_model)
510 except RuntimeError, e:
511 self.reporter.reportError("Failed to create instance of '%s': %s"
512 %(_model, str(e))
513 );
514 except RuntimeError, e:
515 if self.options.model:
516 self.reporter.reportError("Unknown model type '%s': %s"
517 %(_model, str(e))
518 );
519
520 def run(self):
521 self.window.show()
522 print_loading_status("ASCEND is now running")
523 gtk.main()
524
525 # ------------------
526 # SOLVER LIST
527
528 def set_solver(self,solvername):
529 """ this sets the active solver in the GUI, which is the default applied to newly instantiated models """
530 self.solver = ascpy.Solver(solvername)
531 self.prefs.setStringPref("Solver","engine",solvername)
532 self.reporter.reportNote("Set solver engine to '%s'" % solvername)
533
534 # --------------------------------------------
535 # MAJOR GUI COMMANDS
536
537 def on_fix_variable_activate(self,*args):
538 self.modelview.on_fix_variable_activate(*args)
539
540 def on_free_variable_activate(self,*args):
541 self.modelview.on_free_variable_activate(*args)
542
543 def on_select_solver_toggled(self,widget,solvername):
544 if widget.get_active():
545 self.set_solver(solvername)
546
547 def do_open(self,filename):
548 # TODO does the user want to lose their work?
549 # TODO do we need to chdir?
550
551 _context = self.statusbar.get_context_id("do_open")
552
553 self.errorstore.clear()
554 self.modelview.clear()
555
556 # self.library.clear()
557
558 print "Filename =",filename
559 self.statusbar.push(_context,"Loading '"+filename+"'")
560 self.library.load(filename)
561 print "Statusbar =",self.statusbar
562 try:
563 self.statusbar.pop(_context)
564 except TypeError,e:
565 print "For some reason, a type error (context=%s,filename=%s): %s" % (_context,filename,e)
566
567 self.filename = filename
568
569 # Load the current list of modules into self.modules
570 self.modtank = {}
571 self.modulestore.clear()
572 modules = self.library.getModules()
573 #self.library.listModules()
574 try:
575 _lll=len(modules)
576 except:
577 _msg = "UNABLE TO ACCESS MODULES LIST. This is bad.\n"+\
578 "Check your SWIG configuration (check for warnings during build)."
579
580 self.reporter.reportError(_msg)
581 raise RuntimeError(_msg)
582
583 for m in reversed(modules):
584 _n = str( m.getName() )
585 _f = str( m.getFilename() )
586 #print "ADDING ROW name %s, file = %s" % (_n, _f)
587 _r = self.modulestore.append(None, [ _n, _f, pango.WEIGHT_NORMAL ])
588 for t in self.library.getModuleTypes(m):
589 _n = t.getName()
590 _hasparams = t.hasParameters()
591 if _hasparams:
592 _w = pango.WEIGHT_NORMAL
593 else:
594 _w = pango.WEIGHT_BOLD
595
596 #print "ADDING TYPE %s" % _n
597 _piter = self.modulestore.append(_r , [ _n, "", _w ])
598 _path = self.modulestore.get_path(_piter)
599 self.modtank[_path]=t
600
601 #print "DONE ADDING MODULES"
602
603 self.sim = None;
604 self.maintabs.set_current_page(0);
605
606 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
607 # for details on how the 'wait cursor' is done.
608 def start_waiting(self, message):
609 self.waitcontext = self.statusbar.get_context_id("waiting")
610 self.statusbar.push(self.waitcontext,message)
611
612 if self.waitwin:
613 self.waitwin.show()
614
615 while gtk.events_pending():
616 gtk.main_iteration()
617
618 def stop_waiting(self):
619 if self.waitwin:
620 self.statusbar.pop(self.waitcontext)
621 self.waitwin.hide()
622
623 def do_sim(self, type_object):
624 self.sim = None;
625 # TODO: clear out old simulation first!
626
627 print "DO_SIM(%s)" % str(type_object.getName())
628 self.start_waiting("Compiling...")
629
630 try:
631 _v = self.prefs.getBoolPref("Compiler","use_relation_sharing",True)
632 ascpy.getCompiler().setUseRelationSharing(_v)
633
634 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim",False)
635
636 self.reporter.reportNote("SIMULATION ASSIGNED")
637 except RuntimeError, e:
638 self.stop_waiting()
639 self.reporter.reportError(str(e))
640 return
641
642 print "...DONE 'getSimulation'"
643 self.stop_waiting()
644
645 # get method names and load them into the GUI
646 self.methodstore.clear()
647 _methods = self.sim.getType().getMethods()
648 _activemethod = None;
649 for _m in _methods:
650 _i = self.methodstore.append([_m.getName()])
651 if _m.getName()=="on_load":
652 self.methodsel.set_active_iter(_i)
653
654 self.modelview.setSimulation(self.sim)
655
656 # run the 'on_load' method
657 self.start_waiting("Running default method...")
658 try:
659 self.reporter.reportNote("SIMULATION CREATED, RUNNING DEFAULT METHOD NOW...")
660 self.sim.runDefaultMethod()
661 except RuntimeError, e:
662 self.stop_waiting()
663 self.reporter.reportError(str(e))
664 return
665 self.stop_waiting()
666
667 self.modelview.refreshtree()
668
669 def do_solve_if_auto(self):
670 if self.is_auto:
671 self.sim.checkInstance()
672 self.do_solve()
673 else:
674 self.sim.processVarStatus()
675 self.modelview.refreshtree()
676
677 self.sync_observers()
678
679 def do_solve(self):
680 if not self.sim:
681 self.reporter.reportError("No model selected yet")
682 return
683
684 try:
685 self.sim.build()
686 except RuntimeError,e:
687 self.reporter.reportError("Couldn't build system: %s",str(e));
688 return
689
690 self.start_waiting("Solving with %s..." % self.solver.getName())
691
692 if self.prefs.getBoolPref("SolverReporter","show_popup",True):
693 reporter = PopupSolverReporter(self,self.sim.getNumVars())
694 else:
695 reporter = SimpleSolverReporter(self)
696
697 self.sim.solve(self.solver,reporter)
698
699 self.stop_waiting()
700
701 self.modelview.refreshtree()
702
703 def do_integrate(self):
704 if not self.sim:
705 self.reporter.reportError("No model selected yet")
706 return
707 integwin = IntegratorWindow(self,self.sim)
708 _integratorreporter = integwin.run()
709 if _integratorreporter!=None:
710 _integratorreporter.run()
711 self.sim.processVarStatus()
712 self.modelview.refreshtree()
713
714
715 def do_check(self):
716 if not self.sim:
717 self.reporter.reportError("No simulation yet")
718 return
719
720 self.start_waiting("Checking system...")
721
722 try:
723 self.sim.checkInstance()
724 self.reporter.reportWarning("System instance check run, check above for error (if any).")
725 # the above gives output but doesn't throw errors or return a status.
726 # ... this is a problem (at the C level)
727
728 status = self.sim.checkDoF()
729 if status==ascpy.ASCXX_DOF_UNDERSPECIFIED:
730 self.on_show_fixable_variables_activate(None)
731 elif status==ascpy.ASCXX_DOF_OVERSPECIFIED:
732 self.on_show_freeable_variables_activate(None)
733 elif status==ascpy.ASCXX_DOF_STRUCT_SINGULAR:
734 if not self.sim.checkStructuralSingularity():
735 sing = self.sim.getSingularityInfo()
736 title = "Structural singularity"
737 text = title
738 text += "\n\nThe singularity can be reduced by freeing the following variables:"
739 msgs = {
740 "The singularity can be reduced by freeing the following variables" : sing.freeablevars
741 ,"Relations involved in the structural singularity" : sing.rels
742 ,"Variables involved in the structural singularity" : sing.vars
743 }
744 for k,v in msgs.iteritems():
745 text+="\n\n%s:" % k
746 if len(v):
747 _l = [j.getName() for j in v]
748 _l.sort()
749 text+= "\n\t" + "\n\t".join(_l)
750 else:
751 text += "\nnone"
752
753 _dialog = InfoDialog(self,self.window,text,title)
754 _dialog.run()
755 else:
756 self.reporter.reportNote("System DoF check OK")
757
758 except RuntimeError, e:
759 self.stop_waiting()
760 self.reporter.reportError(str(e))
761 return
762
763 self.stop_waiting()
764 self.modelview.refreshtree()
765
766 def do_method(self,method):
767 if not self.sim:
768 self.reporter.reportError("No model selected yet")
769
770 self.sim.run(method)
771 self.sim.processVarStatus()
772 self.modelview.refreshtree()
773
774 def do_quit(self):
775 print_loading_status("Saving window location")
776 self.reporter.clearPythonErrorCallback()
777
778 _w,_h = self.window.get_size()
779 _t,_l = self.window.get_position()
780 _display = self.window.get_screen().get_display().get_name()
781 self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
782
783 _p = self.browserpaned.get_position()
784 self.prefs.setGeometryValue(_display,"browserpaned",_p);
785
786 print_loading_status("Saving current directory")
787 self.prefs.setStringPref("Directories","fileopenpath",self.fileopenpath)
788
789 self.prefs.setBoolPref("Browser","auto_solve",self.is_auto)
790
791 print_loading_status("Saving preferences")
792 # causes prefs to be saved unless they are still being used elsewher
793 del(self.prefs)
794
795 print_loading_status("Clearing error callback")
796 self.reporter.clearPythonErrorCallback()
797
798 print_loading_status("Closing down GTK")
799 gtk.main_quit()
800
801 print_loading_status("Clearing library")
802 self.library.clear()
803
804 print_loading_status("Quitting")
805
806 return False
807
808 def on_tools_sparsity_click(self,*args):
809
810 self.reporter.reportNote("Preparing incidence matrix...")
811 _im = self.sim.getIncidenceMatrix();
812
813 self.reporter.reportNote("Plotting incidence matrix...")
814
815 _sp = IncidenceMatrixWindow(_im);
816 _sp.run();
817
818 def on_tools_repaint_tree_activate(self,*args):
819 self.reporter.reportNote("Repainting model view...")
820 self.modelview.refreshtree()
821
822 def on_diagnose_blocks_click(self,*args):
823 try:
824 _bl = self.sim.getActiveBlock()
825 except RuntimeError, e:
826 self.reporter.reportError(str(e))
827 return
828 _db = DiagnoseWindow(self,_bl)
829 _db.run();
830
831 def on_add_observer_click(self,*args):
832 self.create_observer()
833
834 def on_keep_observed_click(self,*args):
835 print "KEEPING..."
836 if len(self.observers) <= 0:
837 self.reporter.reportError("No observer defined!")
838 return
839 self.tabs[self.currentobservertab].do_add_row()
840
841 def on_copy_observer_matrix_click(self,*args):
842 if self.clip == None:
843 self.clip = gtk.Clipboard()
844
845 if len(self.observers) <= 0:
846 self.reporter.reportError("No observer defined!")
847 return
848 self.tabs[self.currentobservertab].copy_to_clipboard(self.clip)
849
850 def on_use_relation_sharing_toggle(self,checkmenuitem,*args):
851 _v = checkmenuitem.get_active()
852 self.prefs.setBoolPref("Compiler","use_relation_sharing",_v)
853 self.reporter.reportNote("Relation sharing set to "+str(_v))
854
855 def on_show_solving_popup_toggle(self,checkmenuitem,*args):
856 _v = checkmenuitem.get_active()
857 self.prefs.setBoolPref("SolverReporter","show_popup",_v)
858 print "SET TO",_v
859
860 def on_close_on_converged_toggle(self,checkmenuitem,*args):
861 _v = checkmenuitem.get_active()
862 self.prefs.setBoolPref("SolverReporter","close_on_converged",_v)
863
864 def on_close_on_nonconverged_toggle(self,checkmenuitem,*args):
865 _v = checkmenuitem.get_active()
866 self.prefs.setBoolPref("SolverReporter","close_on_nonconverged",_v)
867
868 def on_show_variables_near_bounds_activate(self,*args):
869 _epsilon = 1e-4;
870 text = "Variables Near Bounds"
871 title=text;
872 text += "\n"
873 _vars = self.sim.getVariablesNearBounds(_epsilon)
874 if len(_vars):
875 for _v in _vars:
876 text += "\n%s"%_v.getName()
877 else:
878 text +="\nnone"
879 _dialog = InfoDialog(self,self.window,text,title)
880 _dialog.run()
881
882 # --------------------------------------------
883 # MODULE LIST
884
885 def module_activated(self, treeview, path, column, *args):
886 modules = self.library.getModules()
887 print "PATH",path
888 if len(path)==1:
889 self.reporter.reportNote("Launching of external editor not yet implemented")
890 elif len(path)==2:
891 if(self.modtank.has_key(path)):
892 _type = self.modtank[path];
893 self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
894 self.do_sim(_type)
895 else:
896 self.reporter.reportError("Didn't find type corresponding to row")
897
898 # ----------------------------------
899 # ERROR PANEL
900
901 def get_error_row_data(self,sev,filename,line,msg):
902 try:
903 _sevicon = {
904 0 : self.iconok
905 ,1 : self.iconinfo
906 ,2 : self.iconwarning
907 ,4 : self.iconerror
908 ,8 : self.iconinfo
909 ,16 : self.iconwarning
910 ,32 : self.iconerror
911 ,64 : self.iconerror
912 }[sev]
913 except KeyError:
914 _sevicon = self.iconerror
915
916 _fontweight = pango.WEIGHT_NORMAL
917 if sev==32 or sev==64:
918 _fontweight = pango.WEIGHT_BOLD
919
920 _fgcolor = "black"
921 if sev==8:
922 _fgcolor = "#888800"
923 elif sev==16:
924 _fgcolor = "#884400"
925 elif sev==32 or sev==64:
926 _fgcolor = "#880000"
927 elif sev==0:
928 _fgcolor = BROWSER_FIXED_COLOR
929
930 if not filename and not line:
931 _fileline = ""
932 else:
933 if(len(filename) > 25):
934 filename = "..."+filename[-22:]
935 _fileline = filename + ":" + str(line)
936
937 _res = (_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight)
938 #print _res
939 return _res
940
941 def error_callback(self,sev,filename,line,msg):
942 #print "SEV =",sev
943 #print "FILENAME =",filename
944 #print "LINE =",line
945 #print "MSG =",msg
946 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
947 path = self.errorstore.get_path(pos)
948 col = self.errorview.get_column(3)
949 self.errorview.scroll_to_cell(path,col)
950 return 0;
951
952 # --------------------------------
953 # BUTTON METHODS
954
955 def open_click(self,*args):
956 #print_loading_status("CURRENT FILEOPENPATH is",self.fileopenpath)
957 dialog = gtk.FileChooserDialog("Open ASCEND model...",
958 self.window,
959 gtk.FILE_CHOOSER_ACTION_OPEN,
960 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
961 )
962 dialog.set_current_folder(self.fileopenpath)
963 dialog.set_default_response(gtk.RESPONSE_OK)
964 dialog.set_transient_for(self.window)
965 dialog.set_modal(True)
966
967 filter = gtk.FileFilter()
968 filter.set_name("*.a4c, *.a4l")
969 filter.add_pattern("*.[Aa]4[Cc]")
970 filter.add_pattern("*.[Aa]4[Ll]")
971 dialog.add_filter(filter)
972
973 filter = gtk.FileFilter()
974 filter.set_name("All files")
975 filter.add_pattern("*")
976 dialog.add_filter(filter)
977
978 response = dialog.run()
979 _filename = dialog.get_filename()
980 print "\nFILENAME SELECTED:",_filename
981
982 _path = dialog.get_current_folder()
983 if _path:
984 self.fileopenpath = _path
985
986 dialog.hide()
987
988 if response == gtk.RESPONSE_OK:
989 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
990 self.library.clear()
991 self.do_open( _filename)
992
993 def reload_click(self,*args):
994 _type = None
995 if(self.sim):
996 _type = self.sim.getType().getName().toString();
997
998 self.library.clear()
999 self.do_open(self.filename)
1000
1001 if _type:
1002 _t = self.library.findType(_type)
1003 self.do_sim(_t)
1004
1005 def props_activate(self,widget,*args):
1006 return self.modelview.props_activate(self,widget,*args)
1007
1008 def observe_activate(self,widget,*args):
1009 return self.modelview.observe_activate(self,widget,*args)
1010
1011 def solve_click(self,*args):
1012 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
1013 self.do_solve()
1014
1015 def console_click(self,*args):
1016 try:
1017 console.start(self)
1018 except RuntimeError,e:
1019 self.reporter.reportError("Unable to start console: "+str(e));
1020
1021 def integrate_click(self,*args):
1022 self.do_integrate()
1023
1024 def check_click(self,*args):
1025 self.do_check()
1026 #self.reporter.reportError("CHECK clicked")
1027
1028 def preferences_click(self,*args):
1029 if not self.sim:
1030 self.reporter.reportError("No simulation created yet!");
1031 self.sim.setSolver(self.solver)
1032 _paramswin = SolverParametersWindow(self)
1033 _paramswin.show()
1034
1035 def methodrun_click(self,*args):
1036 _sel = self.methodsel.get_active_text()
1037 if _sel:
1038 _method = None
1039 _methods = self.sim.getType().getMethods()
1040 for _m in _methods:
1041 if _m.getName()==_sel:
1042 _method = _m
1043 if not _method:
1044 self.reporter.reportError("Method is not valid")
1045 return
1046 self.do_method(_method)
1047 else:
1048 self.reporter.reportError("No method selected")
1049
1050 def auto_toggle(self,button,*args):
1051 self.is_auto = button.get_active()
1052 if hasattr(self,'automenu'):
1053 self.automenu.set_active(self.is_auto)
1054 else:
1055 raise RuntimeError("no automenu")
1056
1057 #if self.is_auto:
1058 # self.reporter.reportSuccess("Auto mode is now ON")
1059 #else:
1060 # self.reporter.reportSuccess("Auto mode is now OFF")
1061
1062 def on_file_quit_click(self,*args):
1063 self.do_quit()
1064
1065 def on_tools_auto_toggle(self,checkmenuitem,*args):
1066 self.is_auto = checkmenuitem.get_active()
1067 self.autotoggle.set_active(self.is_auto)
1068
1069 def on_help_about_click(self,*args):
1070 _xml = gtk.glade.XML(self.glade_file,"aboutdialog")
1071 _about = _xml.get_widget("aboutdialog")
1072 _about.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
1073 _about.set_transient_for(self.window);
1074 _about.set_version(config.VERSION)
1075 _about.run()
1076 _about.destroy()
1077
1078 def on_help_contents_click(self,*args):
1079 _help = Help(HELP_ROOT)
1080 _help.run()
1081
1082 def on_help_check_for_updates_click(self,*args):
1083 v = VersionCheck()
1084 title = "Check for updates"
1085 text = "Your version is %s\n" % config.VERSION
1086 try:
1087 v.check()
1088 if config.VERSION==v.latest:
1089 text += "You are running the latest released version"
1090 else:
1091 text += "Latest version is %s\n" % v.latest
1092 if v.info:
1093 text += "Get more info at %s\n" % v.info
1094 if v.download:
1095 text += "Download from %s\n" % v.download
1096 except Exception, e:
1097 text += "\nUnable to check version\n"
1098 text += str(e)
1099
1100 _dialog = InfoDialog(self,self.window,text,title)
1101 _dialog.run()
1102
1103 def on_show_fixable_variables_activate(self,*args):
1104 v = self.sim.getFixableVariables()
1105 text = "Fixable Variables"
1106 title = text
1107 text += "\n"
1108 if len(v):
1109 for var in v:
1110 text += "\n%s"%var
1111 else:
1112 text += "\nnone"
1113 _dialog = InfoDialog(self,self.window,text,title)
1114 _dialog.run()
1115
1116 def on_show_freeable_variables_activate(self,*args):
1117 v = self.sim.getFreeableVariables()
1118
1119 text = "Freeable Variables"
1120 title = text
1121 text += "\n"
1122 if len(v):
1123 for var in v:
1124 text += "\n%s" % var
1125 else:
1126 text += "\nnone"
1127 _dialog = InfoDialog(self,self.window,text,title)
1128 _dialog.run()
1129
1130 def on_show_external_functions_activate(self,*args):
1131 v = self.library.getExtMethods()
1132 text = "External Functions"
1133 title = text
1134 text +="\nHere is the list of external functions currently present in"
1135 text +=" the Library:"
1136
1137 if len(v):
1138 for ext in v:
1139 text += "\n\n%s (%d inputs, %d outputs):" % \
1140 (ext.getName(), ext.getNumInputs(), ext.getNumOutputs())
1141 text += "\n%s" % ext.getHelp()
1142 else:
1143 text +="\n\nNone"
1144 _dialog = InfoDialog(self,self.window,text,title)
1145 _dialog.run()
1146
1147 def on_maintabs_switch_page(self,notebook,page,pagenum):
1148 print("Page switched to %d" % pagenum)
1149 if pagenum in self.tabs.keys():
1150 self.currentobservertab = pagenum
1151
1152 def create_observer(self,name=None):
1153 _xml = gtk.glade.XML(self.glade_file,"observervbox");
1154 _label = gtk.Label();
1155 _tab = self.maintabs.append_page(_xml.get_widget("observervbox"),_label);
1156 _obs = ObserverTab(xml=_xml, name=name, browser=self, tab=_tab)
1157 _label.set_text(_obs.name)
1158 self.observers.append(_obs)
1159 self.tabs[_tab] = _obs
1160 self.currentobservertab = _tab
1161 return _obs
1162
1163 def sync_observers(self):
1164 for _o in self.observers:
1165 _o.sync()
1166
1167 def delete_event(self, widget, event):
1168 self.do_quit()
1169 return False
1170
1171 def observe(self,instance):
1172 if len(self.observers) ==0:
1173 self.create_observer()
1174 _observer = self.tabs[self.currentobservertab]
1175 _observer.add_instance(instance)
1176
1177 if __name__ == "__main__":
1178 b = Browser();
1179 b.run()

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