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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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