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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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