Split selections.py into three different controller classes, one for each list. There
is still some work to be done, and bugs to be fixed.
This commit is contained in:
parent
a2195bcb4b
commit
2cc4e86b0a
|
@ -152,9 +152,12 @@ class FluentApp:
|
||||||
gtk.glade.set_custom_handler(self.custom_object_factory)
|
gtk.glade.set_custom_handler(self.custom_object_factory)
|
||||||
self.widget_tree = gtk.glade.XML(GLADEFILENAME, 'appwindow')
|
self.widget_tree = gtk.glade.XML(GLADEFILENAME, 'appwindow')
|
||||||
self.workflow = wf(self)
|
self.workflow = wf(self)
|
||||||
self.dimlistcontroller = selections.DimListController(self['dim_list'],
|
|
||||||
self['selection_tree'],
|
self.idlist_crt = selections.IdListController(self['identifier_list'])
|
||||||
self['identifier_list'])
|
self.sellist_crt = selections.SelectionListController(self['selection_tree'],
|
||||||
|
self.idlist_crt)
|
||||||
|
self.dimlist_crt = selections.DimListController(self['dim_list'],
|
||||||
|
self.sellist_crt)
|
||||||
|
|
||||||
def init_gui(self):
|
def init_gui(self):
|
||||||
self['appwindow'].set_size_request(800, 600)
|
self['appwindow'].set_size_request(800, 600)
|
||||||
|
@ -203,7 +206,7 @@ class FluentApp:
|
||||||
project.project = proj
|
project.project = proj
|
||||||
self.workflow.add_project(proj)
|
self.workflow.add_project(proj)
|
||||||
self.navigator_view.add_project(proj)
|
self.navigator_view.add_project(proj)
|
||||||
self.dimlistcontroller.set_project(proj)
|
self.dimlist_crt.set_project(proj)
|
||||||
|
|
||||||
def set_workflow(self, workflow):
|
def set_workflow(self, workflow):
|
||||||
self.workflow = workflow
|
self.workflow = workflow
|
||||||
|
|
|
@ -21,244 +21,126 @@ class SimpleMenu(gtk.Menu):
|
||||||
item.show()
|
item.show()
|
||||||
|
|
||||||
|
|
||||||
class DimListController:
|
class IdListController:
|
||||||
def __init__(self, dimlist, seltree, idlist):
|
"""Controller class for the identifier list."""
|
||||||
|
|
||||||
self._current_dim = None
|
def __init__(self, idlist):
|
||||||
|
self._idlist = idlist
|
||||||
|
|
||||||
## dimstore is a list of all dimensions in the application
|
# dimname: current_annotation_name
|
||||||
self.dimstore = gtk.ListStore(gobject.TYPE_STRING)
|
self._annotation = {}
|
||||||
|
|
||||||
## Two types of lines, one for CategoryDatasets and one for
|
# current dimension
|
||||||
## Selections. The elements are title, link to dataset or selection
|
self._dimension = None
|
||||||
## and the name of the dimension.
|
|
||||||
self.selstore = gtk.TreeStore(gobject.TYPE_STRING,
|
|
||||||
gobject.TYPE_PYOBJECT,
|
|
||||||
gobject.TYPE_STRING)
|
|
||||||
self.selstore_filter = self.selstore.filter_new()
|
|
||||||
self.selstore_filter.set_visible_func(self.dimension_filter)
|
|
||||||
|
|
||||||
## idstore is a list of currently selected identifiers
|
# id, annotation
|
||||||
## the list is cleared and rebuilt each time a new selection is
|
self._idstore = gtk.ListStore(gobject.TYPE_STRING,
|
||||||
## focused.
|
gobject.TYPE_STRING,)
|
||||||
self.idstore = gtk.ListStore(gobject.TYPE_STRING)
|
|
||||||
|
|
||||||
## The widgets we are controlling
|
|
||||||
self.dimlist = dimlist
|
|
||||||
self.seltree = seltree
|
|
||||||
self.idlist = idlist
|
|
||||||
|
|
||||||
## Set up dimensions list
|
|
||||||
dimlist.set_model(self.dimstore)
|
|
||||||
|
|
||||||
renderer = gtk.CellRendererText()
|
|
||||||
dim_column = gtk.TreeViewColumn('Dimension', renderer, text=0)
|
|
||||||
dimlist.insert_column(dim_column, 0)
|
|
||||||
|
|
||||||
dimlist.connect('row-activated', self._dim_row_activated)
|
|
||||||
dimlist.connect('cursor-changed', self._dim_cursor_changed)
|
|
||||||
|
|
||||||
## Set up selection tree
|
|
||||||
seltree.set_model(self.selstore_filter)
|
|
||||||
|
|
||||||
renderer = gtk.CellRendererText()
|
|
||||||
sel_column = gtk.TreeViewColumn('Selection', renderer, text=0)
|
|
||||||
seltree.insert_column(sel_column, 0)
|
|
||||||
|
|
||||||
seltree.connect('row-activated', self._sel_row_activated)
|
|
||||||
seltree.connect('cursor-changed', self._sel_cursor_changed)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
## Set up identifier list
|
## Set up identifier list
|
||||||
idlist.set_model(self.idstore)
|
idlist.set_model(self._idstore)
|
||||||
|
|
||||||
renderer = gtk.CellRendererText()
|
renderer = gtk.CellRendererText()
|
||||||
dim_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
|
dim_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
|
||||||
idlist.insert_column(dim_column, 0)
|
idlist.insert_column(dim_column, 0)
|
||||||
idlist.connect('button-press-event', self._idlist_button_pressed)
|
idlist.connect('button-press-event', self._button_pressed)
|
||||||
|
|
||||||
## Set up identifier list context menu
|
## Set up identifier list context menu
|
||||||
self._idlist_menu = SimpleMenu()
|
menu = self._menu = SimpleMenu()
|
||||||
self._idlist_menu.add_simple_item('Import...', self._on_idlist_import)
|
menu.add_simple_item('Import...', self._on_import_list)
|
||||||
self._idlist_menu.add_simple_item('Export...', self._on_idlist_export)
|
menu.add_simple_item('Export...', self._on_export_list)
|
||||||
|
|
||||||
i = gtk.MenuItem('Show annotations')
|
item = gtk.MenuItem('Show annotations')
|
||||||
self._idlist_menu.append(i)
|
menu.append(item)
|
||||||
i.show()
|
item.show()
|
||||||
self._idlist_menu_ann = i
|
self._menu_ann = item
|
||||||
|
|
||||||
|
|
||||||
def get_dataset_iter(self, dataset):
|
|
||||||
"""Returns the iterator to the selection tree row containing a
|
|
||||||
given dataset."""
|
|
||||||
i = self.selstore.get_iter_first()
|
|
||||||
while i:
|
|
||||||
if self.selstore.get_value(i, 1) == dataset:
|
|
||||||
return i
|
|
||||||
i = self.selstore.iter_next(i)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_current_selection_iter(self, selection, dimension):
|
|
||||||
i = self.selstore.get_iter_first()
|
|
||||||
while i:
|
|
||||||
if self.selstore.get_value(i, 1) == selection:
|
|
||||||
if self.selstore.get_value(i, 2) == dimension:
|
|
||||||
return i
|
|
||||||
i = self.selstore.iter_next(i)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def set_project(self, project):
|
|
||||||
"""Dependency injection."""
|
|
||||||
self.project = project
|
|
||||||
self.dim_names = project.dim_names
|
|
||||||
self.update_dims()
|
|
||||||
project.add_selection_observer(self)
|
|
||||||
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.get_iter_first()
|
|
||||||
while i:
|
|
||||||
if self.dimstore.get_value(i, 0) == dim:
|
|
||||||
return i
|
|
||||||
i = self.dimstore.iter_next(i)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def dimension_filter(self, store, row):
|
|
||||||
"""Filters out everything but the selected dimension."""
|
|
||||||
row_dim = store.get_value(row, 2)
|
|
||||||
return row_dim == self._current_dim
|
|
||||||
|
|
||||||
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,))
|
|
||||||
|
|
||||||
def add_dataset(self, dataset):
|
|
||||||
di = self.get_dataset_iter(dataset)
|
|
||||||
if not di:
|
|
||||||
values = (dataset.get_name(), dataset, dataset.get_dim_name(0))
|
|
||||||
i = self.selstore.insert_after(None, None, values)
|
|
||||||
for selection in dataset.as_selections():
|
|
||||||
values = (selection.title, selection, dataset.get_dim_name(0))
|
|
||||||
self.selstore.insert_after(i, None, values)
|
|
||||||
|
|
||||||
def selection_changed(self, dim_name, selection):
|
|
||||||
"""Callback function from Project."""
|
|
||||||
|
|
||||||
for dim in selection.dims():
|
|
||||||
if not self.get_current_selection_iter(selection, dim):
|
|
||||||
values = (selection.title, selection, dim)
|
|
||||||
self.selstore.insert_after(None, None, values)
|
|
||||||
|
|
||||||
self.update_dims()
|
|
||||||
|
|
||||||
def dataset_changed(self):
|
|
||||||
"""Callback function from Project."""
|
|
||||||
self.update_dims()
|
|
||||||
|
|
||||||
## GTK Callbacks.
|
|
||||||
def _dim_cursor_changed(self, widget):
|
|
||||||
cursor = self.dimlist.get_cursor()[0]
|
|
||||||
i = self.dimstore.get_iter(cursor)
|
|
||||||
row = self.dimstore.get_value(i, 0)
|
|
||||||
self.set_dimension(row)
|
|
||||||
|
|
||||||
def _dim_row_activated(self, widget, path, column):
|
|
||||||
self.seltree.grab_focus()
|
|
||||||
|
|
||||||
def _sel_cursor_changed(self, widget):
|
|
||||||
"Show the list of identifier strings."
|
|
||||||
p = self.seltree.get_cursor()[0]
|
|
||||||
p = self.selstore_filter.convert_path_to_child_path(p)
|
|
||||||
i = self.selstore.get_iter(p)
|
|
||||||
obj = self.selstore.get_value(i, 1)
|
|
||||||
|
|
||||||
id_list = []
|
|
||||||
if isinstance(obj, dataset.Selection):
|
|
||||||
id_list = list(obj[self._current_dim])
|
|
||||||
id_list.sort()
|
|
||||||
|
|
||||||
self.idstore.clear()
|
|
||||||
for e in id_list:
|
|
||||||
self.idstore.append((e,))
|
|
||||||
|
|
||||||
def _sel_row_activated(self, widget, path, column):
|
|
||||||
path = self.selstore_filter.convert_path_to_child_path(path)
|
|
||||||
i = self.selstore.get_iter(path)
|
|
||||||
obj = self.selstore.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):
|
|
||||||
self.project.set_selection(self._current_dim,
|
|
||||||
obj[self._current_dim])
|
|
||||||
|
|
||||||
|
##
|
||||||
|
## Public interface
|
||||||
|
##
|
||||||
def set_dimension(self, dimname):
|
def set_dimension(self, dimname):
|
||||||
self._current_dim = dimname
|
"""Set dimension"""
|
||||||
self.selstore_filter.refilter()
|
if dimname == self._dimension:
|
||||||
|
return
|
||||||
|
|
||||||
dim = self.get_dimension(self._current_dim)
|
if not self._annotation.has_key(dimname):
|
||||||
path = self.dimstore.get_path(dim)
|
self._annotation[dimname] = None
|
||||||
|
self._dimension = dimname
|
||||||
|
|
||||||
if self.dimlist.get_cursor()[0] != path:
|
def set_annotation(self, annotation):
|
||||||
self.dimlist.set_cursor(self.dimstore.get_path(dim))
|
"""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."""
|
||||||
|
|
||||||
def _drag_data_received(self, widget, drag_context, x, y,
|
if annotation == self._annotation:
|
||||||
selection, info, timestamp):
|
return
|
||||||
|
|
||||||
treestore, path = selection.tree_get_row_drag_data()
|
if self.annotation == None:
|
||||||
i = treestore.get_iter(path)
|
self._idlist.remove_column(self._annotation_colum)
|
||||||
obj = treestore.get_value(i, 2)
|
else:
|
||||||
if isinstance(obj, dataset.CategoryDataset):
|
for x in self._idstore:
|
||||||
self.add_dataset(obj)
|
print "set annotation:", x
|
||||||
self.set_dimension(obj.get_dim_name(0))
|
|
||||||
widget.emit_stop_by_name('drag-data-received')
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
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):
|
def _update_annotations_menu(self):
|
||||||
dim_h = annotations.get_dim_handler(self._current_dim)
|
"""Updates the annotations menu with the available annotations for the
|
||||||
|
current dim."""
|
||||||
|
|
||||||
|
dim_h = annotations.get_dim_handler(self._dimension)
|
||||||
if not dim_h:
|
if not dim_h:
|
||||||
print "No annotations etc"
|
print "No annotations etc"
|
||||||
self._idlist_menu_ann.set_sensitive(False)
|
self._menu_ann.set_sensitive(False)
|
||||||
else:
|
else:
|
||||||
annotations_menu = gtk.Menu()
|
annotations_menu = gtk.Menu()
|
||||||
self._idlist_menu_ann.set_sensitive(True)
|
self._menu_ann.set_sensitive(True)
|
||||||
ann_names = annotations.get_dim_handler(self._current_dim).get_annotation_names()
|
ann_names = annotations.get_dim_handler(self._dimension).get_annotation_names()
|
||||||
for ann in ann_names:
|
for ann in ann_names:
|
||||||
item = gtk.MenuItem(ann)
|
item = gtk.MenuItem(ann)
|
||||||
item.connect('activate', self._on_annotation_activated, ann)
|
item.connect('activate', self._on_annotation_activated, ann)
|
||||||
annotations_menu.append(item)
|
annotations_menu.append(item)
|
||||||
item.show()
|
item.show()
|
||||||
|
|
||||||
self._idlist_menu_ann.set_submenu(annotations_menu)
|
self._menu_ann.set_submenu(annotations_menu)
|
||||||
|
|
||||||
def _idlist_button_pressed(self, widget, event):
|
##
|
||||||
if event.button == 3:
|
## GTK Callbacks
|
||||||
|
##
|
||||||
|
def _popup_menu(self, *rest):
|
||||||
self._update_annotations_menu()
|
self._update_annotations_menu()
|
||||||
self._idlist_menu.popup(None, None, None, event.button, event.time)
|
self._menu.popup(None, None, None, 0, 0)
|
||||||
|
|
||||||
def _popup_idlist_menu(self, *rest):
|
|
||||||
self._update_annotations_menu()
|
|
||||||
self._idlist_menu.popup(None, None, None, 0, 0)
|
|
||||||
|
|
||||||
def _on_annotation_activated(self, menuitem, annotation):
|
def _on_annotation_activated(self, menuitem, annotation):
|
||||||
print "Congratulations. You chouse %s" % annotation
|
self.set_annotation(annotation)
|
||||||
|
|
||||||
def _on_idlist_export(self, menuitem):
|
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):
|
||||||
print "export stuff"
|
print "export stuff"
|
||||||
|
|
||||||
def _on_idlist_import(self, menuitem):
|
def _on_import_list(self, menuitem):
|
||||||
dialog = gtk.FileChooserDialog('Load annotations')
|
dialog = gtk.FileChooserDialog('Load annotations')
|
||||||
dialog.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)
|
dialog.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)
|
||||||
dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||||
|
@ -274,5 +156,238 @@ class DimListController:
|
||||||
print "unknown; ", retval
|
print "unknown; ", retval
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
pass
|
|
||||||
|
class SelectionListController:
|
||||||
|
def __init__(self, seltree, idlist_controller):
|
||||||
|
self._seltree = seltree
|
||||||
|
self._sel_stores = {}
|
||||||
|
self._dimension = None
|
||||||
|
self._idlist_controller = idlist_controller
|
||||||
|
|
||||||
|
renderer = gtk.CellRendererText()
|
||||||
|
sel_column = gtk.TreeViewColumn('Selection', renderer, text=0)
|
||||||
|
seltree.insert_column(sel_column, 0)
|
||||||
|
|
||||||
|
seltree.connect('row-activated', self._on_row_activated)
|
||||||
|
seltree.connect('cursor-changed', self._on_cursor_changed)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Public interface
|
||||||
|
##
|
||||||
|
def set_dimension(self, dim):
|
||||||
|
print "SelTreeController.set_dimension(%s)" % dim
|
||||||
|
|
||||||
|
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."""
|
||||||
|
print "selection_changed"
|
||||||
|
|
||||||
|
for dim in selection.dims():
|
||||||
|
self._ensure_selection_store(dim)
|
||||||
|
store = self._sel_stores[dim]
|
||||||
|
|
||||||
|
if not self._get_current_selection_iter(selection, dim):
|
||||||
|
print " inserting into store"
|
||||||
|
values = (selection.title, selection, dim)
|
||||||
|
store.insert_after(None, None, values)
|
||||||
|
|
||||||
|
def add_dataset(self, dataset):
|
||||||
|
store = self._sel_stores[dataset.get_dim_name(0)]
|
||||||
|
di = self._get_dataset_iter(dataset)
|
||||||
|
if not di:
|
||||||
|
values = (dataset.get_name(), dataset, dataset.get_dim_name(0))
|
||||||
|
|
||||||
|
i = store.insert_after(None, None, values)
|
||||||
|
for selection in dataset.as_selections():
|
||||||
|
values = (selection.title, selection, dataset.get_dim_name(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
|
||||||
|
## and the name of the dimension.
|
||||||
|
store = gtk.TreeStore(gobject.TYPE_STRING,
|
||||||
|
gobject.TYPE_PYOBJECT,
|
||||||
|
gobject.TYPE_STRING)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
##
|
||||||
|
## GTK callbacks
|
||||||
|
##
|
||||||
|
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.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)
|
||||||
|
|
||||||
|
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):
|
||||||
|
self.project.set_selection(self._dimension,
|
||||||
|
obj[self._dimension])
|
||||||
|
|
||||||
|
|
||||||
|
class DimListController:
|
||||||
|
def __init__(self, dimlist, seltree_controller):
|
||||||
|
|
||||||
|
self._current_dim = None
|
||||||
|
self._seltree_controller = seltree_controller
|
||||||
|
|
||||||
|
## dimstore is a list of all dimensions in the application
|
||||||
|
self.dimstore = gtk.ListStore(gobject.TYPE_STRING)
|
||||||
|
|
||||||
|
## The widgets we are controlling
|
||||||
|
self.dimlist = dimlist
|
||||||
|
|
||||||
|
## Set up dimensions list
|
||||||
|
dimlist.set_model(self.dimstore)
|
||||||
|
|
||||||
|
renderer = gtk.CellRendererText()
|
||||||
|
dim_column = gtk.TreeViewColumn('Dimension', renderer, text=0)
|
||||||
|
dimlist.insert_column(dim_column, 0)
|
||||||
|
|
||||||
|
dimlist.connect('row-activated', self._dim_row_activated)
|
||||||
|
dimlist.connect('cursor-changed', self._dim_cursor_changed)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Public interface
|
||||||
|
##
|
||||||
|
def set_project(self, project):
|
||||||
|
"""Dependency injection."""
|
||||||
|
self.project = project
|
||||||
|
self.dim_names = project.dim_names
|
||||||
|
self.update_dims()
|
||||||
|
project.add_selection_observer(self._seltree_controller)
|
||||||
|
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.get_iter_first()
|
||||||
|
while i:
|
||||||
|
if self.dimstore.get_value(i, 0) == dim:
|
||||||
|
return i
|
||||||
|
i = self.dimstore.iter_next(i)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_dimension(self, dimname):
|
||||||
|
self._current_dim = dimname
|
||||||
|
|
||||||
|
dim = self.get_dimension(self._current_dim)
|
||||||
|
path = self.dimstore.get_path(dim)
|
||||||
|
|
||||||
|
if self.dimlist.get_cursor()[0] != path:
|
||||||
|
self.dimlist.set_cursor(self.dimstore.get_path(dim))
|
||||||
|
|
||||||
|
self._seltree_controller.set_dimension(dimname)
|
||||||
|
print "DimListController.set_dimension()"
|
||||||
|
|
||||||
|
def dataset_changed(self):
|
||||||
|
"""Callback function from Project."""
|
||||||
|
self.update_dims()
|
||||||
|
|
||||||
|
##
|
||||||
|
## Private interface
|
||||||
|
##
|
||||||
|
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,))
|
||||||
|
|
||||||
|
def _dimension_filter(self, store, row):
|
||||||
|
"""Filters out everything but the selected dimension."""
|
||||||
|
row_dim = store.get_value(row, 2)
|
||||||
|
return row_dim == self._current_dim
|
||||||
|
|
||||||
|
##
|
||||||
|
## GTK Callbacks.
|
||||||
|
##
|
||||||
|
def _dim_cursor_changed(self, widget):
|
||||||
|
cursor = self.dimlist.get_cursor()[0]
|
||||||
|
i = self.dimstore.get_iter(cursor)
|
||||||
|
row = self.dimstore.get_value(i, 0)
|
||||||
|
self.set_dimension(row)
|
||||||
|
|
||||||
|
def _dim_row_activated(self, widget, path, column):
|
||||||
|
self._seltree_controller.set_dimension(dim)
|
||||||
|
|
||||||
|
|
Reference in New Issue