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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3334 - (show annotations) (download) (as text)
Mon Jan 22 03:19:54 2018 UTC (19 months, 3 weeks ago) by jpye
File MIME type: text/x-python
File size: 51262 byte(s)
remove python debug output

1 try:
2 import loading
3 #loading.print_status("Loading PSYCO")
4 #try:
5 # import psyco
6 # psyco.full()
7 # print "Running with PSYCO optimisation..."
8 #except ImportError:
9 # pass
10
11 loading.print_status("Loading python standard libraries")
12
13 import pygtk
14 pygtk.require('2.0')
15 import gtk
16 import gtkexcepthook
17
18 import re
19 import urlparse
20 import optparse
21 import platform
22 import sys
23 import os
24
25 if platform.system() != "Windows":
26 try:
27 import dl
28 _dlflags = dl.RTLD_GLOBAL|dl.RTLD_NOW
29 except:
30 # On platforms that unilaterally refuse to provide the 'dl' module
31 # we'll just set the value and see if it works.
32 loading.print_status("Setting dlopen flags","Python 'dl' module not available on this system")
33 _dlflags = 258
34 # This sets the flags for dlopen used by python so that the symbols in the
35 # ascend library are made available to libraries dlopened within ASCEND:
36 sys.setdlopenflags(_dlflags)
37
38 loading.print_status("Loading LIBASCEND/ascpy")
39 import ascpy
40
41 loading.print_status("Loading PyGTK, pango")
42
43 import pango
44
45 loading.load_matplotlib()
46
47 loading.print_status("Loading ASCEND python modules")
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 imagewindow import * # image viewer window
53 from observer import * # observer tab support
54 from properties import * # solver_var properties dialog
55 from varentry import * # for inputting of variables with units
56 from diagnose import * # for diagnosing block non-convergence
57 from solverreporter import * # solver status reporting
58 from moduleview import * # module browser
59 from modelview import * # model browser
60 from integrator import * # integrator dialog
61 from infodialog import * # general-purpose textual information dialog
62 from versioncheck import * # version check (contacts ascend.cruncher2.dyndns.org)
63 from unitsdialog import * # general-purpose textual information dialog
64 from solverhooks import * # solver hooks for use from Python layer
65 import config
66
67 #loading.complete();
68
69 except RuntimeError, e:
70 print "ASCEND had problems starting up. Please report the following"
71 print "error message on ASCEND bug tracker."
72 print "\n\nFull error message:",str(e)
73 print "\n\nPress ENTER to close this window."
74 sys.stdout.flush()
75 sys.stdin.readline();
76 sys.exit();
77
78 except ImportError, e:
79 print "\n\n------------------ ERROR ---------------------"
80 print "ASCEND had problems importing required Python modules."
81 print "\nPlease ensure you have all the runtime prerequisites installed."
82 print "Please then report a bug if you continue to have problems."
83 print "\nFull error message:",str(e)
84 if platform.system()=="Windows":
85 print "\nYou will also need to report the contents of any popup error"
86 print "messages from Windows if any were shown."
87 print "\n\nPress ENTER to close this window."
88 sys.stdout.flush()
89 sys.stdin.readline();
90 sys.exit();
91
92 loading.print_status("Starting GUI")
93
94 # This is my first ever GUI code so please be nice :)
95 # But I *have* at least read
96 # http://www.joelonsoftware.com/uibook/chapters/fog0000000057.html
97 # and leafed through
98 # http://developer.gnome.org/projects/gup/hig/
99
100 # The fancy tree-view gizmo is the GtkTreeView object. See the article
101 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/300304
102 # for the original source code on which my implementation was based.
103
104 ESCAPE_KEY = 65307
105
106 HELP_ROOT = None
107
108 #======================================
109 # Browser is the main ASCEND library/model browser window
110
111 class Browser:
112
113 # ---------------------------------
114 # SETUP
115
116 def __init__(self,librarypath=None,assetspath=None):
117
118 if assetspath==None:
119 if platform.system()=="Windows":
120 assetspath=os.path.normpath(os.path.join(os.path.dirname(__file__),"..","glade"))
121 else:
122 assetspath=config.PYGTK_ASSETS
123
124 #--------
125 # load the file referenced in the command line, if any
126
127 loading.print_status("Parsing options","CONFIG = %s"%config.VERSION)
128
129 #print "Command-line options:",sys.argv
130
131 parser = optparse.OptionParser(usage="%prog [[-m typename] file]", version="gtkbrowser $rev$" )
132 # add options here if we want
133
134 #print "About to parse..."
135
136 if platform.system() == "Darwin":
137 parser.add_option("-p", "--silly-mac-thing"
138 ,action="store", type="string", dest="process_number"
139 ,help="Launch Services for Mac passes in a -psn-NNNNN argument that we need to swallow.")
140
141 parser.add_option("-m", "--model"
142 ,action="store", type="string", dest="model"
143 ,help="specify the model to instantiate upon loading modules")
144
145 parser.add_option("--pygtk-assets"
146 ,action="store", type="string", dest="assets_dir"
147 ,help="override the configuration value for the location of assets"\
148 +" required by PyGTK for the ASCEND GUI, optional"
149 ,default=assetspath
150 )
151
152 parser.add_option("--library"
153 ,action="store", type="string", dest="library_path"
154 ,help="override the configuration value for the library path"
155 ,default=librarypath
156 )
157
158 parser.add_option("--no-auto-sim"
159 ,action="store_false", dest="auto_sim"
160 ,help="disable auto-instantiation of MODEL named as the file stem"
161 ,default=True
162 )
163
164 parser.add_option("-t", "--test"
165 ,action="store", type="string", dest="test"
166 ,help="load a model and run contained tests without GUI")
167
168 (self.options, args) = parser.parse_args()
169
170 if len(args)>=1:
171 if os.path.isfile(args[0])==False:
172 error = '\033[91mERROR : %s is not a file\033[0m'%args[0]
173 print error
174 sys.exit()
175
176 #print "OPTIONS_______________:",self.options
177
178 self.assets_dir = self.options.assets_dir
179 #loading.create_window(self.assets_dir)
180
181 self.observers = []
182 self.currentobservertab = None
183 self.clip = None
184
185 #--------
186 # load up the preferences ini file
187
188 loading.print_status("Loading preferences")
189
190 self.prefs = Preferences()
191 _prefpath = self.prefs.getStringPref("Directories","librarypath",None)
192 _preffileopenpath = self.prefs.getStringPref("Directories","fileopenpath",None)
193 self.filename = None
194
195 #--------
196 # set up library path and the path to use for File->Open dialogs
197
198 if self.options.library_path != None:
199 _path = os.path.abspath(self.options.library_path)
200 _pathsrc = "command line options"
201 # when a special path is specified, use the last path component as the file-open location
202 if platform.system()=="Windows":
203 self.fileopenpath = _path.split(":").pop()
204 else:
205 self.fileopenpath = _path.split(":").pop()
206 else:
207 if _prefpath:
208 _path = _prefpath
209 _pathsrc = "user preferences"
210 else:
211 # default setting, but override with Windows registry if present
212 _path = config.LIBRARY_PATH
213 _pathsrc = "default (config.py)"
214
215 if platform.system()=="Windows":
216 # use the registry
217 try:
218 import _winreg
219 x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
220 y= _winreg.OpenKey(x,r"SOFTWARE\ASCEND")
221 _regpath,t = _winreg.QueryValueEx(y,"ASCENDLIBRARY")
222 _winreg.CloseKey(y)
223 _winreg.CloseKey(x)
224 _path = _regpath
225 os.environ['ASCENDLIBRARY'] = _regpath
226 _pathsrc = "Windows registry"
227 except:
228 # otherwise keep using the default
229 pass
230
231 if _preffileopenpath:
232 self.fileopenpath = _preffileopenpath
233 else:
234 self.fileopenpath = _path
235
236 #--------
237 # Create the ASCXX 'Library' object
238
239 loading.print_status("Creating ASCEND 'Library' object","ASCENDLIBRARY = "+_path+" FROM "+_pathsrc)
240 self.library = ascpy.Library(str(_path))
241
242 self.sim = None
243
244 #--------
245 # report absence of solvers if nec.
246
247 if not len(ascpy.getSolvers()):
248 print "NO SOLVERS LOADED!"
249 self.reporter.reportError( "No solvers were loaded! ASCEND is probably not configured correctly." )
250
251 #--test option
252 if self.options.test:
253 print '================================================================================'
254 print 'IN TEST'
255 self.test()
256 return
257
258 #-------------------
259 # Set up the window and main widget actions
260 self.glade_file = os.path.join(self.assets_dir,config.GLADE_FILE)
261
262 loading.print_status("Setting up windows") #,"GLADE_FILE = %s" % self.glade_file)
263
264 builder = gtk.Builder()
265 #builder.add_from_file(self.glade_file)
266 builder.add_objects_from_file(self.glade_file,["integ_icon","browserwin","list_of_td"])
267 self.builder=builder
268 self.window=self.builder.get_object ("browserwin")
269
270 self.disable_menu()
271 self.disable_on_first_run()
272 if not self.window:
273 raise RuntimeError("Couldn't load window from glade file")
274
275 _display = self.window.get_screen().get_display().get_name()
276 _geom=self.prefs.getGeometrySizePosition(_display,"browserwin")
277 if _geom:
278 self.window.resize(_geom[0],_geom[1])
279 self.window.move(_geom[2],_geom[3])
280
281 self.window.connect("delete_event", self.delete_event)
282
283 self.browserpaned=self.builder.get_object ("browserpaned")
284 _geom2=self.prefs.getGeometryValue(_display,"browserpaned")
285 if _geom2:
286 self.browserpaned.set_position(_geom2)
287
288 buttons = ["open","reload","solve","integrate","check","methodrun"]
289 for n in buttons:
290 name = "%sbutton"%n
291 setattr(self,name,self.builder.get_object(name))
292 getattr(self,name).connect("clicked",getattr(self,"%s_click"%n))
293
294 widgets = ["autotoggle","automenu","methodsel","maintabs","lowertabs","consolescroll","statusbar","browsermenu","reloadwarn"]
295 for n in widgets:
296 setattr(self,n,self.builder.get_object(n))
297
298 self.autotoggle.connect("toggled",self.auto_toggle)
299
300 self.show_solving_popup=self.builder.get_object("show_solving_popup")
301 self.show_solving_popup.set_active(self.prefs.getBoolPref("SolverReporter","show_popup",True))
302 self.close_on_converged=self.builder.get_object("close_on_converged")
303 self.close_on_converged.set_active(self.prefs.getBoolPref("SolverReporter","close_on_converged",True))
304 self.close_on_nonconverged=self.builder.get_object("close_on_nonconverged")
305 self.close_on_nonconverged.set_active(self.prefs.getBoolPref("SolverReporter","close_on_nonconverged",True))
306 self.solver_engine=self.builder.get_object("solver_engine")
307 self.recent_files=self.builder.get_object("recentfiles")
308
309 self.use_relation_sharing=self.builder.get_object("use_relation_sharing")
310 self.use_relation_sharing.set_active(self.prefs.getBoolPref("Compiler","use_relation_sharing",True))
311
312 self.use_binary_compilation=self.builder.get_object("use_binary_compilation")
313 self.use_binary_compilation.set_active(self.prefs.getBoolPref("Compiler","use_binary_compilation",False))
314 self.use_binary_compilation.set_sensitive(self.use_relation_sharing.get_active())
315
316 self.check_weekly=self.builder.get_object("check_weekly")
317 self.check_weekly.set_active(not(self.prefs.getBoolPref("Browser","disable_auto_check_for_updates",False)))
318
319 self.builder.connect_signals(self)
320
321 #-------
322 # Status icons
323
324 self.fixedimg = gtk.Image()
325 _fixedimgpath = os.path.join(self.options.assets_dir,'locked.png')
326
327 # this stuff catches some strange environment-variable related problems on Mac OSX.
328 try:
329 if not os.path.exists(_fixedimgpath):
330 raise RuntimeError("Image file '%s' could not be found" % _fixedimgpath)
331 _fixedpixbuf = gtk.gdk.pixbuf_new_from_file(_fixedimgpath)
332 self.fixedimg.set_from_pixbuf(_fixedpixbuf)
333 except Exception,e:
334 raise RuntimeError("Failed to load pixbuf '%s' (%s)" % (_fixedimgpath, str(e)))
335
336 self.inactiveimg = gtk.Image()
337 self.inactiveimg.set_from_file(os.path.join(self.options.assets_dir,'unattached.png'))
338
339 self.iconstatusunknown = None
340 self.iconfixed = self.fixedimg.get_pixbuf()
341 self.iconsolved = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
342 self.iconactive = self.window.render_icon(gtk.STOCK_NO,gtk.ICON_SIZE_MENU)
343 self.iconinactive = self.inactiveimg.get_pixbuf()
344 self.iconunsolved = None
345
346 self.statusicons={
347 ascpy.ASCXX_INST_STATUS_UNKNOWN: self.iconstatusunknown
348 ,ascpy.ASCXX_VAR_FIXED: self.iconfixed
349 ,ascpy.ASCXX_VAR_SOLVED: self.iconsolved
350 ,ascpy.ASCXX_VAR_ACTIVE: self.iconactive
351 ,ascpy.ASCXX_VAR_UNSOLVED: self.iconunsolved
352 ,ascpy.ASCXX_REL_INACTIVE: self.iconinactive
353 }
354
355
356 self.statusmessages={
357 ascpy.ASCXX_INST_STATUS_UNKNOWN: "Status unknown"
358 ,ascpy.ASCXX_VAR_FIXED: "Fixed"
359 ,ascpy.ASCXX_VAR_SOLVED: "Converged"
360 ,ascpy.ASCXX_VAR_ACTIVE: "Active (unconverged)"
361 ,ascpy.ASCXX_VAR_UNSOLVED: "Not yet visited"
362 ,ascpy.ASCXX_REL_INACTIVE: "Inactive"
363 }
364
365 #-------------------
366 # waitwin
367
368 self.waitwin = gtk.gdk.Window(self.window.window,
369 gtk.gdk.screen_width(),
370 gtk.gdk.screen_height(),
371 gtk.gdk.WINDOW_CHILD,
372 0,
373 gtk.gdk.INPUT_ONLY)
374
375 _cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
376 self.waitwin.set_cursor(_cursor)
377
378 #-------------------
379 # pixbufs to be used in the error listing
380
381 self.iconok = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
382 self.iconinfo = self.window.render_icon(gtk.STOCK_DIALOG_INFO,gtk.ICON_SIZE_MENU)
383 self.iconwarning = self.window.render_icon(gtk.STOCK_DIALOG_WARNING,gtk.ICON_SIZE_MENU)
384 self.iconerror = self.window.render_icon(gtk.STOCK_DIALOG_ERROR,gtk.ICON_SIZE_MENU)
385
386 #--------------------
387 # pixbufs for solver_var status
388
389 #--------------------
390 # set up the error view
391
392 self.errorview = self.builder.get_object("errorview")
393 errstorecolstypes = [gtk.gdk.Pixbuf,str,str,str,int]
394 self.errorstore = gtk.TreeStore(*errstorecolstypes)
395 errtitles = ["","Location","Message"];
396 self.errorview.set_model(self.errorstore)
397 self.errcols = [ gtk.TreeViewColumn() for _type in errstorecolstypes]
398
399 i = 0
400 for tvcolumn in self.errcols[:len(errtitles)]:
401 tvcolumn.set_title(errtitles[i])
402 self.errorview.append_column(tvcolumn)
403
404 if i>0:
405 _renderer = gtk.CellRendererText()
406 tvcolumn.pack_start(_renderer, True)
407 tvcolumn.add_attribute(_renderer, 'text', i)
408 if(i==2):
409 tvcolumn.add_attribute(_renderer, 'foreground', 3)
410 tvcolumn.add_attribute(_renderer, 'weight', 4)
411 else:
412 _renderer1 = gtk.CellRendererPixbuf()
413 tvcolumn.pack_start(_renderer1, False)
414 tvcolumn.add_attribute(_renderer1, 'pixbuf', int(0))
415
416 i = i + 1
417
418
419 #--------------------
420 # set up the error reporter callback
421 self.reporter = ascpy.getReporter()
422 self.reporter.setPythonErrorCallback(self.error_callback)
423
424
425 #-------
426 # Solver engine list
427
428 self.update_solver_list()
429
430 #-------
431 # Recent file list
432
433 self.recent_file_list = gtk.Menu()
434 self.recent_file_list.show()
435 self.recent_files.set_submenu(self.recent_file_list)
436
437 _max_num = int(self.prefs.getStringPref("recentfiles","max","-1"))
438 if _max_num == -1:
439 self.prefs.setStringPref("recentfiles","max","10")
440
441 _cur_num = int(self.prefs.getStringPref("recentfiles","cur","-1"))
442 if _cur_num >= 0:
443 for _i in range(_cur_num):
444 _fname = self.prefs.getStringPref("recentfiles","file%s"%(_cur_num -_i - 1),"no recent files")
445 _mi = gtk.MenuItem(_fname,False)
446 _mi.show()
447 _mi.connect("activate",self.on_recent_file_select)
448 self.recent_file_list.append(_mi)
449 else:
450 self.recent_file_list.set_state(gtk.STATE_INSENSITIVE)
451
452 _pref_solver = self.prefs.getStringPref("Solver","engine","QRSlv")
453 _mi = self.solver_engine_menu_dict.get(_pref_solver)
454 if _mi:
455 _mi.set_active(1)
456
457 #--------
458 # Assign an icon to the main window
459
460 self.icon = None
461 if config.ICON_EXTENSION:
462 _iconpath = ""
463 try:
464 _icon = gtk.Image()
465 _iconpath = os.path.join(self.assets_dir,'ascend'+config.ICON_EXTENSION)
466 _icon.set_from_file(_iconpath)
467 _iconpbuf = _icon.get_pixbuf()
468 self.window.set_icon(_iconpbuf)
469 self.icon = _iconpbuf
470 except Exception, e:
471 print "FAILED TO SET APPLICATION ICON PATH '%s': %s" % (_iconpath,str(e))
472 self.reporter.reportError("FAILED to set application icon '%s': %s"
473 % (_iconpath,str(e))
474 )
475
476 #-------------------
477 # set up the module view
478
479 self.modtank = {}
480 self.moduleview = ModuleView(self, self.builder, self.library)
481
482 #--------------------
483 # set up the methods combobox
484
485 self.methodstore = gtk.ListStore(str)
486 self.methodsel.set_model(self.methodstore)
487 _methodrenderer = gtk.CellRendererText()
488 self.methodsel.pack_start(_methodrenderer, True)
489 self.methodsel.add_attribute(_methodrenderer, 'text',0)
490
491 #--------
492 # set up the instance browser view
493
494 self.modelview = ModelView(self, self.builder)
495
496 #--------
497 # set up the tabs
498 self.tabs = {}
499 self.activetab = None # most recent observer tab
500
501 #--------
502 # set the state of the 'auto' toggle
503
504 self.is_auto = self.prefs.getBoolPref("Browser","auto_solve",True)
505 self.autotoggle.set_active(self.is_auto)
506 self.automenu.set_active(self.is_auto)
507
508 #--------
509 # set the state of the 'warn on reload' toggle
510
511 self.reload_warn = self.prefs.getBoolPref("Browser","warn_on_reload",True)
512 self.reloadwarn.set_active(self.reload_warn)
513
514 #--------
515 # tell libascend about this 'browser' object
516
517 #print dir(ascpy.Registry())
518 ascpy.Registry().set("browser",self)
519
520 #--------
521 # Set up SolverHooks
522
523 print "PYTHON: SETTING UP SOLVER HOOKS"
524 self.solverhooks = SolverHooksPythonBrowser(self)
525 ascpy.SolverHooksManager_Instance().setHooks(self.solverhooks)
526
527 #--------
528 # options
529 if(len(args)==1):
530 try:
531 self.do_open(args[0])
532 except RuntimeError,e:
533 self.reporter.reportError(str(e))
534 return
535
536 #print "Options: ",self.options
537
538 _model = None
539 if self.options.model:
540 _model = self.options.model
541 print "MODEL: '%s'" % _model
542 elif self.options.auto_sim:
543 _head, _tail = os.path.split(args[0])
544 if(_tail):
545 _model, _ext = os.path.splitext(_tail)
546
547 if _model:
548 try:
549 _t=self.library.findType(_model)
550 if not _t.isModel():
551 if self.options.auto_sim:
552 self.reporter.reportError("Won't auto-instantiate with type '%s': not a MODEL." % _model)
553 elif _t.hasParameters():
554 if self.options.auto_sim:
555 self.reporter.reportError("Won't auto-instantiate MODEL %s: model requires parameters." % _model)
556 else:
557 try:
558 self.do_sim(_t)
559 if not self.options.model:
560 self.reporter.reportNote("Instantiated self-titled model '%s'" %_model)
561 except RuntimeError, e:
562 self.reporter.reportError("Failed to create instance of '%s': %s"
563 %(_model, str(e))
564 );
565 except RuntimeError, e:
566 if self.options.model:
567 self.reporter.reportError("Unknown model type '%s': %s"
568 %(_model, str(e))
569 );
570
571
572 #--------
573 # IPython console, if available
574
575 import console
576 console.create_widget(self)
577
578 import locale
579 if locale.localeconv()['decimal_point'] != '.':
580 self.reporter.reportError(
581 """Incompatible locale settings detected. Please set your system local to one which
582 uses '.' as the decimal point separator, such as en_US or en_AU. Note that failing
583 to make this change will cause input and output values to be truncated.
584 For details, see http://ascendbugs.cheme.cmu.edu/view.php?id=337"""
585 )
586
587 def run(self):
588 if not self.options.test:
589 #self.window.show()
590 loading.print_status("ASCEND is now running")
591 loading.complete()
592 if self.prefs.getStringPref('Browser','first_run') == None:
593 self.prefs.setStringPref('Browser','first_run',time.time())
594 else:
595 time_now = time.time()
596 first_run_time = float(self.prefs.getStringPref('Browser','first_run'))
597 if ((time_now-first_run_time)/(3600*24)) >= 7:
598 self.auto_update_check()
599 gtk.main()
600
601 def test(self):
602 print sys.argv[1]
603 print sys.argv[3]
604 if len(sys.argv)==4:
605 ascpy.test_model(str(sys.argv[1]),str(sys.argv[3]))
606 #Call the function at the SWIG API level that runs all the tests and pass to it, the *args
607 #ascpy is accessible here
608
609
610 # ------------------
611 # SOLVER LIST
612
613 def update_solver_list(self):
614 self.solver_engine_menu = gtk.Menu()
615 self.solver_engine_menu.show()
616 self.solver_engine.set_submenu(self.solver_engine_menu)
617 self.solver_engine_menu_dict = {}
618 _slvlist = ascpy.getSolvers()
619 _fmi = None
620 for _s in _slvlist:
621 _mi = gtk.RadioMenuItem(_fmi,_s.getName(),False)
622 if _fmi==None:
623 _fmi = _mi
624 _mi.show()
625 _mi.connect('toggled',self.on_select_solver_toggled,_s.getName())
626 self.solver_engine_menu.append(_mi)
627 self.solver_engine_menu_dict[_s.getName()]=_mi
628
629 def set_solver(self,solvername):
630 """ this sets the active solver in the GUI, which is the default applied to newly instantiated models """
631 self.solver = ascpy.Solver(solvername)
632 self.prefs.setStringPref("Solver","engine",solvername)
633 self.reporter.reportNote("Set solver engine to '%s'" % solvername)
634
635 # --------------------------------------------
636 # MAJOR GUI COMMANDS
637
638 def on_fix_variable_activate(self,*args):
639 if not self.sim:
640 self.reporter.reportError("No model selected yet")
641 return
642 self.modelview.on_fix_variable_activate(*args)
643
644 def on_free_variable_activate(self,*args):
645 if not self.sim:
646 self.reporter.reportError("No model selected yet")
647 return
648 self.modelview.on_free_variable_activate(*args)
649
650 def on_select_solver_toggled(self,widget,solvername):
651 if widget.get_active():
652 self.set_solver(solvername)
653
654 def on_recent_file_select(self,widget):
655 if widget:
656 # _msg = gtk.MessageDialog(buttons=gtk.BUTTONS_OK,message_format=filename,flags=gtk.DIALOG_MODAL)
657 # _msg.run()
658 self.do_open(widget.get_label())
659
660 def update_recent_files(self,filename):
661 if filename:
662 _max_num = int(self.prefs.getStringPref("recentfiles","max","10"))
663 _cur_num = int(self.prefs.getStringPref("recentfiles","cur","0"))
664 _should_change = False
665 _temp = None
666 if _cur_num < _max_num:
667 for _i in range(_cur_num):
668 _temp = self.prefs.getStringPref("recentfiles","file%s"%(_i),None)
669 if _temp == filename: #already in the list before
670 _should_change = True
671 if _should_change and _i+1 < _cur_num:
672 _temp = self.prefs.getStringPref("recentfiles","file%s"%(_i+1),None)
673 self.prefs.setStringPref("recentfiles","file%s"%(_i),_temp)
674 if _should_change and _i == _cur_num - 1:
675 self.prefs.setStringPref("recentfiles","file%s"%(_i),filename)
676
677 if _should_change == False:
678 self.prefs.setStringPref("recentfiles","file%s"%(_cur_num),filename)
679 self.prefs.setStringPref("recentfiles","cur",_cur_num+1)
680 else:
681 for _i in range(_max_num):
682 _temp = self.prefs.getStringPref("recentfiles","file%s"%(_i),None)
683 if _temp == filename: #already in the list before
684 _should_change = True
685 if _should_change and _i+1 < _max_num:
686 _temp = self.prefs.getStringPref("recentfiles","file%s"%(_i+1),None)
687 self.prefs.setStringPref("recentfiles","file%s"%(_i),_temp)
688 if _should_change and _i == _max_num - 1:
689 self.prefs.setStringPref("recentfiles","file%s"%(_i),filename)
690
691 if _should_change == False: #this is a new file, then remove the oldest one
692 for _i in range(_max_num):
693 if _i+1 < _max_num:
694 _temp = self.prefs.getStringPref("recentfiles","file%s"%(_i+1),None)
695 self.prefs.setStringPref("recentfiles","file%s"%(_i),_temp)
696 else:
697 self.prefs.setStringPref("recentfiles","file%s"%(_i),filename)
698
699
700 def do_open(self,filename):
701 # TODO does the user want to lose their work?
702 # TODO do we need to chdir?
703
704 _context = self.statusbar.get_context_id("do_open")
705
706 self.errorstore.clear()
707 self.modelview.clear()
708 self.currentobservertab = None
709 for _obs in self.observers:
710 if _obs.alive == False:
711 _obs.reloaded = True
712 _obs.set_dead()
713 # self.library.clear()
714 #print "Filename =",filename
715 self.statusbar.push(_context,"Loading '"+filename+"'")
716 try:
717 self.filename = filename
718 self.disable_menu()
719 self.enable_on_file_open()
720 # call the low-level 'load' command...
721 self.library.load(filename)
722 self.update_recent_files(filename)
723 except RuntimeError,e:
724 self.statusbar.pop(_context)
725 raise
726
727 try:
728 self.statusbar.pop(_context)
729 except TypeError,e:
730 print "For some reason, a type error (context=%s,filename=%s): %s" % (_context,filename,e)
731
732 # Load the current list of modules into self.modules
733 self.moduleview.refresh(self.library)
734
735 self.sim = None;
736 self.maintabs.set_current_page(0);
737
738 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
739 # for details on how the 'wait cursor' is done.
740 def start_waiting(self, message):
741 self.waitcontext = self.statusbar.get_context_id("waiting")
742 self.statusbar.push(self.waitcontext,message)
743
744 if self.waitwin:
745 self.waitwin.show()
746
747 while gtk.events_pending():
748 gtk.main_iteration()
749
750 def stop_waiting(self):
751 if self.waitwin:
752 self.statusbar.pop(self.waitcontext)
753 self.waitwin.hide()
754
755 def do_sim(self, type_object):
756 self.sim = None;
757 # TODO: clear out old simulation first!
758
759 #print "DO_SIM(%s)" % str(type_object.getName())
760 self.start_waiting("Compiling...")
761
762 try:
763 _v = self.prefs.getBoolPref("Compiler","use_relation_sharing",True)
764 ascpy.getCompiler().setUseRelationSharing(_v)
765 print "Relation sharing set to",_v
766
767 _v = self.prefs.getBoolPref("Compiler","use_binary_compilation",False)
768 ascpy.getCompiler().setBinaryCompilation(_v)
769 print "Binary compilation set to",_v
770
771 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim",False)
772
773 #self.reporter.reportNote("SIMULATION ASSIGNED")
774 except RuntimeError, e:
775 self.stop_waiting()
776 self.reporter.reportError(str(e))
777 return
778
779 self.stop_waiting()
780
781 # get method names and load them into the GUI
782 self.methodstore.clear()
783 _methods = self.sim.getType().getMethods()
784 _activemethod = None;
785 for _m in _methods:
786 _i = self.methodstore.append([_m.getName()])
787 if _m.getName()=="on_load":
788 self.methodsel.set_active_iter(_i)
789
790 self.modelview.setSimulation(self.sim)
791
792 # run the 'on_load' method
793 self.start_waiting("Running default method...")
794 try:
795 #self.reporter.reportNote("SIMULATION CREATED, RUNNING DEFAULT METHOD NOW...")
796 self.sim.runDefaultMethod()
797 except RuntimeError, e:
798 self.stop_waiting()
799 self.reporter.reportError(str(e))
800 return
801 self.stop_waiting()
802
803 self.modelview.refreshtree()
804
805 def do_solve_if_auto(self):
806 if self.is_auto:
807 self.sim.checkInstance()
808 self.do_solve()
809 else:
810 try:
811 self.sim.processVarStatus()
812 except RuntimeError,e:
813 self.reporter.reportError(str(e))
814 self.modelview.refreshtree()
815
816 self.sync_observers()
817
818
819 def no_built_system(self):
820 """ check that the system is 'built', ready for use by the solver. """
821
822 if not self.sim:
823 self.reporter.reportError("No model selected yet")
824 return 1
825
826 try:
827 self.sim.build()
828 self.enable_on_sim_build()
829 except RuntimeError,e:
830 self.reporter.reportError("Couldn't build system: %s" % str(e));
831 return 1
832
833 return 0;
834
835 def do_solve(self):
836 if self.no_built_system():
837 return
838
839 if not hasattr(self,'solver'):
840 self.reporter.reportError("No solver assigned!")
841 return
842
843 self.start_waiting("Solving with %s..." % self.solver.getName())
844
845 if self.prefs.getBoolPref("SolverReporter","show_popup",True):
846 reporter = PopupSolverReporter(self,self.sim)
847 else:
848 reporter = SimpleSolverReporter(self)
849
850 try:
851 self.sim.solve(self.solver,reporter)
852 except RuntimeError,e:
853 self.reporter.reportError(str(e))
854
855 self.stop_waiting()
856
857 self.modelview.refreshtree()
858
859 def do_integrate(self):
860 if self.no_built_system():
861 return
862
863 try:
864 self.sim.build()
865 except RuntimeError,e:
866 self.reporter.reportError("Couldn't build system: %s",str(e))
867 return
868 integrator = ascpy.Integrator(self.sim)
869 try:
870 integrator.findIndependentVar()
871 except RuntimeError,e:
872 self.reporter.reportNote(str(e))
873
874 integwin = IntegratorWindow(self,self.sim)
875 _integratorreporter = integwin.run()
876 if _integratorreporter!=None:
877 _integratorreporter.run()
878 self.sim.processVarStatus()
879 self.modelview.refreshtree()
880
881
882 def do_check(self):
883 if self.no_built_system():
884 return
885
886 self.start_waiting("Checking system...")
887
888 try:
889 self.sim.checkInstance()
890 self.reporter.reportWarning("System instance check run, check above for error (if any).")
891 # the above gives output but doesn't throw errors or return a status.
892 # ... this is a problem (at the C level)
893
894 status = self.sim.checkDoF()
895 if status==ascpy.ASCXX_DOF_UNDERSPECIFIED:
896 self.on_show_fixable_variables_activate(None)
897 elif status==ascpy.ASCXX_DOF_OVERSPECIFIED:
898 self.on_show_freeable_variables_activate(None)
899 elif status==ascpy.ASCXX_DOF_STRUCT_SINGULAR:
900 if not self.sim.checkStructuralSingularity():
901 sing = self.sim.getSingularityInfo()
902 title = "Structural singularity"
903 text = title
904 msgs = {
905 "The singularity can be reduced by freeing the following variables" : sing.freeablevars
906 ,"Relations involved in the structural singularity" : sing.rels
907 ,"Variables involved in the structural singularity" : sing.vars
908 }
909 for k,v in msgs.iteritems():
910 text+="\n\n%s:" % k
911 if len(v):
912 _l = [j.getName() for j in v]
913 _l.sort()
914 text+= "\n\t" + "\n\t".join(_l)
915 else:
916 text += "\nnone"
917
918 _dialog = InfoDialog(self,self.window,text,title)
919 _dialog.run()
920 else:
921 self.reporter.reportNote("System DoF check OK")
922
923 except RuntimeError, e:
924 self.stop_waiting()
925 self.reporter.reportError(str(e))
926 return
927
928 self.stop_waiting()
929 self.modelview.refreshtree()
930
931 def do_method(self,method):
932
933 try:
934 self.sim.run(method)
935 except RuntimeError,e:
936 self.reporter.reportError(str(e))
937
938 self.sim.processVarStatus()
939 self.modelview.refreshtree()
940
941 def do_quit(self):
942 loading.print_status("Saving window location")
943 self.reporter.clearPythonErrorCallback()
944
945 _w,_h = self.window.get_size()
946 _t,_l = self.window.get_position()
947 _display = self.window.get_screen().get_display().get_name()
948 self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
949
950 _p = self.browserpaned.get_position()
951 self.prefs.setGeometryValue(_display,"browserpaned",_p);
952
953 loading.print_status("Saving current directory")
954 self.prefs.setStringPref("Directories","fileopenpath",self.fileopenpath)
955
956 self.prefs.setBoolPref("Browser","auto_solve",self.is_auto)
957
958 loading.print_status("Saving preferences")
959 # causes prefs to be saved unless they are still being used elsewher
960 del(self.prefs)
961
962 loading.print_status("Clearing error callback")
963 self.reporter.clearPythonErrorCallback()
964
965 loading.print_status("Closing down GTK")
966 gtk.main_quit()
967
968 loading.print_status("Clearing library")
969 self.library.clear()
970
971 loading.print_status("Quitting")
972
973 return False
974
975 def on_tools_sparsity_click(self,*args):
976
977 self.reporter.reportNote("Preparing incidence matrix...")
978 try:
979 _im = self.sim.getIncidenceMatrix()
980 self.reporter.reportNote("Plotting incidence matrix...")
981 _sp = IncidenceMatrixWindow(_im)
982 _sp.run()
983 except RuntimeError,e:
984 self.reporter.reportError(str(e))
985
986 def on_units_click(self,*args):
987 T = self.modelview.get_selected_type()
988 _un = UnitsDialog(self,T)
989 _un.run()
990
991 def on_tools_incidencegraph_click(self,*args):
992 self.reporter.reportNote("Preparing incidence graph...")
993 fname = os.tempnam()
994 self.start_waiting("Creating incidence graph...")
995 try:
996 self.sim.write(fname,'dot') # create a PNG file in f
997 except Exception,e:
998 self.stop_waiting()
999 self.reporter.reportError("Failed to create incidence graph: %s" % str(e))
1000 return
1001 self.stop_waiting()
1002 _ig = ImageWindow(self, self.window, fname, title="Incidence Graph", delete=True)
1003 _ig.run()
1004 self.reporter.reportNote("Deleted temporary file")
1005
1006 def on_tools_repaint_tree_activate(self,*args):
1007 self.reporter.reportNote("Repainting model view...")
1008 self.modelview.refreshtree()
1009
1010 def on_diagnose_blocks_activate(self,*args):
1011 try:
1012 _bl = self.sim.getActiveBlock()
1013 _db = DiagnoseWindow(self,_bl)
1014 _db.run();
1015 except RuntimeError, e:
1016 self.reporter.reportError(str(e))
1017 return
1018
1019 def on_add_observer_click(self,*args):
1020 self.create_observer()
1021
1022 def on_keep_observed_click(self,*args):
1023 print "KEEPING..."
1024 if self.currentobservertab is None:
1025 self.reporter.reportError("No observers defined for this model!")
1026 return
1027 self.tabs[self.currentobservertab].do_add_row()
1028
1029 def on_copy_observer_matrix_click(self,*args):
1030 if self.clip == None:
1031 self.clip = gtk.Clipboard()
1032
1033 if len(self.observers) <= 0:
1034 self.reporter.reportError("No observer defined!")
1035 return
1036 self.tabs[self.currentpage].copy_to_clipboard(self.clip)
1037
1038 def on_use_relation_sharing_toggle(self,checkmenuitem,*args):
1039 _v = checkmenuitem.get_active()
1040 self.prefs.setBoolPref("Compiler","use_relation_sharing",_v)
1041 self.reporter.reportNote("Relation sharing set to "+str(_v))
1042 self.use_binary_compilation.set_sensitive(_v);
1043
1044 def on_use_binary_compilation_toggle(self,checkmenuitem,*args):
1045 _v = checkmenuitem.get_active()
1046 self.prefs.setBoolPref("Compiler","use_binary_compilation",_v)
1047 self.reporter.reportNote("Binary compilation set to "+str(_v))
1048
1049 def on_show_solving_popup_toggle(self,checkmenuitem,*args):
1050 _v = checkmenuitem.get_active()
1051 self.prefs.setBoolPref("SolverReporter","show_popup",_v)
1052
1053 def on_close_on_converged_toggle(self,checkmenuitem,*args):
1054 _v = checkmenuitem.get_active()
1055 self.prefs.setBoolPref("SolverReporter","close_on_converged",_v)
1056
1057 def on_close_on_nonconverged_toggle(self,checkmenuitem,*args):
1058 _v = checkmenuitem.get_active()
1059 self.prefs.setBoolPref("SolverReporter","close_on_nonconverged",_v)
1060
1061 def on_show_variables_near_bounds_activate(self,*args):
1062 _epsilon = 1e-4;
1063 try:
1064 _vars = self.sim.getVariablesNearBounds(_epsilon)
1065 except RuntimeError,e:
1066 self.reporter.reportError("Unable to show variables near bounds:\n%s"%str(e))
1067 return
1068 text = "Variables Near Bounds"
1069 title=text;
1070 text += "\n"
1071 if len(_vars):
1072 for _v in _vars:
1073 text += "\n%s"%_v.getName()
1074 else:
1075 text +="\nnone"
1076 _dialog = InfoDialog(self,self.window,text,title)
1077 _dialog.run()
1078
1079 def on_show_vars_far_from_nominals_activate(self,*args):
1080 _bignum = self.prefs.getRealPref("Browser","far_from_nominals",10);
1081 try:
1082 _vars = self.sim.getVariablesFarFromNominals(_bignum)
1083 except RuntimeError,e:
1084 self.reporter.reportError("Unable to show variables far from nominals:\n%s"%str(e))
1085 return
1086 text = "Variables Far from Nominals"
1087 title=text;
1088 text += "\n"
1089 if len(_vars):
1090 for _v in _vars:
1091 text += "\n%s"%_v.getName()
1092 else:
1093 text +="\nnone"
1094
1095 text+="\n\nAbove calculated using a relative error of %f" % float(_bignum)
1096 text+="\nModify this value in .ascend.ini, section '[Browser]', key 'far_from_nominals'."
1097 _dialog = InfoDialog(self,self.window,text,title)
1098 _dialog.run()
1099
1100 def on_show_config_activate(self,*args):
1101 text = "Configuration"
1102 title=text;
1103 text += "\n\nEnvironment variables:\n"
1104 if len(os.environ):
1105 for _k,_v in sorted(os.environ.items()):
1106 text += " %s=%s\n" % (_k,_v)
1107 else:
1108 text +="\nempty"
1109
1110 _dialog = InfoDialog(self,self.window,text,title)
1111 _dialog.run()
1112
1113
1114 # ----------------------------------
1115 # ERROR PANEL
1116
1117 def get_error_row_data(self,sev,filename,line,msg):
1118 try:
1119 _sevicon = {
1120 0 : self.iconok
1121 ,1 : self.iconinfo
1122 ,2 : self.iconwarning
1123 ,4 : self.iconerror
1124 ,8 : self.iconinfo
1125 ,16 : self.iconwarning
1126 ,32 : self.iconerror
1127 ,64 : self.iconerror
1128 }[sev]
1129 except KeyError:
1130 _sevicon = self.iconerror
1131
1132 _fontweight = pango.WEIGHT_NORMAL
1133 if sev==32 or sev==64:
1134 _fontweight = pango.WEIGHT_BOLD
1135
1136 _fgcolor = "black"
1137 if sev==8:
1138 _fgcolor = "#888800"
1139 elif sev==16:
1140 _fgcolor = "#884400"
1141 elif sev==32 or sev==64:
1142 _fgcolor = "#880000"
1143 elif sev==0:
1144 _fgcolor = BROWSER_FIXED_COLOR
1145
1146 if not filename and not line:
1147 _fileline = ""
1148 else:
1149 if(len(filename) > 25):
1150 filename = "..."+filename[-22:]
1151 _fileline = filename + ":" + str(line)
1152
1153 #print "Creating error row data with MSG = '%s'"%(msg.rstrip())
1154
1155 _res = (_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight)
1156 #print _res
1157 return _res
1158
1159 def error_callback(self,sev,filename,line,msg):
1160 #print "SEV =",sev
1161 #print "FILENAME =",filename
1162 #print "LINE =",line
1163 #print "PYTHON error_callback: MSG =",msg
1164 pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
1165 path = self.errorstore.get_path(pos)
1166 col = self.errorview.get_column(3)
1167 self.errorview.scroll_to_cell(path,col)
1168 return 0;
1169
1170 # --------------------------------
1171 # BUTTON METHODS
1172
1173 def open_click(self,*args):
1174 #loading.print_status("CURRENT FILEOPENPATH is",self.fileopenpath)
1175 dialog = gtk.FileChooserDialog("Open ASCEND model...",
1176 self.window,
1177 gtk.FILE_CHOOSER_ACTION_OPEN,
1178 (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)
1179 )
1180 dialog.set_current_folder(self.fileopenpath)
1181 dialog.set_default_response(gtk.RESPONSE_OK)
1182 dialog.set_transient_for(self.window)
1183 dialog.set_modal(True)
1184
1185 filter = gtk.FileFilter()
1186 filter.set_name("*.a4c, *.a4l")
1187 filter.add_pattern("*.[Aa]4[Cc]")
1188 filter.add_pattern("*.[Aa]4[Ll]")
1189 dialog.add_filter(filter)
1190
1191 filter = gtk.FileFilter()
1192 filter.set_name("All files")
1193 filter.add_pattern("*")
1194 dialog.add_filter(filter)
1195
1196 response = dialog.run()
1197 _filename = dialog.get_filename()
1198 print "\nFILENAME SELECTED:",_filename
1199
1200 _path = dialog.get_current_folder()
1201 if _path:
1202 self.fileopenpath = _path
1203
1204 dialog.hide()
1205
1206 if response == gtk.RESPONSE_OK:
1207 self.reporter.reportNote("File %s selected." % dialog.get_filename() )
1208 self.library.clear()
1209 try:
1210 self.do_open( _filename)
1211 except RuntimeError,e:
1212 self.reporter.reportError(str(e))
1213
1214 def on_reloadwarn_toggled(self,*args):
1215 self.prefs.setBoolPref("Browser","warn_on_reload",self.reloadwarn.get_active())
1216
1217 def reload_click(self,*args):
1218 _type = None
1219
1220 if not self.filename:
1221 self.reporter.reportError("No file loaded yet!")
1222 return
1223
1224 if self.sim:
1225 _type = self.sim.getType().getName().toString();
1226
1227 if self.reloadwarn.get_active() and self.currentobservertab is not None:
1228 _alertwin = ReloadDialog(self)
1229 _reload = _alertwin.run()
1230 if _reload is False:
1231 return
1232 self.library.clear()
1233
1234 try:
1235 self.do_open(self.filename)
1236 if _type:
1237 _t = self.library.findType(_type)
1238 self.do_sim(_t)
1239 except RuntimeError,e:
1240 self.reporter.reportError(str(e))
1241
1242 def props_activate(self,widget,*args):
1243 return self.modelview.props_activate(self,widget,*args)
1244
1245 def observe_activate(self,widget,*args):
1246 return self.modelview.observe_activate(self,widget,*args)
1247
1248 def solve_click(self,*args):
1249 #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
1250 self.do_solve()
1251
1252 def console_click(self,*args):
1253 self.lowertabs.set_current_page(1)
1254 self.consoletext.grab_focus()
1255
1256 def integrate_click(self,*args):
1257 self.do_integrate()
1258
1259 def check_click(self,*args):
1260 self.do_check()
1261 #self.reporter.reportError("CHECK clicked")
1262
1263 def preferences_click(self,*args):
1264 if not self.sim:
1265 self.reporter.reportError("No simulation created yet!");
1266 self.sim.setSolver(self.solver)
1267 _params = self.sim.getParameters()
1268 _paramswin = SolverParametersWindow(
1269 browser=self
1270 ,params=_params
1271 ,name=self.solver.getName()
1272 )
1273 if _paramswin.run() == gtk.RESPONSE_OK:
1274 print "PARAMS UPDATED"
1275 self.sim.setParameters(_paramswin.params)
1276 else:
1277 print "PARAMS NOT UPDATED"
1278
1279 def methodrun_click(self,*args):
1280 _sel = self.methodsel.get_active_text()
1281 if _sel:
1282 _method = None
1283 _methods = self.sim.getType().getMethods()
1284 for _m in _methods:
1285 if _m.getName()==_sel:
1286 _method = _m
1287 if not _method:
1288 self.reporter.reportError("Method is not valid")
1289 return
1290 self.do_method(_method)
1291 else:
1292 self.reporter.reportError("No method selected")
1293
1294 def auto_toggle(self,button,*args):
1295 self.is_auto = button.get_active()
1296 if hasattr(self,'automenu'):
1297 self.automenu.set_active(self.is_auto)
1298 else:
1299 raise RuntimeError("no automenu")
1300
1301 #if self.is_auto:
1302 # self.reporter.reportSuccess("Auto mode is now ON")
1303 #else:
1304 # self.reporter.reportSuccess("Auto mode is now OFF")
1305
1306 def on_file_quit_click(self,*args):
1307 #self.exit_popup()
1308 self.do_quit()
1309
1310 def on_tools_auto_toggle(self,checkmenuitem,*args):
1311 self.is_auto = checkmenuitem.get_active()
1312 self.autotoggle.set_active(self.is_auto)
1313
1314 def on_help_about_click(self,*args):
1315
1316 self.builder.add_objects_from_file(self.glade_file,["aboutdialog"])
1317 _about = self.builder.get_object("aboutdialog")
1318 _about.set_transient_for(self.window);
1319 _about.set_version(config.VERSION)
1320 _about.run()
1321 _about.destroy()
1322
1323 def on_help_contents_click(self,*args):
1324 _help = Help(HELP_ROOT)
1325 _help.run()
1326
1327 def on_report_a_bug_click(self,*args):
1328 import urllib
1329 import platform
1330 _plat = str(platform.system())
1331 _version = config.VERSION
1332 _help = Help(
1333 url="http://bugs.ascend4.org/bug_report_page.php?project_id=ascend&platform=%s&product_version=%s"
1334 % (_plat,_version)
1335 )
1336 _help.run()
1337
1338 def on_help_check_for_updates_click(self,*args):
1339 v = VersionCheck()
1340 title = "Check for updates"
1341 text = "Your version is %s\n" % config.VERSION
1342 self.prefs.setStringPref("Browser","last_update_check","%s" %time.time())
1343
1344 try:
1345 v.check()
1346 if config.VERSION==v.latest:
1347 text += "You are running the latest released version"
1348 else:
1349 text += "Latest version is %s\n" % v.latest
1350 if v.info:
1351 text += "Get more info at %s\n" % v.info
1352 if v.download:
1353 text += "Download from %s\n" % v.download
1354 except Exception, e:
1355 text += "\nUnable to check version\n"
1356 text += str(e)
1357
1358 _dialog = InfoDialog(self,self.window,text,title)
1359 _dialog.run()
1360
1361 def on_show_fixable_variables_activate(self,*args):
1362 try:
1363 v = self.sim.getFixableVariables()
1364 except Exception,e:
1365 self.reporter.reportError("Unable to show fixable variables: %s"%str(e))
1366 return
1367 text = "Fixable Variables"
1368 title = text
1369 text += "\n"
1370 if len(v):
1371 for var in v:
1372 text += "\n%s"%var
1373 else:
1374 text += "\nnone"
1375 _dialog = InfoDialog(self,self.window,text,title)
1376 _dialog.run()
1377
1378 def on_show_fixed_vars_activate(self,*args):
1379 try:
1380 v = self.sim.getFixedVariables()
1381 except RuntimeError,e:
1382 self.reporter.reportError("Unable to show fixed variables: %s"%str(e))
1383 return
1384 text = "%d fixed variables:" % len(v)
1385 title = "Fixed Variables"
1386 text += "\n"
1387 if len(v):
1388 for var in v:
1389 text += "\n%s\t= %f"%(str(var),var.getValue())
1390 else:
1391 text += "\nnone"
1392 _dialog = InfoDialog(self,self.window,text,title,tabs=[100,200])
1393 _dialog.run()
1394
1395 def on_show_freeable_variables_activate(self,*args):
1396 try:
1397 v = self.sim.getFreeableVariables()
1398 except RuntimeError,e:
1399 self.reporter.reportError("Unable to show freeable variables: %s"%str(e))
1400 return
1401 text = "Freeable Variables"
1402 title = text
1403 text += "\n"
1404 if len(v):
1405 for var in v:
1406 text += "\n%s" % var
1407 else:
1408 text += "\nnone"
1409 _dialog = InfoDialog(self,self.window,text,title)
1410 _dialog.run()
1411
1412 def on_show_external_functions_activate(self,*args):
1413 v = self.library.getExtMethods()
1414 text = "External Functions"
1415 title = text
1416 text +="\nHere is the list of external functions currently present in"
1417 text +=" the Library:"
1418
1419 if len(v):
1420 for ext in v:
1421 text += "\n\n%s (%d inputs, %d outputs):" % \
1422 (ext.getName(), ext.getNumInputs(), ext.getNumOutputs())
1423 text += "\n%s" % ext.getHelp()
1424 else:
1425 text +="\n\nNone"
1426 _dialog = InfoDialog(self,self.window,text,title)
1427 _dialog.run()
1428
1429 def on_notes_view_activate(self,*args):
1430 t = None
1431 try:
1432 D = self.library.getAnnotationDatabase()
1433 i = self.modelview.get_selected_instance()
1434 if i and i.isModel():
1435 t = i.getType()
1436 else:
1437 self.reporter.reportError("First select a MODEL instance");
1438 return
1439 v = D.getNotes(t)
1440 except RuntimeError,e:
1441 self.reporter.reportError("Unable to show notes: %s"%str(e))
1442 return
1443 text = "Notes for '%s'" % t.getName()
1444 title = text
1445 text += "\nHere are all notes defined within this MODEL:"
1446 nn = {}
1447 if len(v):
1448 for n in v:
1449 text += "\n\n%s (%s):" % (n.getId(), n.getLanguage())
1450 text += "\n\t%s" % n.getText()
1451 else:
1452 text += "\n\nThere are no noted defined locally within in this model"
1453
1454 _dialog = InfoDialog(self,self.window,text,title)
1455 _dialog.run()
1456
1457 def on_maintabs_switch_page(self,notebook,page,pagenum):
1458 #print("Page switched to %d" % pagenum)
1459 if (pagenum in self.tabs.keys()) and self.tabs[pagenum].alive:
1460 self.currentobservertab = pagenum
1461 self.currentpage = pagenum
1462 else:
1463 self.currentpage = pagenum
1464 if pagenum == 1:
1465 self.enable_on_enter_sim_tab()
1466 self.modelview.modelview.grab_focus()
1467 else:
1468 self.disable_on_leave_sim_tab()
1469
1470 def create_observer(self,name=None):
1471 _imagelist = []
1472 for i in range(5):
1473 _imagelist.append("image%s" % (i+7))
1474 self.builder.add_objects_from_file(self.glade_file, _imagelist)
1475
1476 self.builder.add_objects_from_file(self.glade_file,["observervbox","observercontext"])
1477
1478 _label = gtk.Label();
1479 _tab = self.maintabs.append_page(self.builder.get_object("observervbox"),_label);
1480 _obs = ObserverTab(name=name, browser=self, tab=_tab)
1481 _label.set_text(_obs.name)
1482 self.observers.append(_obs)
1483 self.tabs[_tab] = _obs
1484 self.currentobservertab = _tab
1485
1486 self.builder.get_object("copy_observer_matrix").set_sensitive(True)
1487 self.builder.get_object("keep_observed").set_sensitive(True)
1488 return _obs
1489
1490 def sync_observers(self):
1491 for _o in self.observers:
1492 _o.sync()
1493
1494 def delete_event(self, widget, event):
1495 self.do_quit()
1496 return False
1497 #return self.exit_popup()
1498
1499 def exit_popup(self):
1500 dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO,
1501 gtk.BUTTONS_YES_NO, "Are you sure you want to Quit?")
1502 dialog.set_title("Exit popup")
1503 #dialog.set_default_size(600,300)
1504 response = dialog.run()
1505 dialog.destroy()
1506 if response == gtk.RESPONSE_YES:
1507 self.do_quit()
1508 return False
1509 else:
1510 return True
1511
1512 def observe(self,instance):
1513 if self.currentobservertab is None:
1514 self.create_observer()
1515 _observer = self.tabs[self.currentobservertab]
1516 _observer.add_instance(instance)
1517
1518 def auto_update_check(self):
1519 _p = self.prefs
1520 _no_auto_check = _p.getBoolPref("Browser", "disable_auto_check_for_updates", False)
1521
1522 if _no_auto_check is True:
1523 return
1524
1525 _time_now = time.time()
1526 _last_update = float(self.prefs.getStringPref("Browser","last_update_check","0"))
1527 print "Time since last update check : %f days" %((_time_now-_last_update)/(3600*24))
1528
1529 if ((_time_now-_last_update)/(3600*24)) < 7:
1530 return
1531
1532 _win = AutoUpdateDialog(self)
1533 _check_now = _win.run()
1534
1535 if _check_now is False:
1536 return
1537
1538 self.on_help_check_for_updates_click()
1539
1540 def on_check_weekly_toggled(self, widget):
1541 _p = self.prefs
1542 _p.setBoolPref("Browser", "disable_auto_check_for_updates", not(widget.get_active()))
1543
1544 def disable_menu(self):
1545 list=["free_variable","fix_variable","sparsity","propsmenuitem","copy_observer_matrix",
1546 "incidencegraph","diagnose_blocks","show_fixed_vars","show_freeable_vars",
1547 "show_fixable_variables","show_variables_near_bounds","show_vars_far_from_nominals1",
1548 "repaint_tree","checkbutton","solvebutton","integratebutton","methodrunbutton",
1549 "check1","solve1","integrate1","units","add_observer","keep_observed","preferences","notes_view"]
1550 for button in list:
1551 self.builder.get_object(button).set_sensitive(False)
1552
1553 def disable_on_leave_sim_tab(self):
1554 list =["free_variable","fix_variable","propsmenuitem","units"]
1555 for button in list:
1556 self.builder.get_object(button).set_sensitive(False)
1557
1558 def enable_on_enter_sim_tab(self):
1559 list =["free_variable","fix_variable","propsmenuitem","units"]
1560 for button in list:
1561 self.builder.get_object(button).set_sensitive(False)
1562 if hasattr(self.modelview,'sim'):
1563 _path, _col = self.modelview.modelview.get_cursor()
1564 _instance = None
1565 if _path:
1566 _name,_instance = self.modelview.otank[_path]
1567 if _instance is None:
1568 return
1569 if _instance.isReal():
1570 self.builder.get_object("units").set_sensitive(True)
1571 if _instance.getType().isRefinedSolverVar():
1572 self.builder.get_object("propsmenuitem").set_sensitive(True)
1573 if _instance.isFixed():
1574 self.builder.get_object("free_variable").set_sensitive(True)
1575 else:
1576 self.builder.get_object("fix_variable").set_sensitive(True)
1577 elif _instance.isRelation():
1578 self.builder.get_object("propsmenuitem").set_sensitive(True)
1579
1580 def enable_on_sim_build(self):
1581 list=["sparsity","incidencegraph","diagnose_blocks","show_fixed_vars","show_freeable_vars",
1582 "show_fixable_variables","show_variables_near_bounds","show_vars_far_from_nominals1","notes_view"]
1583 for button in list:
1584 self.builder.get_object(button).set_sensitive(True)
1585 def disable_on_first_run(self):
1586 list=["reloadbutton","reload","show_external_functions","notes_view"]
1587 for button in list:
1588 self.builder.get_object(button).set_sensitive(False)
1589 def enable_on_file_open(self):
1590 list=["reloadbutton","reload","show_external_functions"]
1591 for button in list:
1592 self.builder.get_object(button).set_sensitive(True)
1593 def enable_on_model_tree_build(self):
1594 list=["repaint_tree","checkbutton","solvebutton","integratebutton","methodrunbutton",
1595 "check1","solve1","integrate1","units","add_observer","preferences","notes_view"]
1596 for button in list:
1597 self.builder.get_object(button).set_sensitive(True)
1598 if __name__ == "__main__":
1599 b = Browser();
1600 b.run()
1601
1602 class ReloadDialog:
1603
1604 # Just a dialog to confirm that the user REALLY
1605 # wants to reload the model
1606
1607 def __init__(self, browser):
1608 browser.builder.add_objects_from_file(browser.glade_file, ["reloaddialog"])
1609 self.alertwin = browser.builder.get_object("reloaddialog")
1610 browser.builder.connect_signals(self)
1611
1612 def on_reloaddialog_close(self,*args):
1613 self.alertwin.response(gtk.RESPONSE_CLOSE)
1614
1615 def run(self):
1616 _continue = True
1617 while _continue:
1618 _res = self.alertwin.run()
1619 if _res == gtk.RESPONSE_YES:
1620 self.alertwin.destroy()
1621 return True
1622 else:
1623 self.alertwin.destroy()
1624 return False
1625
1626 class AutoUpdateDialog:
1627
1628 # A dialog to automatically check for updates
1629
1630 def __init__(self, browser):
1631 self.browser = browser
1632 browser.builder.add_objects_from_file(browser.glade_file, ["autoupdatedialog"])
1633 self.win = browser.builder.get_object("autoupdatedialog")
1634 self.checkbutton = browser.builder.get_object("autoupdate")
1635
1636 _p = self.browser.prefs
1637 self.checkbutton.set_active(_p.getBoolPref("Browser", "disable_auto_check_for_updates", False))
1638
1639 browser.builder.connect_signals(self)
1640
1641 def on_autoupdate_toggled(self, widget):
1642 _p = self.browser.prefs
1643 _p.setBoolPref("Browser", "disable_auto_check_for_updates", widget.get_active())
1644 self.browser.check_weekly.set_active(not(widget.get_active()))
1645
1646 def run(self):
1647 _continue = True
1648 while _continue:
1649 _res = self.win.run()
1650 if _res == gtk.RESPONSE_YES:
1651 self.win.destroy()
1652 return True
1653 elif _res == gtk.RESPONSE_NO or _res == gtk.RESPONSE_DELETE_EVENT or _res == gtk.RESPONSE_CLOSE:
1654 self.win.destroy()
1655 return False
1656

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