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

Annotation of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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