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

Contents of /trunk/pygtk/observer.py

Parent Directory Parent Directory | Revision Log Revision Log


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

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