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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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