/[ascend]/branches/adrian/pygtk/gtkbrowser.py
ViewVC logotype

Contents of /branches/adrian/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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