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

Annotation of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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