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

Annotation of /trunk/pygtk/gtkbrowser.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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