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

Annotation of /trunk/pygtk/observer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2495 - (hide annotations) (download) (as text)
Tue Aug 16 11:35:08 2011 UTC (12 years, 11 months ago) by aakash
File MIME type: text/x-python
File size: 24144 byte(s)
Merge further changes from Aakash to trunk.
1 johnpye 245 import pygtk
2     pygtk.require('2.0')
3     import gtk
4     import pango
5 jpye 1356 import os.path
6 johnpye 245
7 aakash 2494 from study import *
8     from unitsdialog import *
9    
10 johnpye 852 OBSERVER_EDIT_COLOR = "#008800"
11     OBSERVER_NOEDIT_COLOR = "#000088"
12     OBSERVER_NORMAL_COLOR = "black"
13 aakash 2494 OBSERVER_TAINTED_COLOR = "#FFBBBB"
14     OBSERVER_DEAD_COLOR = "#ababab"
15 johnpye 1053 # This code uses the techniques described in
16 johnpye 280 # http://www.daa.com.au/pipermail/pygtk/2006-February/011777.html
17 johnpye 1053 # http://piman.livejournal.com/361173.html
18 johnpye 280
19 johnpye 849 OBSERVER_NUM=0
20    
21 johnpye 1053 class ClickableTreeColumn(gtk.TreeViewColumn):
22     def __init__(self, title="", *args, **kwargs):
23     super(ClickableTreeColumn, self).__init__(None, *args, **kwargs)
24     self.label = gtk.Label("%s" % title)
25     self.label.show()
26     self.set_widget(self.label)
27 aakash 2494 self.title = title
28     #self.set_sort_column_id(0)
29     #self.set_clickable(True)
30 johnpye 1053
31     def do_connect(self):
32     """ Connect the defined 'on_click' method. Note: must be called after
33     this object (ClickableTreeColumn) has been added to the TreeView,
34     eg mytreeview.append_column(col). """
35     button = self.label.get_ancestor(gtk.Button)
36     h = button.connect("clicked",self.on_click)
37     #button.clicked()
38    
39     def on_click(self,widget,*args):
40     print "RECEIVED EVENT"
41    
42 johnpye 849 class ObserverColumn:
43     """
44     A class to identify the instance that relates to a specify column
45     and the units of measurement and column title, etc.
46     """
47     def __init__(self,instance,index,name=None,units=None,browser=None):
48     self.instance = instance
49     self.name = name
50     self.index = index
51    
52     if name==None:
53     if browser == None:
54     name = "UNNAMED"
55     else:
56     name = browser.sim.getInstanceName(instance)
57    
58 jpye 1735 if units is None:
59 johnpye 849 units = instance.getType().getPreferredUnits()
60 jpye 1735 if units is None:
61 johnpye 849 units = instance.getType().getDimensions().getDefaultUnits()
62    
63     uname = str(units.getName())
64 jpye 1387 if len(uname) or uname.find("/")!=-1:
65 johnpye 849 uname = "["+uname+"]"
66    
67     if uname == "":
68     _title = "%s" % (name)
69     else:
70     _title = "%s / %s" % (name, uname)
71    
72     self.title = _title
73     self.units = units
74     self.uname = uname
75     self.name = name
76    
77     def __repr__(self):
78     return "ObserverColumn(name="+self.name+")"
79    
80     def cellvalue(self, column, cell, model, iter):
81 johnpye 852 #print "RENDERING COLUMN",self.index
82 johnpye 849 _rowobject = model.get_value(iter,0)
83    
84 johnpye 852 cell.set_property('editable',False)
85     cell.set_property('weight',400)
86 johnpye 849 try:
87 aakash 2494 if _rowobject.active or _rowobject.dead:
88 johnpye 849 _rawval = self.instance.getRealValue()
89 johnpye 852 if self.instance.getType().isRefinedSolverVar():
90     if self.instance.isFixed():
91     cell.set_property('editable',True)
92     cell.set_property('weight',700)
93     cell.set_property('foreground',OBSERVER_EDIT_COLOR)
94     else:
95     cell.set_property('foreground',OBSERVER_NOEDIT_COLOR)
96 aakash 2494 _dataval = _rawval / self.units.getConversion()
97 johnpye 849 else:
98 johnpye 852 cell.set_property('foreground',OBSERVER_NORMAL_COLOR)
99 aakash 2494 try :
100     _rawval = _rowobject.values[self.index]
101     _dataval = _rawval / self.units.getConversion()
102     except:
103     _dataval = ""
104     if _rowobject.tainted is True:
105     cell.set_property('background', OBSERVER_TAINTED_COLOR)
106     elif _rowobject.dead:
107     cell.set_property('background', OBSERVER_DEAD_COLOR)
108     cell.set_property('editable', False)
109     else:
110     cell.set_property('background', None)
111 johnpye 856 except IndexError:
112 johnpye 853 _dataval = ""
113 johnpye 849
114     cell.set_property('text', _dataval)
115    
116     class ObserverRow:
117     """
118     Just a container for a vector of values, but with columns that
119     should correspond to those in the Observer object's vector of
120     ObserverColumn objects.
121     """
122 aakash 2494 def __init__(self,values=None,active=True,tainted=False):
123 johnpye 849 if values==None:
124 aakash 2494 values={}
125     self.tainted = tainted
126 johnpye 849 self.values = values
127     self.active = active
128 aakash 2494 self.dead = False
129     self.error_msg = None
130 johnpye 849
131     def make_static(self,table):
132     self.active = False
133     print "TABLE COLS:",table.cols
134     print "ROW VALUES:",self.values
135 aakash 2494 _v = {}
136 johnpye 856 for col in table.cols.values():
137 aakash 2494 _v[col.index] = col.instance.getRealValue()
138 johnpye 856 self.values = _v
139 johnpye 849 print "Made static, values:",self.values
140    
141 johnpye 852 def get_values(self,table):
142 aakash 2494 vv = {}
143 johnpye 852 if not self.active:
144 jpye 1366 for k,v in table.cols.iteritems():
145 aakash 2494 try:
146     vv[k]=(self.values[v.index]/v.units.getConversion())
147     except:
148     vv[k]=""
149 jpye 1366 return vv
150 johnpye 852 else:
151 aakash 2494 for index, col in table.cols.iteritems():
152     vv[index] = float(col.instance.getRealValue())/col.units.getConversion()
153     return vv
154 johnpye 852
155 johnpye 245 class ObserverTab:
156 johnpye 849
157 aakash 2494 def __init__(self,browser,tab,name=None,alive=True):
158 johnpye 849 global OBSERVER_NUM
159     self.colindex = 0
160     if name==None:
161     OBSERVER_NUM=OBSERVER_NUM+1
162     name = "Observer %d" % OBSERVER_NUM
163     self.name = name
164     self.browser=browser
165 aakash 2494 self.browser.builder.connect_signals(self)
166     self.view = self.browser.builder.get_object('observerview')
167     self.view.set_has_tooltip(True)
168     self.addbutton = self.browser.builder.get_object('add')
169 johnpye 849 self.tab = tab
170     self.alive=alive
171 aakash 2494 self.old_path = None
172     self.current_instance = None
173 johnpye 849 if self.alive:
174     self.browser.reporter.reportNote("New observer is 'alive'")
175    
176     self.keptimg = gtk.Image()
177     self.activeimg = gtk.Image()
178 aakash 2494 self.errorimg = gtk.Image()
179 jpye 1356 self.activeimg.set_from_file(os.path.join(browser.options.assets_dir,"active.png"))
180 aakash 2494 self.errorimg.set_from_file(os.path.join(browser.options.assets_dir,"solveerror.png"))
181 johnpye 849 # create PixBuf objects from these?
182     self.rows = []
183 johnpye 852 _store = gtk.TreeStore(object)
184 johnpye 849 self.cols = {}
185    
186     # create the 'active' pixbuf column
187     _renderer = gtk.CellRendererPixbuf()
188 johnpye 1053 _col = ClickableTreeColumn("")
189 johnpye 849 _col.pack_start(_renderer,False)
190     _col.set_cell_data_func(_renderer, self.activepixbufvalue)
191 johnpye 1053 self.view.append_column(_col)
192     _col.do_connect()
193 johnpye 849
194 aakash 2494 # get the context menu
195     self.treecontext=self.browser.builder.get_object("observercontext")
196     self.studycolumnmenuitem=self.browser.builder.get_object("study_column")
197     self.unitsmenuitem=self.browser.builder.get_object("units2")
198     self.deleterowmenuitem=self.browser.builder.get_object("delete_row")
199     self.deletecolumnmenuitem=self.browser.builder.get_object("delete_column")
200     self.plotmenuitem=self.browser.builder.get_object("plotmenuitem")
201 johnpye 849 # initially there will not be any other columns
202    
203     if self.alive:
204     # for a 'live' Observer, create the 'active' bottom row
205     self.browser.reporter.reportNote("Adding empty row to store")
206 johnpye 852 _row = ObserverRow()
207     self.activeiter = _store.append(None, [_row] )
208     self.rows.append(_row)
209 johnpye 849
210     self.view.set_model(_store)
211     self.browser.reporter.reportNote("Created observer '%s'" % self.name)
212 aakash 2494
213     _sel = self.view.get_selection()
214     _sel.set_mode(gtk.SELECTION_MULTIPLE)
215 johnpye 849
216     def activepixbufvalue(self,column,cell,model,iter):
217     _rowobject = model.get_value(iter,0)
218     if _rowobject.active:
219     cell.set_property('pixbuf',self.activeimg.get_pixbuf())
220 aakash 2494 elif _rowobject.tainted:
221     cell.set_property('pixbuf',self.errorimg.get_pixbuf())
222 johnpye 849 else:
223     cell.set_property('pixbuf',self.keptimg.get_pixbuf())
224    
225     def on_add_clicked(self,*args):
226     self.do_add_row()
227    
228     def on_clear_clicked(self,*args):
229 aakash 2494 if self.alive is False:
230     self.on_close_observer_clicked()
231     return
232 johnpye 852 _store = self.view.get_model()
233     _store.clear();
234 jpye 1367 self.rows = []
235 aakash 2494 _row = ObserverRow()
236     self.activeiter = _store.append(None, [_row] )
237     self.rows.append(_row)
238 johnpye 849
239 jpye 1387 def plot(self,x=None,y=None,y2=None):
240     """create a plot from two columns in the ObserverTable"""
241     import platform
242     import matplotlib
243     matplotlib.use('GTKAgg')
244     import pylab
245     pylab.ioff()
246     if x is None or y is None:
247     if len(self.cols)<2:
248     raise Exception("Not enough columns to plot (need 2+)")
249     if x is None:
250     x=self.cols[0]
251     if y is None:
252     y=self.cols[1]
253    
254     if x.__class__ is int and x>=0 and x<len(self.cols):
255     x=self.cols[x]
256     if y.__class__ is int and y>=0 and y<len(self.cols):
257     y=self.cols[y]
258     if y2.__class__ is int and y2>=0 and y2<len(self.cols):
259 aakash 2495 y2=self.cols[y2]
260 jpye 1387
261     ncols = 2
262 aakash 2494 start = None
263 jpye 1387 if y2 is not None:
264     ncols+=1
265 aakash 2494 _p = self.browser.prefs
266     _ignore = _p.getBoolPref("PlotDialog", "ignore_error_points", True)
267     r = {}
268     if _ignore == False:
269     for i in range(len(self.rows)-1):
270     try:
271     r = self.rows[i].get_values(self)
272     if r[x.index] and r[y.index]:
273     if start == None:
274     start = i
275     break
276     except:
277     continue
278     if start == None:
279     self.browser.reporter.reportError("Can't plot, could not get enough points.")
280     return
281     A = pylab.zeros((len(self.rows)-1-start,ncols),'f')
282     i = 0
283     while start <len(self.rows)-1:
284     r = self.rows[start].get_values(self)
285     A[i,0]=r[x.index]
286     A[i,1]=r[y.index]
287     if y2 is not None:
288     A[i,2]=r[y2.index]
289     start+=1
290     i+=1
291     else:
292     j = 0
293     k = 0
294     # we need to initiate A according to the number of error
295     # free rows/points going to be plotted
296     for i in range(len(self.rows)-1):
297     if self.rows[i].tainted is False:
298     try:
299     r = self.rows[i].get_values(self)
300     if r[x.index] and r[y.index]:
301     if start == None:
302     start = i
303     j=0
304     j+=1
305     except:
306     continue
307     if start == None:
308     self.browser.reporter.reportError("Can't plot, could not get enough points.")
309 aakash 2495 return
310 aakash 2494 A = pylab.zeros((j,ncols),'f')
311     while start<len(self.rows)-1:
312     if self.rows[start].tainted is True:
313 aakash 2495 start+=1
314 aakash 2494 continue
315     r = self.rows[start].get_values(self)
316     A[k,0]=r[x.index]
317     A[k,1]=r[y.index]
318     if y2 is not None:
319     A[k,2]=r[y2.index]
320     k+=1
321     start+=1
322    
323 jpye 1387 pylab.figure()
324     p1 = pylab.plot(A[:,0],A[:,1],'b-')
325     pylab.xlabel(x.title)
326     pylab.ylabel(y.title)
327    
328     if y2 is not None:
329     ax2 = pylab.twinx()
330     p2 = pylab.plot(A[:,0],A[:,2],'r-')
331     pylab.ylabel(y2.title)
332     ax2.yaxis.tick_right()
333     pylab.legend([y.name,y2.name])
334    
335     pylab.ion()
336     if platform.system()=="Windows":
337     pylab.show()
338     else:
339     pylab.show(False)
340    
341     def on_plot_clicked(self,*args):
342     try:
343 aakash 2494 if len(self.cols)<2:
344     raise Exception("Not enough columns to plot (need 2+)")
345     _plotwin = PlotDialog(self.browser, self)
346     _plot = _plotwin.run()
347     if _plot:
348     self.plot(x=_plotwin.xcol, y=_plotwin.ycol)
349 jpye 1387 except Exception,e:
350     self.browser.reporter.reportError(str(e))
351    
352 johnpye 854 def do_add_row(self,values=None):
353     _store = self.view.get_model()
354 johnpye 849 if self.alive:
355 johnpye 852 _row = ObserverRow()
356     self.rows.append(_row)
357 aakash 2494 if self.activeiter is not None:
358     _oldrow = _store.get_value(self.activeiter,0)
359     _oldrow.make_static(self)
360 johnpye 852 self.activeiter = _store.append(None,[_row])
361     _path = _store.get_path(self.activeiter)
362     _oldpath,_oldcol = self.view.get_cursor()
363     self.view.set_cursor(_path, _oldcol)
364 johnpye 849 else:
365 aakash 2494 _row = ObserverRow(values=values,active=False,tainted=taint)
366 johnpye 854 self.rows.append(_row)
367     _store.append(None,[_row])
368 johnpye 894 #self.browser.reporter.reportNote("Added data row")
369 aakash 2494
370 johnpye 852 def on_view_cell_edited(self, renderer, path, newtext, col):
371     # we can assume it's always the self.activeiter that is edited...
372     if col.instance.isFixed():
373     val = float(newtext) * col.units.getConversion()
374     col.instance.setRealValue( val )
375     self.browser.reporter.reportNote("Updated value to %f" % float(newtext))
376     else:
377     self.browser.reporter.reportError("Can't set a FREE variable from the Observer")
378     return
379     self.browser.do_solve_if_auto()
380 johnpye 849
381     def sync(self):
382 johnpye 852 self.view.queue_draw()
383 johnpye 894 #self.browser.reporter.reportNote("SYNC performed")
384 johnpye 849
385     def add_instance(self,instance):
386     _col = ObserverColumn(instance,self.colindex,browser=self.browser)
387 aakash 2494
388     # the loop is to ensure that we dont add multiple columns for the same variable
389     for _cols in self.cols:
390     if self.cols[_cols].title == _col.title:
391     del(_col)
392     return
393 johnpye 849 self.cols[self.colindex] = _col
394     self.colindex = self.colindex + 1
395    
396     # create a new column
397     _renderer = gtk.CellRendererText()
398 johnpye 852 _renderer.connect('edited',self.on_view_cell_edited, _col)
399 johnpye 1053 _tvcol = ClickableTreeColumn(_col.title)
400 johnpye 849 _tvcol.pack_start(_renderer,False)
401     _tvcol.set_cell_data_func(_renderer, _col.cellvalue)
402     self.view.append_column(_tvcol);
403 johnpye 1053 _tvcol.do_connect()
404 johnpye 888 #self.browser.reporter.reportError("cols = "+str(self.cols))
405 johnpye 849
406 johnpye 852 def copy_to_clipboard(self,clip):
407     _s = []
408     _s.append('\t'.join([_v.title for _k,_v in self.cols.iteritems()]))
409 jpye 1387 #_cf = [_v.units.getConversion() for _k,_v in self.cols.iteritems()]
410 johnpye 852 print "COPYING %d ROWS" % len(self.rows)
411 jpye 1387 #print "CONVERSIONS:",_cf
412 johnpye 852 for _r in self.rows:
413 aakash 2494 _s.append("\t".join(["%s" % _v for _k, _v in _r.get_values(self).iteritems()]))
414 johnpye 852
415     clip.set_text('\n'.join(_s),-1)
416    
417     self.browser.reporter.reportNote("Observer '%s' data copied to clipboard" % self.name)
418 aakash 2494
419     def on_observerview_query_tooltip(self, widget, _x, _y, keyboard_mode, _tooltip):
420     _store = self.view.get_model()
421     _pthinfo = self.view.get_path_at_pos(_x, _y)
422    
423     if _pthinfo is None:
424     return False
425     _path, _col, _cellx, _celly = _pthinfo
426     _temp, = _path
427     if(_temp==0):
428     return False
429     _path = _temp-1,
430    
431     # the folowing is to ensure that the tooltip
432     # gets refreshed for each row
433     if self.old_path == _path:
434     _iter = _store.get_iter(_path)
435     _rowobject = _store.get_value(_iter,0)
436     if _rowobject.error_msg is None:
437     return False
438     _tooltip.set_text(_rowobject.error_msg)
439     return True
440     else:
441     self.old_path = _path
442     return False
443    
444     def set_all_menu_items_sensitive(self):
445     self.unitsmenuitem.set_sensitive(True)
446     self.studycolumnmenuitem.set_sensitive(True)
447     self.plotmenuitem.set_sensitive(True)
448     self.deletecolumnmenuitem.set_sensitive(True)
449    
450     def on_treeview_event(self,widget,event):
451    
452     _path = None
453     _delete_row = False
454     _contextmenu = False
455    
456     _sel = self.view.get_selection()
457     _model, _rowlist = _sel.get_selected_rows()
458     if event.type==gtk.gdk.KEY_PRESS:
459     _keyval = gtk.gdk.keyval_name(event.keyval)
460     _path, _col = self.view.get_cursor()
461     if _path is not None:
462     if _keyval=='Menu':
463     self.set_all_menu_items_sensitive()
464     _contextmenu = True
465     _button = 3
466     elif _keyval=='Delete' or _keyval=='BackSpace':
467     _delete_row = True
468    
469     elif event.type==gtk.gdk.BUTTON_PRESS:
470     _x = int(event.x)
471     _y = int(event.y)
472     _button = event.button
473     _pthinfo = self.view.get_path_at_pos(_x, _y)
474     if _pthinfo is not None:
475     _path, _col, _cellx, _celly = _pthinfo
476     if event.button == 3:
477     self.set_all_menu_items_sensitive()
478     _contextmenu = True
479    
480     if not (_contextmenu or _delete_row):
481     #print "NOT DOING ANYTHING ABOUT %s" % gtk.gdk.keyval_name(event.keyval)
482     return
483    
484     if len(_rowlist)>1:
485     self.unitsmenuitem.set_sensitive(False)
486     self.studycolumnmenuitem.set_sensitive(False)
487     self.plotmenuitem.set_sensitive(False)
488     self.deletecolumnmenuitem.set_sensitive(False)
489     if _delete_row:
490     self.on_delete_row()
491     return
492     self.treecontext.popup( None, None, None, _button, event.time)
493     return
494    
495     self.view.grab_focus()
496     self.view.set_cursor( _path, _col, 0)
497    
498     self.current_path = _path
499     self.current_col = _col
500     self.current_instance = None
501     if _delete_row:
502     self.on_delete_row()
503     elif self.alive is False:
504     self.unitsmenuitem.set_sensitive(False)
505     self.studycolumnmenuitem.set_sensitive(False)
506     self.treecontext.popup( None, None, None, _button, event.time)
507     else:
508     # Since we have the instance data in self.cols and treeview points us to the
509     # ClickableTreeColumn, we need to match the two.
510     for _cols in self.cols:
511     if self.cols[_cols].title == self.current_col.title:
512     self.current_instance = self.cols[_cols].instance
513     self.current_col_key = _cols
514     break
515     if self.current_instance is None:
516     return 0
517     if self.current_instance.isFixed() == False:
518     self.studycolumnmenuitem.set_sensitive(False)
519     self.treecontext.popup( None, None, None, _button, event.time)
520     return 1
521    
522     def on_study_column_activate(self, *args):
523     if self.current_instance is not None:
524     _dia = StudyWin(self.browser,self.current_instance)
525     _dia.run()
526    
527     def on_delete_row(self, *args):
528     # We need to remove the row from two places,
529     # the treestore, and our own list of ObserverRows
530    
531     _sel = self.view.get_selection()
532     _store, _rowlist = _sel.get_selected_rows()
533     i = 0
534     (x,) = _rowlist[0]
535     for _path in _rowlist:
536     if len(self.rows) == x+1:
537     self.browser.reporter.reportWarning("Can't delete the active row")
538     return
539     self.rows.pop(x)
540     _store.remove(_store.get_iter((x,)))
541    
542     # now that we have deleted the row, it is
543     # time to move the cursor to the next available element
544    
545     self.view.grab_focus()
546     self.view.set_cursor((x,), self.current_col, 0)
547    
548     def taint_row(self, msg, _rowobject = None):
549     # to set the solver error message as the row's tooltip
550     _store = self.view.get_model()
551     if _rowobject is None:
552     _rowobject = _store.get_value(self.activeiter,0)
553     _rowobject.error_msg = msg
554     _rowobject.tainted = True
555    
556     def on_delete_column(self, *args):
557     # To delete columns
558     self.cols.pop(self.current_col_key)
559     self.view.remove_column(self.current_col)
560    
561     def on_plotmenuitem_activate(self, *args):
562     # To preselect the column as y axis
563     try:
564     if len(self.cols)<2:
565     raise Exception("Not enough columns to plot (need 2+)")
566     _plotwin = PlotDialog(self.browser, self)
567     _plotwin.select_ycol(self.cols[self.current_col_key], self)
568     _plot = _plotwin.run()
569     if _plot:
570     self.plot(x=_plotwin.xcol, y=_plotwin.ycol)
571     except Exception,e:
572     self.browser.reporter.reportError(str(e))
573    
574     def on_close_observer_clicked(self, *args):
575     # First, the dialog box is brought up, and if the user clicks on yes,
576     # the observer tab is closed. Need to make sure that this instance is
577     # removed from the list of observers maintained in the browser
578    
579     _alertwin = CloseDialog(self.browser)
580     destroy = _alertwin.run()
581     if destroy:
582     self.view.destroy()
583     if self.browser.currentobservertab == self.browser.currentpage:
584     self.browser.currentobservertab = None
585     self.browser.maintabs.remove_page(self.browser.currentpage)
586     self.rows = []
587     self.browser.observers.remove(self)
588    
589     def on_units_activate(self, *args):
590     if self.current_instance is not None:
591     T = self.current_instance.getType()
592     _un = UnitsDialog(self.browser,T)
593     _un.run()
594    
595     def units_refresh(self, instance_type):
596     for _col in self.cols.values():
597     _units = None
598     _units = instance_type.getPreferredUnits()
599     if _units is None:
600     _units = instance_type.getDimensions().getDefaultUnits()
601     _uname = str(_units.getName())
602    
603     _col_type = _col.instance.getType()
604     _col_units = _col_type.getPreferredUnits()
605     if _col_units is None:
606     _col_units = _col_type.getDimensions().getDefaultUnits()
607     _col_uname = str(_col_units.getName())
608    
609     if _col_uname == _uname:
610     if self.browser == None:
611     name = "UNNAMED"
612     else:
613     name = self.browser.sim.getInstanceName(_col.instance)
614    
615     _uname = str(_units.getName())
616     if len(_uname) or _uname.find("/")!=-1:
617     _uname = "["+_uname+"]"
618    
619     if _uname == "":
620     _title = "%s" % (name)
621     else:
622     _title = "%s / %s" % (name, _uname)
623     for _tvcol in self.view.get_columns():
624     if _tvcol.title == _col.title:
625     _tvcol.label.set_text(str(_title))
626     _tvcol.title = _title
627     _tvcol.set_title(_title)
628     _col.title = _title
629     _col.units = _units
630     _col.uname = _uname
631     _col.name = name
632     def set_dead(self):
633     self.alive = False
634     self.addbutton.set_sensitive(False)
635     _selection = self.view.get_selection()
636     _selection.unselect_all()
637     _store = self.view.get_model()
638     if self.activeiter is not None:
639     _rowobject = _store.get_value(self.activeiter,0)
640     _rowobject.active = False
641     _rowobject.dead = True
642     self.activeiter = None
643    
644     class CloseDialog:
645    
646     # Just a dialog to confirm that the user REALLY wants to close
647     # the observer
648    
649     def __init__(self, browser):
650     browser.builder.add_objects_from_file(browser.glade_file, ["closeobserverdialog"])
651     self.alertwin = browser.builder.get_object("closeobserverdialog")
652     browser.builder.connect_signals(self)
653    
654     def on_closeobserverdialog_close(self,*args):
655     self.alertwin.response(gtk.RESPONSE_CLOSE)
656    
657     def run(self):
658     _continue = True
659     while _continue:
660     _res = self.alertwin.run()
661     if _res == gtk.RESPONSE_YES:
662     self.alertwin.destroy()
663     return True
664     else:
665     self.alertwin.destroy()
666     return False
667    
668     class PlotDialog:
669    
670     # a dialog where the user can select which columns to plot
671    
672     def __init__(self, browser, tab):
673     self.browser = browser
674     self.browser.builder.add_objects_from_file(browser.glade_file, ["plotdialog"])
675     self.plotwin = self.browser.builder.get_object("plotdialog")
676     self.plotbutton = self.browser.builder.get_object("plotbutton")
677     self.xview = self.browser.builder.get_object("treeview1")
678     self.yview = self.browser.builder.get_object("treeview2")
679     self.ignorepoints = self.browser.builder.get_object("ignorepoints")
680    
681     _p = self.browser.prefs
682     _ignore = _p.getBoolPref("PlotDialog", "ignore_error_points", True)
683     self.ignorepoints.set_active(_ignore)
684    
685     _xstore = gtk.TreeStore(object)
686     self.xview.set_model(_xstore)
687     _xrenderer = gtk.CellRendererText()
688     _xtvcol = gtk.TreeViewColumn("X axis")
689     _xtvcol.pack_start(_xrenderer,False)
690     _xtvcol.set_cell_data_func(_xrenderer, self.varlist)
691     self.xview.append_column(_xtvcol)
692    
693     _ystore = gtk.TreeStore(object)
694     self.yview.set_model(_ystore)
695     _yrenderer = gtk.CellRendererText()
696     _ytvcol = gtk.TreeViewColumn("Y axis")
697     _ytvcol.pack_start(_yrenderer,False)
698     _ytvcol.set_cell_data_func(_yrenderer, self.varlist)
699     self.yview.append_column(_ytvcol)
700    
701     self.xcol = None
702     self.ycol = None
703     for _cols in tab.cols:
704     _xtemp = _xstore.append(None, [tab.cols[_cols]])
705     _ytemp = _ystore.append(None, [tab.cols[_cols]])
706     if self.xcol is None:
707     self.xcol = tab.cols[_cols]
708     _xiter = _xtemp
709     continue
710     if self.ycol is None:
711     self.ycol = tab.cols[_cols]
712     _yiter = _ytemp
713     self.plotbutton.set_sensitive(True)
714    
715     _selx = self.xview.get_selection()
716     _selx.select_iter(_xiter)
717    
718     _sely = self.yview.get_selection()
719     _sely.select_iter(_yiter)
720    
721     self.browser.builder.connect_signals(self)
722    
723     def on_plotdialog_close(self,*args):
724     self.plotwin.response(gtk.RESPONSE_CANCEL)
725    
726     def varlist(self,column,cell,model,iter):
727     _value = model.get_value(iter,0)
728     cell.set_property('text', _value.title)
729    
730     def on_treeview_event(self,widget,event):
731    
732     _path = None
733     _col = None
734     self.plotbutton.set_sensitive(False)
735     if event.type==gtk.gdk.KEY_RELEASE:
736     _keyval = gtk.gdk.keyval_name(event.keyval)
737     if _keyval == "Escape":
738     self.plotwin.response(gtk.RESPONSE_CANCEL)
739     return
740     _path, _tvcol = widget.get_cursor()
741     if _path is None:
742     return
743    
744     elif event.type==gtk.gdk.BUTTON_RELEASE:
745     _x = int(event.x)
746     _y = int(event.y)
747     _button = event.button
748     _pthinfo = widget.get_path_at_pos(_x, _y)
749     if _pthinfo is None:
750     return
751     _path, _tvcol, _cellx, _celly = _pthinfo
752     if _path is None:
753     return
754    
755     _sel = widget.get_selection()
756     _view, _iter = _sel.get_selected()
757     if _iter is None:
758     return
759     _path = _view.get_path(_iter)
760     if _path is None:
761     return
762    
763     widget.grab_focus()
764     widget.set_cursor( _path, None, 0)
765    
766     _store = widget.get_model()
767     _iter = _store.get_iter(_path)
768     _col = _store.get_value(_iter,0)
769     if widget is self.xview:
770     self.xcol = _col
771     else:
772     self.ycol = _col
773    
774     if self.xcol is not None and self.ycol is not None:
775     if self.xcol.title == self.ycol.title:
776     if widget is self.xview:
777     self.yview.get_selection().unselect_all()
778     self.ycol = None
779     else:
780     self.xview.get_selection().unselect_all()
781     self.xcol = None
782     else:
783     self.plotbutton.set_sensitive(True)
784    
785     def select_ycol(self, _col, _tab):
786     _ystore = self.yview.get_model()
787     _iter = _ystore.get_iter_first()
788     for i in _tab.cols:
789     _item = _ystore.get_value(_iter, 0)
790     if _item.title == _col.title:
791     self.ycol = _col
792     _sel = self.yview.get_selection()
793     _sel.unselect_all()
794     _sel.select_iter(_iter)
795     self.xcol = None
796     self.xview.get_selection().unselect_all()
797     self.plotbutton.set_sensitive(False)
798     _iter = _ystore.iter_next(_iter)
799    
800     def run(self):
801     _continue = True
802     while _continue:
803     _res = self.plotwin.run()
804     if _res == gtk.RESPONSE_YES:
805     _p = self.browser.prefs
806     _p.setBoolPref("PlotDialog", "ignore_error_points", self.ignorepoints.get_active())
807     self.plotwin.destroy()
808     return True
809     else:
810     self.plotwin.destroy()
811     return False

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