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

Contents of /trunk/pygtk/observer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2495 - (show 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 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 start+=1
314 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 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 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 except Exception,e:
350 self.browser.reporter.reportError(str(e))
351
352 def do_add_row(self,values=None):
353 _store = self.view.get_model()
354 if self.alive:
355 _row = ObserverRow()
356 self.rows.append(_row)
357 if self.activeiter is not None:
358 _oldrow = _store.get_value(self.activeiter,0)
359 _oldrow.make_static(self)
360 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 else:
365 _row = ObserverRow(values=values,active=False,tainted=taint)
366 self.rows.append(_row)
367 _store.append(None,[_row])
368 #self.browser.reporter.reportNote("Added data row")
369
370 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
381 def sync(self):
382 self.view.queue_draw()
383 #self.browser.reporter.reportNote("SYNC performed")
384
385 def add_instance(self,instance):
386 _col = ObserverColumn(instance,self.colindex,browser=self.browser)
387
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 self.cols[self.colindex] = _col
394 self.colindex = self.colindex + 1
395
396 # create a new column
397 _renderer = gtk.CellRendererText()
398 _renderer.connect('edited',self.on_view_cell_edited, _col)
399 _tvcol = ClickableTreeColumn(_col.title)
400 _tvcol.pack_start(_renderer,False)
401 _tvcol.set_cell_data_func(_renderer, _col.cellvalue)
402 self.view.append_column(_tvcol);
403 _tvcol.do_connect()
404 #self.browser.reporter.reportError("cols = "+str(self.cols))
405
406 def copy_to_clipboard(self,clip):
407 _s = []
408 _s.append('\t'.join([_v.title for _k,_v in self.cols.iteritems()]))
409 #_cf = [_v.units.getConversion() for _k,_v in self.cols.iteritems()]
410 print "COPYING %d ROWS" % len(self.rows)
411 #print "CONVERSIONS:",_cf
412 for _r in self.rows:
413 _s.append("\t".join(["%s" % _v for _k, _v in _r.get_values(self).iteritems()]))
414
415 clip.set_text('\n'.join(_s),-1)
416
417 self.browser.reporter.reportNote("Observer '%s' data copied to clipboard" % self.name)
418
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