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

Contents of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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