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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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