Projects/laydi
Projects
/
laydi
Archived
7
0
Fork 0

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:
Einar Ryeng 2007-02-21 00:00:26 +00:00
parent a2195bcb4b
commit 2cc4e86b0a
2 changed files with 329 additions and 211 deletions

View File

@ -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

View File

@ -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
self._update_annotations_menu() ##
self._idlist_menu.popup(None, None, None, event.button, event.time) def _popup_menu(self, *rest):
def _popup_idlist_menu(self, *rest):
self._update_annotations_menu() self._update_annotations_menu()
self._idlist_menu.popup(None, None, None, 0, 0) self._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)