BREAKING STUFF!
Rename fluents to laydi.
This commit is contained in:
659
laydi/selections.py
Normal file
659
laydi/selections.py
Normal file
@@ -0,0 +1,659 @@
|
||||
import pygtk
|
||||
import gtk
|
||||
import gtk.gdk
|
||||
import gtk.glade
|
||||
import gnome
|
||||
import gnome.ui
|
||||
import gobject
|
||||
import scipy
|
||||
|
||||
import logger, dataset, main
|
||||
import annotations
|
||||
from lib import hypergeom
|
||||
|
||||
|
||||
class SimpleMenu(gtk.Menu):
|
||||
def __init__(self):
|
||||
gtk.Menu.__init__(self)
|
||||
|
||||
def add_simple_item(self, title, function, *args):
|
||||
item = gtk.MenuItem(title)
|
||||
item.connect('activate', function, *args)
|
||||
self.append(item)
|
||||
item.show()
|
||||
|
||||
|
||||
class IdListController:
|
||||
"""Controller class for the identifier list."""
|
||||
|
||||
def __init__(self, idlist):
|
||||
self._idlist = idlist
|
||||
self._idlist.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
||||
self._idlist.set_rubber_banding(True)
|
||||
|
||||
# dimname: current_annotation_name
|
||||
self._annotation = {}
|
||||
|
||||
# current dimension
|
||||
self._dimension = None
|
||||
|
||||
# id, annotation
|
||||
self._idstore = gtk.ListStore(gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING)
|
||||
self._idstore.set_sort_func(0, self._numeric_compare)
|
||||
|
||||
# Annotation tree column
|
||||
self._annotation_column = None
|
||||
|
||||
## Set up identifier list
|
||||
idlist.set_model(self._idstore)
|
||||
|
||||
renderer = gtk.CellRendererText()
|
||||
dim_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
|
||||
dim_column.set_sort_indicator(True)
|
||||
dim_column.set_sort_column_id(0)
|
||||
dim_column.set_sort_order(gtk.SORT_ASCENDING)
|
||||
idlist.insert_column(dim_column, 0)
|
||||
idlist.connect('button-press-event', self._button_pressed)
|
||||
|
||||
## Enable dropping
|
||||
idlist.drag_dest_set(gtk.DEST_DEFAULT_ALL,
|
||||
[("GTK_TREE_MODEL_ROW", gtk.TARGET_SAME_APP, 7)],
|
||||
gtk.gdk.ACTION_LINK)
|
||||
idlist.connect('drag-data-received', self._drag_data_received)
|
||||
|
||||
## Set up identifier list context menu
|
||||
menu = self._menu = SimpleMenu()
|
||||
menu.add_simple_item('Import...', self._on_import_list)
|
||||
menu.add_simple_item('Export...', self._on_export_list)
|
||||
menu.add_simple_item('Add to selection', self._on_make_selection)
|
||||
item = gtk.MenuItem('Show annotations')
|
||||
menu.append(item)
|
||||
item.show()
|
||||
self._menu_ann = item
|
||||
|
||||
##
|
||||
## Public interface
|
||||
##
|
||||
def set_dimension(self, dimname):
|
||||
"""Set dimension"""
|
||||
if dimname == self._dimension:
|
||||
return
|
||||
|
||||
self._dimension = dimname
|
||||
self.set_annotation(self._annotation.get(dimname, None))
|
||||
|
||||
if not self._annotation.has_key(dimname):
|
||||
self._annotation[dimname] = None
|
||||
|
||||
def set_annotation(self, annotation):
|
||||
"""Set the displayed annotation to annotation. If annotation is None,
|
||||
the annotation column is hidden. Otherwise the annotation column is
|
||||
shown and filled with values from the given annotation field."""
|
||||
|
||||
if annotation == None:
|
||||
if self._annotation_column != None:
|
||||
self._idlist.remove_column(self._annotation_column)
|
||||
self._annotation_column = None
|
||||
else:
|
||||
|
||||
idlist = [x[0] for x in self._idstore]
|
||||
annlist = annotations.get_dim_annotations(self._dimension,
|
||||
annotation,
|
||||
idlist)
|
||||
|
||||
for i, x in enumerate(self._idstore):
|
||||
x[1] = annlist[i]
|
||||
|
||||
if self._annotation_column == None:
|
||||
renderer = gtk.CellRendererText()
|
||||
col = gtk.TreeViewColumn(annotation, renderer, text=1)
|
||||
col.set_sort_indicator(True)
|
||||
col.set_sort_column_id(1)
|
||||
col.set_sort_order(gtk.SORT_ASCENDING)
|
||||
self._idlist.append_column(col)
|
||||
self._annotation_column = col
|
||||
self._annotation_column.set_title(annotation)
|
||||
|
||||
self._annotation[self._dimension] = annotation
|
||||
|
||||
def set_selection(self, selection):
|
||||
"""Set the selection to be displayed.
|
||||
The selection is not stored, the values are copied into the TreeStore"""
|
||||
self._idstore.clear()
|
||||
|
||||
# Return if no selection
|
||||
if selection == None:
|
||||
return
|
||||
|
||||
# Otherwise show selection, possibly with annotations.
|
||||
#id_list = list(selection[self._dimension])
|
||||
idlist = list(selection[self._dimension])
|
||||
if self._annotation[self._dimension] != None:
|
||||
annlist = annotations.get_dim_annotations(self._dimension,
|
||||
self._annotation[self._dimension],
|
||||
idlist)
|
||||
for id, ann in zip(idlist, annlist):
|
||||
self._idstore.append((id, ann))
|
||||
else:
|
||||
for e in idlist:
|
||||
self._idstore.append((e, None))
|
||||
|
||||
##
|
||||
## Private interface
|
||||
##
|
||||
def _update_annotations_menu(self):
|
||||
"""Updates the annotations menu with the available annotations for the
|
||||
current dim."""
|
||||
|
||||
dim_h = annotations.get_dim_handler(self._dimension)
|
||||
if not dim_h:
|
||||
print "set_sensitive(False)"
|
||||
self._menu_ann.set_sensitive(False)
|
||||
else:
|
||||
annotations_menu = gtk.Menu()
|
||||
print "set_sensitive(True)"
|
||||
self._menu_ann.set_sensitive(True)
|
||||
dh = annotations.get_dim_handler(self._dimension)
|
||||
ann_names = dh.get_annotation_names()
|
||||
|
||||
for ann in ann_names:
|
||||
item = gtk.MenuItem(ann)
|
||||
item.connect('activate', self._on_annotation_activated, ann)
|
||||
annotations_menu.append(item)
|
||||
item.show()
|
||||
|
||||
self._menu_ann.set_submenu(annotations_menu)
|
||||
|
||||
|
||||
def import_annotation_file(self):
|
||||
"""Pops up a file dialog and ask the user to select the annotation
|
||||
file to be loaded. Only one file can be selected. The file is loaded
|
||||
into a annotations.AnnotationDictHandler object"""
|
||||
|
||||
dialog = gtk.FileChooserDialog('Load annotations')
|
||||
dialog.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)
|
||||
dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN, gtk.RESPONSE_OK)
|
||||
dialog.set_select_multiple(True)
|
||||
retval = dialog.run()
|
||||
if retval in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
|
||||
pass
|
||||
elif retval == gtk.RESPONSE_OK:
|
||||
for filename in dialog.get_filenames():
|
||||
annotations.read_annotations_file(filename)
|
||||
else:
|
||||
print "unknown; ", retval
|
||||
dialog.destroy()
|
||||
|
||||
def export_annotations(self):
|
||||
"""Pops up a file dialog and ask the user to select a file to save
|
||||
the currently displayed annotations to.
|
||||
"""
|
||||
|
||||
dialog = gtk.FileChooserDialog('Load annotations')
|
||||
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_SAVE, gtk.RESPONSE_OK)
|
||||
retval = dialog.run()
|
||||
if retval in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT]:
|
||||
pass
|
||||
elif retval == gtk.RESPONSE_OK:
|
||||
filename = dialog.get_filename()
|
||||
fd = open(filename, 'w')
|
||||
dim = self._dimension
|
||||
print >> fd, "%s\t%s" % (dim, self._annotation[dim])
|
||||
for id, value in self._idstore:
|
||||
print >> fd, "%s\t%s" % (id, value)
|
||||
fd.close()
|
||||
else:
|
||||
print "unknown; ", retval
|
||||
dialog.destroy()
|
||||
|
||||
def set_rank(self, ds):
|
||||
print "Set rank."
|
||||
|
||||
ra = scipy.sum(ds.asarray(), 1)
|
||||
ranks = {}
|
||||
dim = ds.get_dim_name()[0]
|
||||
for key, value in ds[dim].items():
|
||||
ranks[key] = ra[value]
|
||||
|
||||
ann_h = annotations.get_dim_handler(self._dimension)
|
||||
if ann_h is None:
|
||||
ann_h = annotations.DictAnnotationHandler()
|
||||
annotations.set_dim_handler(self._dimension, ann_h)
|
||||
|
||||
ann_h.add_annotations('Rank', ranks)
|
||||
|
||||
##
|
||||
## GTK Callbacks
|
||||
##
|
||||
|
||||
def _numeric_compare(self, treemodel, iter1, iter2):
|
||||
column = treemodel.get_sort_column_id()[0]
|
||||
|
||||
item1 = treemodel.get_value(iter1, column)
|
||||
item2 = treemodel.get_value(iter2, column)
|
||||
|
||||
try:
|
||||
item1 = float(item1)
|
||||
item2 = float(item2)
|
||||
except:
|
||||
logger.log("notice", "Could not convert to float: %s, %s" %(item1, item2))
|
||||
|
||||
return cmp(item1, item2)
|
||||
|
||||
def _popup_menu(self, *rest):
|
||||
self._update_annotations_menu()
|
||||
self._menu.popup(None, None, None, 0, 0)
|
||||
|
||||
def _on_annotation_activated(self, menuitem, annotation):
|
||||
self.set_annotation(annotation)
|
||||
|
||||
def _button_pressed(self, widget, event):
|
||||
if event.button == 3:
|
||||
self._update_annotations_menu()
|
||||
self._menu.popup(None, None, None, event.button, event.time)
|
||||
|
||||
def _on_export_list(self, menuitem):
|
||||
self.export_annotations()
|
||||
|
||||
def _on_import_list(self, menuitem):
|
||||
self.import_annotation_file()
|
||||
|
||||
def _on_make_selection(self, menuitem):
|
||||
selection = self._idlist.get_selection()
|
||||
model, paths = selection.get_selected_rows()
|
||||
if paths==None: return
|
||||
iters = [self._idstore.get_iter(p) for p in paths]
|
||||
ids = [self._idstore.get_value(i, 0) for i in iters]
|
||||
main.project.set_selection(self._dimension, ids)
|
||||
|
||||
def _drag_data_received(self, widget, drag_context, x, y,
|
||||
selection, info, timestamp):
|
||||
treestore, path = selection.tree_get_row_drag_data()
|
||||
i = treestore.get_iter(path)
|
||||
obj = treestore.get_value(i, 2)
|
||||
if isinstance(obj, dataset.Dataset):
|
||||
if self._dimension in obj.get_dim_name():
|
||||
self.set_rank(obj)
|
||||
widget.emit_stop_by_name('drag-data-received')
|
||||
|
||||
|
||||
class SelectionListController:
|
||||
def __init__(self, seltree, idlist_controller):
|
||||
self._seltree = seltree
|
||||
self._sel_stores = {}
|
||||
self._detail_cols = []
|
||||
self._dimension = None
|
||||
self._idlist_controller = idlist_controller
|
||||
self._details_on = False
|
||||
|
||||
# Selection column
|
||||
renderer = gtk.CellRendererText()
|
||||
sel_column = gtk.TreeViewColumn('Selection', renderer, text=0)
|
||||
sel_column.set_resizable(True)
|
||||
sel_column.set_max_width(200)
|
||||
seltree.insert_column(sel_column, 0)
|
||||
|
||||
# Detail columns
|
||||
cols = [('In CS', 3), ('All', 4), ('Rank', 5)]
|
||||
for name, store_col_num in cols:
|
||||
col = gtk.TreeViewColumn(name, renderer, text=store_col_num)
|
||||
col.set_sort_indicator(True)
|
||||
col.set_sort_column_id(store_col_num)
|
||||
col.set_sort_order(gtk.SORT_ASCENDING)
|
||||
|
||||
self._detail_cols.append(col)
|
||||
# Signals
|
||||
seltree.connect('row-activated', self._on_row_activated)
|
||||
seltree.connect('cursor-changed', self._on_cursor_changed)
|
||||
seltree.connect('button-press-event', self._on_button_pressed)
|
||||
seltree.drag_dest_set(gtk.DEST_DEFAULT_ALL,
|
||||
[("GTK_TREE_MODEL_ROW", gtk.TARGET_SAME_APP, 7)],
|
||||
gtk.gdk.ACTION_LINK)
|
||||
|
||||
seltree.connect('drag-data-received', self._drag_data_received)
|
||||
|
||||
# Selections context menu
|
||||
self._seltree_menu = SimpleMenu()
|
||||
self._seltree_menu.add_simple_item('Sort by selection',
|
||||
self._on_seltree_sort)
|
||||
self._seltree_menu.add_simple_item('Show details',
|
||||
self._enable_details, True)
|
||||
self._seltree_menu.add_simple_item('Hide details',
|
||||
self._enable_details, False)
|
||||
|
||||
#
|
||||
# Public interface
|
||||
#
|
||||
def activate(self):
|
||||
self._seltree.set_cursor((0,))
|
||||
|
||||
def set_project(self, project):
|
||||
"""Dependency injection."""
|
||||
main.project.add_selection_observer(self)
|
||||
|
||||
def set_dimlist_controller(self, dimlist_controller):
|
||||
"""Dependency injection of the dimension list controller."""
|
||||
self._dimlist_controller = dimlist_controller
|
||||
|
||||
def set_dimension(self, dim):
|
||||
"""Set the current dimension, changing the model of the treeview
|
||||
to match dim. After this the current dimension of the identifier list
|
||||
is updated."""
|
||||
self._ensure_selection_store(dim)
|
||||
self._seltree.set_model(self._sel_stores[dim])
|
||||
self._idlist_controller.set_dimension(dim)
|
||||
self._dimension = dim
|
||||
|
||||
def selection_changed(self, dimname, selection):
|
||||
"""Callback function from Project."""
|
||||
for dim in selection.dims():
|
||||
self._ensure_selection_store(dim)
|
||||
store = self._sel_stores[dim]
|
||||
|
||||
if not self._get_current_selection_iter(selection, dim):
|
||||
n = len(selection[dim])
|
||||
values = (selection.title, selection, dim, n, n, 0)
|
||||
store.insert_after(None, None, values)
|
||||
else:
|
||||
# update size of current selection
|
||||
for row in store:
|
||||
if row[1]==selection:
|
||||
row[3] = row[4] = len(selection[dim])
|
||||
|
||||
path = self._seltree.get_cursor()
|
||||
if path and self._sel_stores.has_key(self._dimension):
|
||||
it = self._sel_stores[self._dimension].get_iter(path[0])
|
||||
sel = self._sel_stores[self._dimension].get_value(it, 1)
|
||||
self._idlist_controller.set_selection(sel)
|
||||
|
||||
def add_dataset(self, dataset):
|
||||
"""Converts a CategoryDataset to Selection objects and adds it to
|
||||
the selection tree. The name of the dataset will be the parent
|
||||
node in the tree, and the identifers along the first axis will
|
||||
be added as the names of the subselections."""
|
||||
dim_name = dataset.get_dim_name(0)
|
||||
self._ensure_selection_store(dim_name)
|
||||
store = self._sel_stores[dim_name]
|
||||
di = self._get_dataset_iter(dataset)
|
||||
if not di:
|
||||
n_tot = dataset.shape[0]
|
||||
selection = main.project.get_selection().get(dim_name)
|
||||
ds_idents = dataset.get_identifiers(dim_name)
|
||||
n_cs = len(selection.intersection(ds_idents))
|
||||
values = (dataset.get_name(), dataset, dim_name, n_cs, n_tot, 2)
|
||||
|
||||
i = store.insert_after(None, None, values)
|
||||
for selection in dataset.as_selections():
|
||||
n_sel = len(selection[dim_name])
|
||||
values = (selection.title, selection, dim_name, 0, n_sel, 0)
|
||||
store.insert_after(i, None, values)
|
||||
|
||||
#
|
||||
# Private interface
|
||||
#
|
||||
def _add_selection_store(self, dim):
|
||||
"""Add a new gtk.TreeStore for the selections on a dimension."""
|
||||
# Create new store
|
||||
# Two types of lines, one for CategoryDatasets and one for
|
||||
# Selections. The elements are title, link to dataset or selection,
|
||||
# name of dimension, num. members in selection, num. in
|
||||
# intersection with current selection and the rank of selection.
|
||||
store = gtk.TreeStore(gobject.TYPE_STRING,
|
||||
gobject.TYPE_PYOBJECT,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_INT,
|
||||
gobject.TYPE_INT,
|
||||
gobject.TYPE_FLOAT)
|
||||
|
||||
# Set selection store for this dimension
|
||||
self._sel_stores[dim] = store
|
||||
|
||||
def _ensure_selection_store(self, dim):
|
||||
"""Ensure that the object has a gtk.TreeStore for the given dimension"""
|
||||
# Do not overwrite existing stores
|
||||
if self._sel_stores.has_key(dim):
|
||||
return
|
||||
self._add_selection_store(dim)
|
||||
|
||||
def _get_dataset_iter(self, ds):
|
||||
"""Returns the iterator to the selection tree row containing a
|
||||
given dataset."""
|
||||
|
||||
store = self._sel_stores[ds.get_dim_name(0)]
|
||||
|
||||
i = store.get_iter_first()
|
||||
while i:
|
||||
if store.get_value(i, 1) == ds:
|
||||
return i
|
||||
i = store.iter_next(i)
|
||||
return None
|
||||
|
||||
def _get_current_selection_iter(self, selection, dimension):
|
||||
if not self._sel_stores.has_key(dimension):
|
||||
return None
|
||||
|
||||
store = self._sel_stores[dimension]
|
||||
|
||||
i = store.get_iter_first()
|
||||
while i:
|
||||
if store.get_value(i, 1) == selection:
|
||||
if store.get_value(i, 2) == dimension:
|
||||
return i
|
||||
i = store.iter_next(i)
|
||||
return None
|
||||
|
||||
def _sort_selections(self, dataset):
|
||||
"""Ranks selections by intersection with current selection.
|
||||
Ranks determined by the hypergeometric distribution.
|
||||
"""
|
||||
dim_name = dataset.get_dim_name(0)
|
||||
sel_store = self._sel_stores[dim_name]
|
||||
selection_obj = main.project.get_selection()
|
||||
current_selection = selection_obj.get(dim_name)
|
||||
if current_selection==None: return
|
||||
|
||||
pvals = hypergeom.gene_hypergeo_test(current_selection, dataset)
|
||||
|
||||
for row in sel_store:
|
||||
if row[1]==dataset:
|
||||
for child in row.iterchildren():
|
||||
name = child[0]
|
||||
child[3] = pvals[name][0]
|
||||
child[4] = pvals[name][1]
|
||||
child[5] = pvals[name][2]
|
||||
|
||||
sel_store.set_sort_column_id(5, gtk.SORT_ASCENDING)
|
||||
|
||||
#
|
||||
# GTK callbacks
|
||||
#
|
||||
def _enable_details(self, widget, bool):
|
||||
if self._details_on == bool : return
|
||||
self._details_on = bool
|
||||
if bool==True:
|
||||
for col in self._detail_cols:
|
||||
self._seltree.insert_column(col, -1)
|
||||
else:
|
||||
for col in self._detail_cols:
|
||||
self._seltree.remove_column(col)
|
||||
|
||||
def _drag_data_received(self, widget, drag_context, x, y,
|
||||
selection, info, timestamp):
|
||||
|
||||
treestore, path = selection.tree_get_row_drag_data()
|
||||
i = treestore.get_iter(path)
|
||||
obj = treestore.get_value(i, 2)
|
||||
if isinstance(obj, dataset.CategoryDataset):
|
||||
self.add_dataset(obj)
|
||||
self._dimlist_controller.set_dimension(obj.get_dim_name(0))
|
||||
widget.emit_stop_by_name('drag-data-received')
|
||||
|
||||
def _on_cursor_changed(self, widget):
|
||||
"Show the list of identifier strings."
|
||||
store = self._sel_stores[self._dimension]
|
||||
|
||||
p = self._seltree.get_cursor()[0]
|
||||
i = store.get_iter(p)
|
||||
obj = store.get_value(i, 1)
|
||||
|
||||
if isinstance(obj, dataset.Selection):
|
||||
self._idlist_controller.set_selection(obj)
|
||||
else:
|
||||
self._idlist_controller.set_selection(None)
|
||||
|
||||
def _on_row_activated(self, widget, path, column):
|
||||
store = self._sel_stores[self._dimension]
|
||||
i = store.get_iter(path)
|
||||
obj = store.get_value(i, 1)
|
||||
if isinstance(obj, dataset.Dataset):
|
||||
seltree = self._seltree
|
||||
if seltree.row_expanded(path):
|
||||
seltree.collapse_row(path)
|
||||
else:
|
||||
seltree.expand_row(path, True)
|
||||
elif isinstance(obj, dataset.Selection):
|
||||
main.project.set_selection(self._dimension,
|
||||
obj[self._dimension])
|
||||
|
||||
def _on_button_pressed(self, widget, event):
|
||||
"""Button press callbak."""
|
||||
if event.button == 3:
|
||||
self._seltree_menu.popup(None, None, None, event.button, event.time)
|
||||
|
||||
def _on_seltree_sort(self, menuitem):
|
||||
"""Sort selection tree if row is category dataset."""
|
||||
store = self._sel_stores[self._dimension]
|
||||
p = self._seltree.get_cursor()[0]
|
||||
i = store.get_iter(p)
|
||||
obj = store.get_value(i, 1)
|
||||
if isinstance(obj, dataset.CategoryDataset):
|
||||
self._sort_selections(obj)
|
||||
|
||||
|
||||
class DimListController:
|
||||
def __init__(self, dimlist, seltree_controller):
|
||||
|
||||
self._current_dim = None
|
||||
self._seltree_controller = seltree_controller
|
||||
|
||||
self.show_hidden = False
|
||||
|
||||
## dimstore is a list of all dimensions in the application
|
||||
self.dimstore = gtk.ListStore(gobject.TYPE_STRING)
|
||||
|
||||
# filter for hiding dims prefixed with underscore
|
||||
self.dimstore_filter = self.dimstore.filter_new()
|
||||
self.dimstore_filter.set_visible_func(self._dimension_filter)
|
||||
|
||||
## The widgets we are controlling
|
||||
self.dimlist = dimlist
|
||||
|
||||
## Set up dimensions list
|
||||
dimlist.set_model(self.dimstore_filter)
|
||||
|
||||
renderer = gtk.CellRendererText()
|
||||
dim_column = gtk.TreeViewColumn('Dimension', renderer, text=0)
|
||||
dimlist.insert_column(dim_column, 0)
|
||||
|
||||
# Signals
|
||||
dimlist.connect('row-activated', self._dim_row_activated)
|
||||
dimlist.connect('cursor-changed', self._dim_cursor_changed)
|
||||
dimlist.connect('button-press-event', self._dimlist_button_pressed)
|
||||
|
||||
# Set up dimension context menu
|
||||
self._dimlist_menu = SimpleMenu()
|
||||
self._dimlist_menu.add_simple_item('Hide', self._on_dim_hide)
|
||||
self._dimlist_menu.add_simple_item('Show all', self._on_dim_show)
|
||||
|
||||
|
||||
##
|
||||
## Public interface
|
||||
##
|
||||
def set_project(self, project):
|
||||
"""Dependency injection."""
|
||||
# self.project = project
|
||||
self.dim_names = project.dim_names
|
||||
self.update_dims()
|
||||
project.add_dataset_observer(self)
|
||||
|
||||
def get_dimension(self, dim):
|
||||
"""Returns the iterator to the dimension with the given name, or
|
||||
None if not found."""
|
||||
|
||||
i = self.dimstore_filter.get_iter_first()
|
||||
while i:
|
||||
if self.dimstore_filter.get_value(i, 0) == dim:
|
||||
return i
|
||||
i = self.dimstore_filter.iter_next(i)
|
||||
return None
|
||||
|
||||
def set_dimension(self, dimname):
|
||||
"""Sets the current dimension."""
|
||||
self._current_dim = dimname
|
||||
|
||||
dim = self.get_dimension(self._current_dim)
|
||||
path = self.dimstore_filter.get_path(dim)
|
||||
|
||||
if self.dimlist.get_cursor()[0] != path:
|
||||
self.dimlist.set_cursor(self.dimstore_filter.get_path(dim))
|
||||
self._seltree_controller.set_dimension(dimname)
|
||||
|
||||
def dataset_changed(self):
|
||||
"""Callback function from Project."""
|
||||
self.update_dims()
|
||||
|
||||
def update_dims(self):
|
||||
"""Update the list of dimensions shown"""
|
||||
for dim in self.dim_names:
|
||||
if not self.get_dimension(dim):
|
||||
self.dimstore.insert_after(None, (dim,))
|
||||
self.dimstore_filter.refilter()
|
||||
|
||||
#
|
||||
# Private interface
|
||||
#
|
||||
def _dimension_filter(self, store, row):
|
||||
"""Filters out dimensions with underscore prefix."""
|
||||
if self.show_hidden:
|
||||
return True
|
||||
|
||||
visible = False
|
||||
name = store.get_value(row, 0)
|
||||
if name != None:
|
||||
visible = name[0]!="_"
|
||||
return visible
|
||||
|
||||
#
|
||||
# GTK Callbacks.
|
||||
#
|
||||
def _on_dim_hide(self, menuitem):
|
||||
"""Menu item callback function which hides underscore prefixed
|
||||
dimensions."""
|
||||
self.show_hidden = False
|
||||
self.dimstore_filter.refilter()
|
||||
|
||||
def _on_dim_show(self, menuitem):
|
||||
"""Menu item callback function that shows underscore prefixed
|
||||
dimension names."""
|
||||
self.show_hidden = True
|
||||
self.dimstore_filter.refilter()
|
||||
|
||||
def _dim_cursor_changed(self, widget):
|
||||
cursor = self.dimlist.get_cursor()[0]
|
||||
i = self.dimstore_filter.get_iter(cursor)
|
||||
row = self.dimstore_filter.get_value(i, 0)
|
||||
self.set_dimension(row)
|
||||
self._seltree_controller.activate()
|
||||
|
||||
def _dim_row_activated(self, widget, path, column):
|
||||
#self._seltree_controller.set_dimension(dim)
|
||||
pass
|
||||
|
||||
def _dimlist_button_pressed(self, widget, event):
|
||||
if event.button == 3:
|
||||
self._dimlist_menu.popup(None, None, None, event.button, event.time)
|
||||
|
||||
Reference in New Issue
Block a user