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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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