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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 273 - (hide annotations) (download) (as text)
Sun Feb 5 06:44:06 2006 UTC (13 years, 7 months ago) by johnpye
File MIME type: text/x-python
File size: 29501 byte(s)
Added reporting of relations and residuals via GUI
1 johnpye 132 #!/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 johnpye 230 import preferences # loading/saving of .ini options
10 johnpye 132 import urlparse
11     import optparse
12    
13 johnpye 230 from solverparameters import * # 'solver parameters' window
14 johnpye 268 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 johnpye 230
20 johnpye 132 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 johnpye 227 ESCAPE_KEY = 65307
35    
36 johnpye 230 HELP_ROOT = None
37    
38 johnpye 255 BROWSER_FIXED_COLOR = "#008800"
39     BROWSER_FREE_COLOR = "#000088"
40 johnpye 223 #======================================
41     # Browser is the main ASCEND library/model browser window
42    
43 johnpye 132 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 johnpye 160 parser.add_option("-m", "--model"
56     ,action="store", type="string", dest="model"
57     ,help="specify the model to instantiate upon loading modules")
58 johnpye 132 (options, args) = parser.parse_args()
59    
60     #print "OPTIONS_______________:",options
61    
62 johnpye 246 self.observers = []
63 johnpye 251 self.clip = None
64 johnpye 246
65 johnpye 132 #--------
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 johnpye 208
84 johnpye 132 if not self.window:
85     raise RuntimeError("Couldn't load window from glade file")
86 johnpye 172
87 johnpye 173 _display = self.window.get_screen().get_display().get_name();
88     _geom=self.prefs.getGeometrySizePosition(_display,"browserwin")
89 johnpye 172 if _geom:
90     self.window.resize(_geom[0],_geom[1]);
91     self.window.move(_geom[2],_geom[3]);
92 johnpye 173
93 johnpye 132 self.window.connect("delete_event", self.delete_event)
94    
95 johnpye 173 self.browserpaned=glade.get_widget("browserpaned");
96     _geom2=self.prefs.getGeometryValue(_display,"browserpaned");
97     if _geom2:
98     self.browserpaned.set_position(_geom2);
99    
100 johnpye 132 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 johnpye 230 self.is_auto = self.autotoggle.get_active()
116    
117 johnpye 132 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 johnpye 164 self.statusbar = glade.get_widget("statusbar")
125    
126 johnpye 208 self.menu = glade.get_widget("browsermenu")
127     glade.signal_autoconnect(self)
128    
129 johnpye 230 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 johnpye 132 #-------------------
135 johnpye 164 # 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 johnpye 132 # 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 johnpye 255 # pixbufs for solver_var status
157    
158 johnpye 268 self.fixedimg = gtk.Image()
159     self.fixedimg.set_from_file('icons/locked.png')
160    
161 johnpye 258 self.iconstatusunknown = None
162 johnpye 268 self.iconfixed = self.fixedimg.get_pixbuf()
163 johnpye 255 self.iconsolved = self.window.render_icon(gtk.STOCK_YES,gtk.ICON_SIZE_MENU)
164 johnpye 258 self.iconactive = self.window.render_icon(gtk.STOCK_NO,gtk.ICON_SIZE_MENU)
165 johnpye 255 self.iconunsolved = None
166    
167     self.statusicons={
168     ascend.ASCXX_VAR_STATUS_UNKNOWN: self.iconstatusunknown
169 johnpye 258 ,ascend.ASCXX_VAR_FIXED: self.iconfixed
170 johnpye 255 ,ascend.ASCXX_VAR_SOLVED: self.iconsolved
171     ,ascend.ASCXX_VAR_ACTIVE: self.iconactive
172     ,ascend.ASCXX_VAR_UNSOLVED: self.iconunsolved
173     }
174 johnpye 273 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 johnpye 255
182     #--------------------
183 johnpye 132 # set up the context menu for fixing/freeing vars
184    
185 johnpye 226 # TODO import this menu from Glade (this code is a PITA)
186    
187 johnpye 132 self.treecontext = gtk.Menu();
188 johnpye 181 self.fixmenuitem = gtk.ImageMenuItem("_Fix",True);
189 johnpye 268 self.fixmenuitem.set_image(self.fixedimg)
190 johnpye 181
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 johnpye 246 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 johnpye 207 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 johnpye 246 self.observemenuitem.show(); self.observemenuitem.set_sensitive(False)
215 johnpye 181 self.propsmenuitem.show()
216 johnpye 246 self.treecontext.append(self.fixmenuitem)
217     self.treecontext.append(self.freemenuitem)
218 johnpye 181 _sep = gtk.SeparatorMenuItem(); _sep.show()
219     self.treecontext.append(_sep);
220 johnpye 246 self.treecontext.append(self.plotmenuitem)
221     self.treecontext.append(self.observemenuitem)
222 johnpye 181 _sep = gtk.SeparatorMenuItem(); _sep.show()
223 johnpye 246 self.treecontext.append(_sep)
224     self.treecontext.append(self.propsmenuitem)
225 johnpye 132 self.fixmenuitem.connect("activate",self.fix_activate)
226     self.freemenuitem.connect("activate",self.free_activate)
227 johnpye 175 self.plotmenuitem.connect("activate",self.plot_activate)
228 johnpye 181 self.propsmenuitem.connect("activate",self.props_activate)
229 johnpye 246 self.observemenuitem.connect("activate",self.observe_activate)
230    
231 johnpye 132 if not self.treecontext:
232     raise RuntimeError("Couldn't create browsercontext")
233     #--------------------
234     # set up the error view
235    
236 johnpye 168 self.errorview = glade.get_widget("errorview")
237 johnpye 132 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 johnpye 255
303     # name, type, value, foreground, weight, editable, status-icon
304     columns = [str,str,str,str,int,bool,gtk.gdk.Pixbuf]
305 johnpye 132 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 johnpye 270 self.treeview.connect("button-press-event", self.on_treeview_event )
312     self.treeview.connect("key-press-event",self.on_treeview_event )
313 johnpye 132
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 johnpye 255 if(i==2):
322     # add status icon
323     renderer1 = gtk.CellRendererPixbuf()
324 johnpye 258 tvcolumn.pack_start(renderer1, False)
325 johnpye 255 tvcolumn.add_attribute(renderer1, 'pixbuf', 6)
326    
327 johnpye 132 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 johnpye 223
351 johnpye 132 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 johnpye 164 _context = self.statusbar.get_context_id("do_open")
364    
365 johnpye 132 self.errorstore.clear()
366    
367     self.treestore.clear()
368     self.otank = {}
369    
370 johnpye 175 # self.library.clear()
371 johnpye 164
372     self.statusbar.push(_context,"Loading '"+filename+"'")
373 johnpye 132 self.library.load(filename)
374 johnpye 164 self.statusbar.pop(_context)
375 johnpye 132
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 johnpye 164
399 johnpye 168 # See http://www.daa.com.au/pipermail/pygtk/2005-October/011303.html
400     # for details on how the 'wait cursor' is done.
401 johnpye 164 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 johnpye 132
411 johnpye 164 def stop_waiting(self):
412     if self.waitwin:
413     self.statusbar.pop(self.waitcontext)
414     self.waitwin.hide()
415    
416 johnpye 132 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 johnpye 164 self.start_waiting("Compiling...")
422    
423 johnpye 132 self.sim = type_object.getSimulation(str(type_object.getName())+"_sim")
424     print "...DONE 'getSimulation'"
425 johnpye 164 self.stop_waiting()
426 johnpye 132
427 johnpye 164 self.start_waiting("Building simulation...")
428 johnpye 132 print "BUILDING SIMULATION"
429 johnpye 164 self.sim.build()
430 johnpye 132 print "DONE BUILDING"
431 johnpye 164 self.stop_waiting()
432 johnpye 132
433 johnpye 223 self.sim.setSolver(ascend.Solver("QRSlv"))
434    
435 johnpye 132 # empty things out first
436     self.methodstore.clear()
437     self.treestore.clear()
438    
439     # methods
440     _methods = self.sim.getType().getMethods()
441 johnpye 160 _activemethod = None;
442 johnpye 132 for _m in _methods:
443 johnpye 160 _i = self.methodstore.append([_m.getName()])
444     if _m.getName()=="default_self":
445     self.methodsel.set_active_iter(_i)
446 johnpye 132
447     # instance hierarchy
448     self.otank = {} # map path -> (name,value)
449     self.make( self.sim.getName(),self.sim.getModel() )
450     self.maintabs.set_current_page(1);
451 johnpye 249
452     def do_solve_if_auto(self):
453     if self.is_auto:
454     self.sim.check()
455     self.do_solve()
456     else:
457 johnpye 255 self.sim.processVarStatus()
458 johnpye 249 self.refreshtree()
459    
460     self.sync_observers()
461 johnpye 132
462     def do_solve(self):
463     if not self.sim:
464     self.reporter.reportError("No model selected yet")
465 johnpye 171 return;
466 johnpye 132
467 johnpye 168 self.start_waiting("Solving...")
468 johnpye 164
469 johnpye 154 self.sim.solve(ascend.Solver("QRSlv"))
470 johnpye 164
471 johnpye 168 self.stop_waiting()
472 johnpye 255
473     self.sim.processVarStatus()
474 johnpye 132 self.refreshtree()
475    
476     def do_check(self):
477     if not self.sim:
478     self.reporter.reportError("No model selected yet")
479    
480 johnpye 171 self.start_waiting("Checking system...")
481    
482 johnpye 132 if self.sim.check():
483     self.reporter.reportNote("System check OK")
484 johnpye 171
485 johnpye 132 self.sim.checkDoF()
486    
487 johnpye 171 self.stop_waiting()
488    
489 johnpye 132 self.refreshtree()
490    
491     def do_method(self,method):
492     if not self.sim:
493     self.reporter.reportError("No model selected yet")
494    
495     self.sim.run(method)
496     self.refreshtree()
497    
498 johnpye 230 def do_quit(self):
499     self.reporter.clearPythonErrorCallback()
500     _w,_h = self.window.get_size()
501     _t,_l = self.window.get_position()
502     _display = self.window.get_screen().get_display().get_name()
503     self.prefs.setGeometrySizePosition(_display,"browserwin",_w,_h,_t,_l );
504    
505     _p = self.browserpaned.get_position()
506     self.prefs.setGeometryValue(_display,"browserpaned",_p);
507    
508     # causes prefs to be saved unless they are still being used elsewher
509     del(self.prefs)
510    
511     gtk.main_quit()
512     print "GTK QUIT"
513     return False
514    
515 johnpye 231 def on_tools_sparsity_click(self,*args):
516 johnpye 237
517     self.reporter.reportNote("Preparing incidence matrix...")
518 johnpye 233 _im = self.sim.getIncidenceMatrix();
519 johnpye 231
520 johnpye 237 self.reporter.reportNote("Plotting incidence matrix...")
521 johnpye 234
522 johnpye 237 _sp = IncidenceMatrixWindow(_im);
523     _sp.run();
524    
525 johnpye 245 def on_add_observer_click(self,*args):
526 johnpye 246 if len(self.observers) >= 1:
527     self.reporter.reportError("Not supported: multiple observers")
528     return
529     self.observers.append(self.create_observer())
530 johnpye 245
531 johnpye 250 def on_keep_observed_click(self,*args):
532     if len(self.observers) > 1:
533     self.reporter.reportError("Not supported: multiple observers")
534     return
535     if len(self.observers) <= 0:
536     self.reporter.reportError("No observer defined!")
537     return
538     self.observers[0].do_add_row()
539    
540     def on_copy_observer_matrix_click(self,*args):
541 johnpye 251 if self.clip == None:
542     self.clip = gtk.Clipboard()
543    
544 johnpye 250 if len(self.observers) > 1:
545     self.reporter.reportError("Not supported: multiple observers")
546     return
547     if len(self.observers) <= 0:
548     self.reporter.reportError("No observer defined!")
549     return
550 johnpye 251 self.observers[0].copy_to_clipboard(self.clip)
551 johnpye 270
552 johnpye 132 # --------------------------------------------
553     # MODULE LIST
554    
555     def module_activated(self, treeview, path, column, *args):
556     modules = self.library.getModules()
557     print "PATH",path
558     if len(path)==1:
559     self.reporter.reportNote("Launching of external editor not yet implemented")
560     elif len(path)==2:
561     if(self.modtank.has_key(path)):
562     _type = self.modtank[path];
563     self.reporter.reportNote("Creating simulation for type %s" % str(_type.getName()) )
564     self.do_sim(_type)
565     else:
566     self.reporter.reportError("Didn't find type corresponding to row")
567    
568     # --------------------------------------------
569     # INSTANCE TREE
570    
571 johnpye 255 def get_tree_row_data(self,instance): # for instance browser
572 johnpye 132 _value = str(instance.getValue())
573     _type = str(instance.getType())
574     _name = str(instance.getName())
575     _fgcolor = "black"
576     _fontweight = pango.WEIGHT_NORMAL
577     _editable = False
578 johnpye 273 _statusicon = None
579 johnpye 132 if instance.getType().isRefinedSolverVar():
580     _editable = True
581 johnpye 255 _fontweight = pango.WEIGHT_BOLD
582 johnpye 132 if instance.isFixed():
583 johnpye 255 _fgcolor = BROWSER_FIXED_COLOR
584 johnpye 132 else:
585 johnpye 255 _fgcolor = BROWSER_FREE_COLOR
586 johnpye 132 _fontweight = pango.WEIGHT_BOLD
587 johnpye 273 _status = instance.getVarStatus();
588     _statusicon = self.statusicons[_status]
589    
590 johnpye 132 elif instance.isBool() or instance.isReal() or instance.isInt():
591     # TODO can't edit constants that have already been refined
592     _editable = True
593    
594     #if(len(_value) > 80):
595     # _value = _value[:80] + "..."
596    
597 johnpye 255 return [_name, _type, _value, _fgcolor, _fontweight, _editable, _statusicon]
598 johnpye 132
599 johnpye 255 def make_row( self, piter, name, value ): # for instance browser
600 johnpye 132
601     _piter = self.treestore.append( piter, self.get_tree_row_data(value) )
602     return _piter
603    
604     def refreshtree(self):
605     # @TODO FIXME use a better system than colour literals!
606     for _path in self.otank: # { path : (name,value) }
607     _iter = self.treestore.get_iter(_path)
608     _name, _instance = self.otank[_path]
609     self.treestore.set_value(_iter, 2, _instance.getValue())
610     if _instance.getType().isRefinedSolverVar():
611 johnpye 255 if _instance.isFixed() and self.treestore.get_value(_iter,3)==BROWSER_FREE_COLOR:
612     self.treestore.set_value(_iter,3,BROWSER_FIXED_COLOR)
613     elif not _instance.isFixed() and self.treestore.get_value(_iter,3)==BROWSER_FIXED_COLOR:
614     self.treestore.set_value(_iter,3,BROWSER_FREE_COLOR)
615 johnpye 273 self.treestore.set_value(_iter, 6, self.statusicons[_instance.getVarStatus()])
616 johnpye 132
617     def cell_edited_callback(self, renderer, path, newtext, **kwargs):
618     # get back the Instance object we just edited (having to use this seems like a bug)
619     path = tuple( map(int,path.split(":")) )
620    
621     if not self.otank.has_key(path):
622     raise RuntimeError("cell_edited_callback: invalid path '%s'" % path)
623     return
624    
625     _name, _instance = self.otank[path]
626    
627     if _instance.isReal():
628     # only real-valued things can have units
629    
630 johnpye 268 _e = RealAtomEntry(_instance,newtext);
631 johnpye 132 try:
632 johnpye 268 _e.checkEntry()
633     _e.setValue()
634     _e.exportPreferredUnits(self.prefs)
635     except InputError, e:
636     self.reporter.reportError(str(e))
637     return;
638 johnpye 132
639     else:
640     if _instance.isBool():
641     _lower = newtext.lower();
642     if _lower.startswith("t") or _lower.startswith("y") or _lower.strip()=="1":
643     newtext = 1
644     elif _lower.startswith("f") or _lower.startswith("n") or _lower.strip()=="0":
645     newtext = 0
646     else:
647     self.reporter.reportError("Invalid entry for a boolean variable: '%s'" % newtext)
648     return
649     _val = bool(newtext);
650     if _val == _instance.getValue():
651     self.reporter.reportNote("Boolean atom '%s' was not altered" % _instance.getName())
652     return
653     _instance.setBoolValue(_val)
654    
655     elif _instance.isInt():
656     _val = int(newtext)
657     if _val == _instance.getValue():
658     self.reporter.reportNote("Integer atom '%s' was not altered" % _instance.getName())
659     return
660     _instance.setIntValue(_val)
661     else:
662     self.reporter.reportError("Attempt to set a non-real, non-boolean, non-integer value!")
663     return
664    
665     # now that the variable is set, update the GUI and re-solve if desired
666     _iter = self.treestore.get_iter(path)
667     self.treestore.set_value(_iter,2,_instance.getValue())
668    
669     if _instance.getType().isRefinedSolverVar():
670 johnpye 255 self.treestore.set_value(_iter,3,BROWSER_FIXED_COLOR) # set the row green as fixed
671 johnpye 132
672 johnpye 249 self.do_solve_if_auto()
673 johnpye 132
674     def make_children(self, value, piter ):
675     if value.isCompound():
676     children=value.getChildren();
677     for child in children:
678     _name = child.getName();
679     _piter = self.make_row(piter,_name,child)
680     _path = self.treestore.get_path(_piter)
681     self.otank[_path]=(_name,child)
682     #self.reporter.reportError("2 Added %s at path %s" % (_name,repr(_path)))
683    
684     def make(self, name=None, value=None, path=None, depth=1):
685     if path is None:
686     # make root node
687     piter = self.make_row( None, name, value )
688     path = self.treestore.get_path( piter )
689     self.otank[ path ] = (name, value)
690     #self.reporter.reportError("4 Added %s at path %s" % (name, path))
691     else:
692     name, value = self.otank[ path ]
693    
694     piter = self.treestore.get_iter( path )
695     if not self.treestore.iter_has_child( piter ):
696     self.make_children(value,piter)
697    
698     if depth:
699     for i in range( self.treestore.iter_n_children( piter ) ):
700     self.make( path = path+(i,), depth = depth - 1 )
701 johnpye 160 else:
702     self.treeview.expand_row("0",False)
703 johnpye 132
704     def row_expanded( self, treeview, piter, path ):
705     self.make( path = path )
706    
707     # ----------------------------------
708     # ERROR PANEL
709    
710 johnpye 255 def get_error_row_data(self,sev,filename,line,msg):
711     _sevicon = {
712     0: self.iconok
713     ,1: self.iconinfo
714     ,2: self.iconwarning
715     ,3: self.iconerror
716     ,4: self.iconinfo
717     ,5: self.iconwarning
718     ,6: self.iconerror
719     }[sev]
720    
721     _fontweight = pango.WEIGHT_NORMAL
722     if sev==6:
723     _fontweight = pango.WEIGHT_BOLD
724    
725     _fgcolor = "black"
726     if sev==4:
727     _fgcolor = "#888800"
728     elif sev==5:
729     _fgcolor = "#884400"
730     elif sev==6:
731     _fgcolor = "#880000"
732     elif sev==0:
733     _fgcolor = BROWSER_FIXED_COLOR
734    
735     if not filename and not line:
736     _fileline = ""
737     else:
738     if(len(filename) > 25):
739     filename = "..."+filename[-22:]
740     _fileline = filename + ":" + str(line)
741    
742     _res = [_sevicon,_fileline,msg.rstrip(),_fgcolor,_fontweight]
743     #print _res
744     return _res
745    
746 johnpye 132 def error_callback(self,sev,filename,line,msg):
747     pos = self.errorstore.append(None, self.get_error_row_data(sev, filename,line,msg))
748     path = self.errorstore.get_path(pos)
749     col = self.errorview.get_column(3)
750     self.errorview.scroll_to_cell(path,col)
751    
752     return 0;
753    
754     # --------------------------------
755     # BUTTON METHODS
756    
757     def open_click(self,*args):
758     dialog = gtk.FileChooserDialog("Open file...",
759 johnpye 160 None,
760     gtk.FILE_CHOOSER_ACTION_OPEN,
761     (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
762     gtk.STOCK_OPEN, gtk.RESPONSE_OK))
763 johnpye 132 dialog.set_default_response(gtk.RESPONSE_OK)
764    
765     filter = gtk.FileFilter()
766     filter.set_name("*.a4c, *.a4l")
767     filter.add_pattern("*.[Aa]4[Cc]")
768     filter.add_pattern("*.[Aa]4[Ll]")
769     dialog.add_filter(filter)
770    
771     filter = gtk.FileFilter()
772     filter.set_name("All files")
773     filter.add_pattern("*")
774     dialog.add_filter(filter)
775    
776     response = dialog.run()
777     _filename = dialog.get_filename()
778     dialog.destroy()
779    
780     if response == gtk.RESPONSE_OK:
781     self.reporter.reportNote("File %s selected." % dialog.get_filename() )
782 johnpye 185 self.library.clear()
783 johnpye 132 self.do_open( _filename)
784    
785    
786     def reload_click(self,*args):
787     _type = None
788     if(self.sim):
789     _type = self.sim.getType().getName().toString();
790    
791 johnpye 185 self.library.clear()
792 johnpye 132 self.do_open(self.filename)
793    
794     if _type:
795     _t = self.library.findType(_type)
796     self.do_sim(_t)
797    
798     def solve_click(self,*args):
799     #self.reporter.reportError("Solving simulation '" + self.sim.getName().toString() +"'...")
800     self.do_solve()
801    
802     def check_click(self,*args):
803     self.do_check()
804     #self.reporter.reportError("CHECK clicked")
805    
806 johnpye 208 def preferences_click(self,*args):
807     if not self.sim:
808     self.reporter.reportError("No simulation created yet!");
809    
810 johnpye 235 _paramswin = SolverParametersWindow(self.sim, self.reporter, GLADE_FILE)
811 johnpye 223 _paramswin.show()
812 johnpye 221
813 johnpye 132 def methodrun_click(self,*args):
814     _sel = self.methodsel.get_active_text()
815     if _sel:
816     _method = None
817     _methods = self.sim.getType().getMethods()
818     for _m in _methods:
819     if _m.getName()==_sel:
820     _method = _m
821     if not _method:
822     self.reporter.reportError("Method is not valid")
823     return
824     self.do_method(_method)
825     else:
826     self.reporter.reportError("No method selected")
827    
828     def auto_toggle(self,button,*args):
829 johnpye 230 self.is_auto = button.get_active()
830     self.automenu.set_active(self.is_auto)
831    
832     if self.is_auto:
833 johnpye 168 self.reporter.reportSuccess("Auto mode is now ON")
834 johnpye 132 else:
835 johnpye 168 self.reporter.reportSuccess("Auto mode is now OFF")
836 johnpye 132
837 johnpye 230 def on_file_quit_click(self,*args):
838     self.do_quit()
839    
840     def on_tools_auto_toggle(self,checkmenuitem,*args):
841     self.is_auto = checkmenuitem.get_active()
842     self.autotoggle.set_active(self.is_auto)
843    
844     def on_help_about_click(self,*args):
845     _xml = gtk.glade.XML(GLADE_FILE,"aboutdialog");
846     _dialog = _xml.get_widget("aboutdialog")
847     _dialog.run()
848     _dialog.destroy()
849    
850     def on_help_contents_click(self,*args):
851     _help = Help(HELP_ROOT)
852     _help.run()
853    
854 johnpye 245 def create_observer(self,name=None):
855     if name==None:
856     name="New Observer"
857    
858     _xml = gtk.glade.XML(GLADE_FILE,"observervbox");
859     _label = gtk.Label();
860     _label.set_text(name)
861 johnpye 252 _tab = self.maintabs.append_page(_xml.get_widget("observervbox"),_label);
862     self.observers.append(ObserverTab(_xml, name, self, _tab))
863 johnpye 249
864     def sync_observers(self):
865     for _o in self.observers:
866     _o.sync()
867    
868 johnpye 132 # ------------------------------
869     # CONTEXT MENU
870    
871 johnpye 270 def on_treeview_event(self,widget,event):
872     _contextmenu = False;
873 johnpye 271 if event.type==gtk.gdk.KEY_PRESS and gtk.gdk.keyval_name(event.keyval)=='Menu':
874     _contextmenu = True
875     _path, _col = self.treeview.get_cursor()
876     _button = 3;
877 johnpye 270 elif event.type==gtk.gdk.BUTTON_PRESS:
878     if event.button == 3:
879     _contextmenu = True
880     _x = int(event.x)
881     _y = int(event.y)
882     _button = event.button
883     _pthinfo = self.treeview.get_path_at_pos(_x, _y)
884     if _pthinfo == None:
885     return
886     _path, _col, _cellx, _celly = _pthinfo
887    
888 johnpye 132 # which button was clicked?
889 johnpye 270 if not _contextmenu:
890     return
891 johnpye 172
892 johnpye 270 _canpop = False;
893     # self.reporter.reportError("Right click on %s" % self.otank[_path][0])
894     _instance = self.otank[_path][1]
895     if _instance.getType().isRefinedSolverVar():
896     _canpop = True;
897     self.observemenuitem.set_sensitive(True)
898     if _instance.isFixed():
899     self.fixmenuitem.set_sensitive(False)
900     self.freemenuitem.set_sensitive(True)
901     else:
902     self.fixmenuitem.set_sensitive(True)
903     self.freemenuitem.set_sensitive(False)
904     elif _instance.isRelation():
905     _canpop = True;
906     self.propsmenuitem.set_sensitive(True)
907 johnpye 172
908 johnpye 270 if _instance.isPlottable():
909     self.plotmenuitem.set_sensitive(True)
910     _canpop = True;
911     else:
912     self.plotmenuitem.set_sensitive(False)
913 johnpye 132
914 johnpye 270 if not _canpop:
915     return
916    
917     self.treeview.grab_focus()
918     self.treeview.set_cursor( _path, _col, 0)
919     self.treecontext.popup( None, None, None, _button, event.time)
920     return 1
921    
922 johnpye 132 def fix_activate(self,widget):
923     _path,_col = self.treeview.get_cursor()
924     _name, _instance = self.otank[_path]
925     _instance.setFixed(True)
926     self.reporter.reportNote("Fixed variable %s" % _instance.getName().toString())
927 johnpye 249 self.do_solve_if_auto()
928 johnpye 132 return 1
929    
930     def free_activate(self,widget):
931     _path,_col = self.treeview.get_cursor()
932     _instance = self.otank[_path][1]
933     _instance.setFixed(False)
934     self.reporter.reportNote("Freed variable %s" % _instance.getName().toString())
935 johnpye 249 self.do_solve_if_auto()
936 johnpye 132 return 1
937    
938 johnpye 172 def plot_activate(self,widget):
939 johnpye 175 self.reporter.reportNote("plot_activate...");
940 johnpye 172 _path,_col = self.treeview.get_cursor()
941     _instance = self.otank[_path][1]
942     if not _instance.isPlottable():
943 johnpye 175 self.reporter.reportError("Can't plot instance %s" % _instance.getName().toString())
944 johnpye 172 return
945 johnpye 175 else:
946     self.reporter.reportNote("Instance %s about to be plotted..." % _instance.getName().toString())
947 johnpye 172
948 johnpye 175 print("Plotting instance '%s'..." % _instance.getName().toString())
949    
950 johnpye 176 _plot = _instance.getPlot()
951 johnpye 175
952 johnpye 176 print "Title: ", _plot.getTitle()
953 johnpye 180 _plot.show(True)
954 johnpye 176
955 johnpye 172 return 1
956    
957 johnpye 181 def props_activate(self,widget):
958 johnpye 207 _path,_col = self.treeview.get_cursor()
959     _instance = self.otank[_path][1]
960     if _instance.isRelation():
961 johnpye 215 print "Relation '"+_instance.getName().toString()+"':", \
962     _instance.getRelationAsString(self.sim.getModel())
963 johnpye 273 _dia = RelPropsWin(GLADE_FILE,self,_instance);
964     _dia.run();
965 johnpye 268 elif _instance.getType().isRefinedSolverVar():
966     _dia = VarPropsWin(GLADE_FILE,self,_instance);
967     _dia.run();
968 johnpye 207 else:
969 johnpye 271 self.reporter.reportWarning("Select a variable first...")
970 johnpye 172
971 johnpye 246 def observe_activate(self,widget):
972     _path,_col = self.treeview.get_cursor()
973     _instance = self.otank[_path][1]
974     if _instance.getType().isRefinedSolverVar():
975     print "OBSERVING",_instance.getName().toString()
976     if len(self.observers) > 1:
977     self.reporter.reportError("Not implemented: multiple observers")
978     return
979     if len(self.observers) ==0:
980     self.create_observer()
981     _observer = self.observers[0]
982     _observer.add_instance(_instance)
983 johnpye 270
984     def delete_event(self, widget, event):
985 johnpye 230 self.do_quit()
986 johnpye 132 return False
987    
988     def test():
989     import ascend
990     b = Browser();
991     b.run()
992    
993     if __name__ == "__main__":
994     test()

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