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

Contents of /trunk/pygtk/observer.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2598 - (show annotations) (download) (as text)
Tue Apr 17 21:00:29 2012 UTC (12 years, 3 months ago) by jpye
File MIME type: text/x-python
File size: 24100 byte(s)
Rename to StudyReporter in studyreporter.py (seems to be duplication from solverreporter.py?).
Fixed some unit conversions in tmy3.c, test file seems correct now (to float precision at least).
Suppressed some debug output to try to speed up Study feature, not there yet.
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 pylab.show()
337
338 def on_plot_clicked(self,*args):
339 try:
340 if len(self.cols)<2:
341 raise Exception("Not enough columns to plot (need 2+)")
342 _plotwin = PlotDialog(self.browser, self)
343 _plot = _plotwin.run()
344 if _plot:
345 self.plot(x=_plotwin.xcol, y=_plotwin.ycol)
346 except Exception,e:
347 self.browser.reporter.reportError(str(e))
348
349 def do_add_row(self,values=None):
350 _store = self.view.get_model()
351 if self.alive:
352 _row = ObserverRow()
353 self.rows.append(_row)
354 if self.activeiter is not None:
355 _oldrow = _store.get_value(self.activeiter,0)
356 _oldrow.make_static(self)
357 self.activeiter = _store.append(None,[_row])
358 _path = _store.get_path(self.activeiter)
359 _oldpath,_oldcol = self.view.get_cursor()
360 self.view.set_cursor(_path, _oldcol)
361 else:
362 _row = ObserverRow(values=values,active=False,tainted=taint)
363 self.rows.append(_row)
364 _store.append(None,[_row])
365 #self.browser.reporter.reportNote("Added data row")
366
367 def on_view_cell_edited(self, renderer, path, newtext, col):
368 # we can assume it's always the self.activeiter that is edited...
369 if col.instance.isFixed():
370 val = float(newtext) * col.units.getConversion()
371 col.instance.setRealValue( val )
372 self.browser.reporter.reportNote("Updated value to %f" % float(newtext))
373 else:
374 self.browser.reporter.reportError("Can't set a FREE variable from the Observer")
375 return
376 self.browser.do_solve_if_auto()
377
378 def sync(self):
379 self.view.queue_draw()
380 #self.browser.reporter.reportNote("SYNC performed")
381
382 def add_instance(self,instance):
383 _col = ObserverColumn(instance,self.colindex,browser=self.browser)
384
385 # the loop is to ensure that we dont add multiple columns for the same variable
386 for _cols in self.cols:
387 if self.cols[_cols].title == _col.title:
388 del(_col)
389 return
390 self.cols[self.colindex] = _col
391 self.colindex = self.colindex + 1
392
393 # create a new column
394 _renderer = gtk.CellRendererText()
395 _renderer.connect('edited',self.on_view_cell_edited, _col)
396 _tvcol = ClickableTreeColumn(_col.title)
397 _tvcol.pack_start(_renderer,False)
398 _tvcol.set_cell_data_func(_renderer, _col.cellvalue)
399 self.view.append_column(_tvcol);
400 _tvcol.do_connect()
401 #self.browser.reporter.reportError("cols = "+str(self.cols))
402
403 def copy_to_clipboard(self,clip):
404 _s = []
405 _s.append('\t'.join([_v.title for _k,_v in self.cols.iteritems()]))
406 #_cf = [_v.units.getConversion() for _k,_v in self.cols.iteritems()]
407 print "COPYING %d ROWS" % len(self.rows)
408 #print "CONVERSIONS:",_cf
409 for _r in self.rows:
410 _s.append("\t".join(["%s" % _v for _k, _v in _r.get_values(self).iteritems()]))
411
412 clip.set_text('\n'.join(_s),-1)
413
414 self.browser.reporter.reportNote("Observer '%s' data copied to clipboard" % self.name)
415
416 def on_observerview_query_tooltip(self, widget, _x, _y, keyboard_mode, _tooltip):
417 _store = self.view.get_model()
418 _pthinfo = self.view.get_path_at_pos(_x, _y)
419
420 if _pthinfo is None:
421 return False
422 _path, _col, _cellx, _celly = _pthinfo
423 _temp, = _path
424 if(_temp==0):
425 return False
426 _path = _temp-1,
427
428 # the folowing is to ensure that the tooltip
429 # gets refreshed for each row
430 if self.old_path == _path:
431 _iter = _store.get_iter(_path)
432 _rowobject = _store.get_value(_iter,0)
433 if _rowobject.error_msg is None:
434 return False
435 _tooltip.set_text(_rowobject.error_msg)
436 return True
437 else:
438 self.old_path = _path
439 return False
440
441 def set_all_menu_items_sensitive(self):
442 self.unitsmenuitem.set_sensitive(True)
443 self.studycolumnmenuitem.set_sensitive(True)
444 self.plotmenuitem.set_sensitive(True)
445 self.deletecolumnmenuitem.set_sensitive(True)
446
447 def on_treeview_event(self,widget,event):
448
449 _path = None
450 _delete_row = False
451 _contextmenu = False
452
453 _sel = self.view.get_selection()
454 _model, _rowlist = _sel.get_selected_rows()
455 if event.type==gtk.gdk.KEY_PRESS:
456 _keyval = gtk.gdk.keyval_name(event.keyval)
457 _path, _col = self.view.get_cursor()
458 if _path is not None:
459 if _keyval=='Menu':
460 self.set_all_menu_items_sensitive()
461 _contextmenu = True
462 _button = 3
463 elif _keyval=='Delete' or _keyval=='BackSpace':
464 _delete_row = True
465
466 elif event.type==gtk.gdk.BUTTON_PRESS:
467 _x = int(event.x)
468 _y = int(event.y)
469 _button = event.button
470 _pthinfo = self.view.get_path_at_pos(_x, _y)
471 if _pthinfo is not None:
472 _path, _col, _cellx, _celly = _pthinfo
473 if event.button == 3:
474 self.set_all_menu_items_sensitive()
475 _contextmenu = True
476
477 if not (_contextmenu or _delete_row):
478 #print "NOT DOING ANYTHING ABOUT %s" % gtk.gdk.keyval_name(event.keyval)
479 return
480
481 if len(_rowlist)>1:
482 self.unitsmenuitem.set_sensitive(False)
483 self.studycolumnmenuitem.set_sensitive(False)
484 self.plotmenuitem.set_sensitive(False)
485 self.deletecolumnmenuitem.set_sensitive(False)
486 if _delete_row:
487 self.on_delete_row()
488 return True
489 self.treecontext.popup( None, None, None, _button, event.time)
490 return
491
492 self.view.grab_focus()
493 self.view.set_cursor( _path, _col, 0)
494
495 self.current_path = _path
496 self.current_col = _col
497 self.current_instance = None
498 if _delete_row:
499 self.on_delete_row()
500 elif self.alive is False:
501 self.unitsmenuitem.set_sensitive(False)
502 self.studycolumnmenuitem.set_sensitive(False)
503 self.treecontext.popup( None, None, None, _button, event.time)
504 else:
505 # Since we have the instance data in self.cols and treeview points us to the
506 # ClickableTreeColumn, we need to match the two.
507 for _cols in self.cols:
508 if self.cols[_cols].title == self.current_col.title:
509 self.current_instance = self.cols[_cols].instance
510 self.current_col_key = _cols
511 break
512 if self.current_instance is None:
513 return 0
514 if self.current_instance.isFixed() == False:
515 self.studycolumnmenuitem.set_sensitive(False)
516 self.treecontext.popup( None, None, None, _button, event.time)
517 return 1
518
519 def on_study_column_activate(self, *args):
520 if self.current_instance is not None:
521 _dia = StudyWin(self.browser,self.current_instance)
522 _dia.run()
523
524 def on_delete_row(self, *args):
525 # We need to remove the row from two places,
526 # the treestore, and our own list of ObserverRows
527
528 _sel = self.view.get_selection()
529 _store, _rowlist = _sel.get_selected_rows()
530 i = 0
531 (x,) = _rowlist[0]
532 for _path in _rowlist:
533 if len(self.rows) == x+1:
534 self.browser.reporter.reportWarning("Can't delete the active row")
535 return
536 self.rows.pop(x)
537 _store.remove(_store.get_iter((x,)))
538
539 # now that we have deleted the row, it is
540 # time to move the cursor to the next available element
541
542 self.view.grab_focus()
543 self.view.set_cursor((x,), self.current_col, 0)
544
545 def taint_row(self, msg, _rowobject = None):
546 # to set the solver error message as the row's tooltip
547 _store = self.view.get_model()
548 if _rowobject is None:
549 _rowobject = _store.get_value(self.activeiter,0)
550 _rowobject.error_msg = msg
551 _rowobject.tainted = True
552
553 def on_delete_column(self, *args):
554 # To delete columns
555 self.cols.pop(self.current_col_key)
556 self.view.remove_column(self.current_col)
557
558 def on_plotmenuitem_activate(self, *args):
559 # To preselect the column as y axis
560 try:
561 if len(self.cols)<2:
562 raise Exception("Not enough columns to plot (need 2+)")
563 _plotwin = PlotDialog(self.browser, self)
564 _plotwin.select_ycol(self.cols[self.current_col_key], self)
565 _plot = _plotwin.run()
566 if _plot:
567 self.plot(x=_plotwin.xcol, y=_plotwin.ycol)
568 except Exception,e:
569 self.browser.reporter.reportError(str(e))
570
571 def on_close_observer_clicked(self, *args):
572 # First, the dialog box is brought up, and if the user clicks on yes,
573 # the observer tab is closed. Need to make sure that this instance is
574 # removed from the list of observers maintained in the browser
575
576 _alertwin = CloseDialog(self.browser)
577 destroy = _alertwin.run()
578 if destroy:
579 self.view.destroy()
580 if self.browser.currentobservertab == self.browser.currentpage:
581 self.browser.currentobservertab = None
582 self.browser.maintabs.remove_page(self.browser.currentpage)
583 self.rows = []
584 self.browser.observers.remove(self)
585
586 def on_units_activate(self, *args):
587 if self.current_instance is not None:
588 T = self.current_instance.getType()
589 _un = UnitsDialog(self.browser,T)
590 _un.run()
591
592 def units_refresh(self, instance_type):
593 for _col in self.cols.values():
594 _units = None
595 _units = instance_type.getPreferredUnits()
596 if _units is None:
597 _units = instance_type.getDimensions().getDefaultUnits()
598 _uname = str(_units.getName())
599
600 _col_type = _col.instance.getType()
601 _col_units = _col_type.getPreferredUnits()
602 if _col_units is None:
603 _col_units = _col_type.getDimensions().getDefaultUnits()
604 _col_uname = str(_col_units.getName())
605
606 if _col_uname == _uname:
607 if self.browser == None:
608 name = "UNNAMED"
609 else:
610 name = self.browser.sim.getInstanceName(_col.instance)
611
612 _uname = str(_units.getName())
613 if len(_uname) or _uname.find("/")!=-1:
614 _uname = "["+_uname+"]"
615
616 if _uname == "":
617 _title = "%s" % (name)
618 else:
619 _title = "%s / %s" % (name, _uname)
620 for _tvcol in self.view.get_columns():
621 if _tvcol.title == _col.title:
622 _tvcol.label.set_text(str(_title))
623 _tvcol.title = _title
624 _tvcol.set_title(_title)
625 _col.title = _title
626 _col.units = _units
627 _col.uname = _uname
628 _col.name = name
629 def set_dead(self):
630 self.alive = False
631 self.addbutton.set_sensitive(False)
632 _selection = self.view.get_selection()
633 _selection.unselect_all()
634 _store = self.view.get_model()
635 if self.activeiter is not None:
636 _rowobject = _store.get_value(self.activeiter,0)
637 _rowobject.active = False
638 _rowobject.dead = True
639 self.activeiter = None
640
641 class CloseDialog:
642
643 # Just a dialog to confirm that the user REALLY wants to close
644 # the observer
645
646 def __init__(self, browser):
647 browser.builder.add_objects_from_file(browser.glade_file, ["closeobserverdialog"])
648 self.alertwin = browser.builder.get_object("closeobserverdialog")
649 browser.builder.connect_signals(self)
650
651 def on_closeobserverdialog_close(self,*args):
652 self.alertwin.response(gtk.RESPONSE_CLOSE)
653
654 def run(self):
655 _continue = True
656 while _continue:
657 _res = self.alertwin.run()
658 if _res == gtk.RESPONSE_YES:
659 self.alertwin.destroy()
660 return True
661 else:
662 self.alertwin.destroy()
663 return False
664
665 class PlotDialog:
666
667 # a dialog where the user can select which columns to plot
668
669 def __init__(self, browser, tab):
670 self.browser = browser
671 self.browser.builder.add_objects_from_file(browser.glade_file, ["plotdialog"])
672 self.plotwin = self.browser.builder.get_object("plotdialog")
673 self.plotbutton = self.browser.builder.get_object("plotbutton")
674 self.xview = self.browser.builder.get_object("treeview1")
675 self.yview = self.browser.builder.get_object("treeview2")
676 self.ignorepoints = self.browser.builder.get_object("ignorepoints")
677
678 _p = self.browser.prefs
679 _ignore = _p.getBoolPref("PlotDialog", "ignore_error_points", True)
680 self.ignorepoints.set_active(_ignore)
681
682 _xstore = gtk.TreeStore(object)
683 self.xview.set_model(_xstore)
684 _xrenderer = gtk.CellRendererText()
685 _xtvcol = gtk.TreeViewColumn("X axis")
686 _xtvcol.pack_start(_xrenderer,False)
687 _xtvcol.set_cell_data_func(_xrenderer, self.varlist)
688 self.xview.append_column(_xtvcol)
689
690 _ystore = gtk.TreeStore(object)
691 self.yview.set_model(_ystore)
692 _yrenderer = gtk.CellRendererText()
693 _ytvcol = gtk.TreeViewColumn("Y axis")
694 _ytvcol.pack_start(_yrenderer,False)
695 _ytvcol.set_cell_data_func(_yrenderer, self.varlist)
696 self.yview.append_column(_ytvcol)
697
698 self.xcol = None
699 self.ycol = None
700 for _cols in tab.cols:
701 _xtemp = _xstore.append(None, [tab.cols[_cols]])
702 _ytemp = _ystore.append(None, [tab.cols[_cols]])
703 if self.xcol is None:
704 self.xcol = tab.cols[_cols]
705 _xiter = _xtemp
706 continue
707 if self.ycol is None:
708 self.ycol = tab.cols[_cols]
709 _yiter = _ytemp
710 self.plotbutton.set_sensitive(True)
711
712 _selx = self.xview.get_selection()
713 _selx.select_iter(_xiter)
714
715 _sely = self.yview.get_selection()
716 _sely.select_iter(_yiter)
717
718 self.browser.builder.connect_signals(self)
719
720 def on_plotdialog_close(self,*args):
721 self.plotwin.response(gtk.RESPONSE_CANCEL)
722
723 def varlist(self,column,cell,model,iter):
724 _value = model.get_value(iter,0)
725 cell.set_property('text', _value.title)
726
727 def on_treeview_event(self,widget,event):
728
729 _path = None
730 _col = None
731 self.plotbutton.set_sensitive(False)
732 if event.type==gtk.gdk.KEY_RELEASE:
733 _keyval = gtk.gdk.keyval_name(event.keyval)
734 if _keyval == "Escape":
735 self.plotwin.response(gtk.RESPONSE_CANCEL)
736 return
737 _path, _tvcol = widget.get_cursor()
738 if _path is None:
739 return
740
741 elif event.type==gtk.gdk.BUTTON_RELEASE:
742 _x = int(event.x)
743 _y = int(event.y)
744 _button = event.button
745 _pthinfo = widget.get_path_at_pos(_x, _y)
746 if _pthinfo is None:
747 return
748 _path, _tvcol, _cellx, _celly = _pthinfo
749 if _path is None:
750 return
751
752 _sel = widget.get_selection()
753 _view, _iter = _sel.get_selected()
754 if _iter is None:
755 return
756 _path = _view.get_path(_iter)
757 if _path is None:
758 return
759
760 widget.grab_focus()
761 widget.set_cursor( _path, None, 0)
762
763 _store = widget.get_model()
764 _iter = _store.get_iter(_path)
765 _col = _store.get_value(_iter,0)
766 if widget is self.xview:
767 self.xcol = _col
768 else:
769 self.ycol = _col
770
771 if self.xcol is not None and self.ycol is not None:
772 if self.xcol.title == self.ycol.title:
773 if widget is self.xview:
774 self.yview.get_selection().unselect_all()
775 self.ycol = None
776 else:
777 self.xview.get_selection().unselect_all()
778 self.xcol = None
779 else:
780 self.plotbutton.set_sensitive(True)
781
782 def select_ycol(self, _col, _tab):
783 _ystore = self.yview.get_model()
784 _iter = _ystore.get_iter_first()
785 for i in _tab.cols:
786 _item = _ystore.get_value(_iter, 0)
787 if _item.title == _col.title:
788 self.ycol = _col
789 _sel = self.yview.get_selection()
790 _sel.unselect_all()
791 _sel.select_iter(_iter)
792 self.xcol = None
793 self.xview.get_selection().unselect_all()
794 self.plotbutton.set_sensitive(False)
795 _iter = _ystore.iter_next(_iter)
796
797 def run(self):
798 _continue = True
799 while _continue:
800 _res = self.plotwin.run()
801 if _res == gtk.RESPONSE_YES:
802 _p = self.browser.prefs
803 _p.setBoolPref("PlotDialog", "ignore_error_points", self.ignorepoints.get_active())
804 self.plotwin.destroy()
805 return True
806 else:
807 self.plotwin.destroy()
808 return False

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