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

Annotation of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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