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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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