Changed how the selection list works. CategoryDatasets can be dragged down to

the selection list, and will then be converted to Selections.
This commit is contained in:
2006-09-08 18:25:03 +00:00
parent df7f98adec
commit e0ca48d4b3
5 changed files with 480 additions and 64 deletions

View File

@@ -19,7 +19,316 @@ class SimpleMenu(gtk.Menu):
self.append(item)
item.show()
class DimListController:
def __init__(self, dimlist, seltree, idlist):
self._current_dim = None
## dimstore is a list of all dimensions in the application
self.dimstore = gtk.ListStore(gobject.TYPE_STRING)
## 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.
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
## the list is cleared and rebuilt each time a new selection is
## focused.
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('Dimension', 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
idlist.set_model(self.idstore)
renderer = gtk.CellRendererText()
dim_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
idlist.insert_column(dim_column, 0)
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 set_project(self, project):
"""Dependency injection."""
print "setting 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_selection(self, dataset, selection):
di = self.get_dataset_iter(dataset)
values = (selection.title, selection, selection.dims()[0])
self.selstore.insert_after(di, None, values)
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, selection):
"""Callback function from Project."""
print 'selection changed'
self.update_dims()
def dataset_changed(self):
"""Callback function from Project."""
print 'dataset changed'
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]
i = self.selstore.get_iter(p)
obj = self.selstore.get_value(i, 1)
id_list = []
if isinstance(obj, dataset.Selection):
id_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):
pass
def set_dimension(self, dimname):
self._current_dim = dimname
self.selstore_filter.refilter()
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))
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))
class SelectionTree(gtk.TreeView):
"""Shows a list of CategoryDatasets for the selected dimension."""
def __init__(self):
self.store = gtk.TreeStore(gobject.TYPE_STRING,
gobject.TYPE_PYOBJECT,
gobject.TYPE_STRING)
# Set up filter that shows only the selected dimension
self.filter = self.store.filter_new()
gtk.TreeView.__init__(self, self.filter)
self.filter.set_visible_func(self.dimension_filter)
renderer = gtk.CellRendererText()
sel_column = gtk.TreeViewColumn('Selection', renderer, text=0)
self.insert_column(sel_column, 0)
self.connect('row-activated', self._on_row_activated)
self.connect('cursor-changed', self._on_cursor_changed)
self.drag_dest_set(gtk.DEST_DEFAULT_ALL,
[("GTK_TREE_MODEL_ROW", gtk.TARGET_SAME_APP, 7)],
gtk.gdk.ACTION_LINK)
self.connect('drag-data-received', self.drag_data_received)
self._identifier_list = None
self.set_headers_visible(True)
self._dimension = None
def set_identifier_list(self, widget):
self._identifier_list = widget
def set_project(self, project):
"""Dependency injection. Set the current project."""
self.project = project
project.add_selection_observer(self)
project.add_dataset_observer(self)
self.add_selection(None, project.get_selection())
def get_dataset_iter(self, dataset):
i = self.store.get_iter_first()
while i:
if self.store.get_value(i, 1) == dataset:
return i
i = self.store.iter_next(i)
return None
def add_selection(self, dataset, selection):
if dataset == None:
return
di = self.get_dataset_iter(dataset)
self.store.insert_after(di, None, (selection.title,
selection,
dataset.dims()[0]))
def add_dataset(self, dataset):
di = self.get_dataset_iter(dataset)
if not di:
i = self.store.insert_after(None, None, (dataset.get_name(),
dataset,
dataset.get_dim_name(0)))
for selection in dataset.as_selections():
self.store.insert_after(i, None, (selection.title,
selection,
dataset.get_dim_name(0)))
def dimension_filter(self, store, i):
"""Filters out everything but the selected dimension."""
i_dim = store.get_value(i, 2)
return i_dim == self._dimension
def set_dimension(self, dimension):
self._dimension = dimension
self.filter.refilter()
def dataset_changed(self):
pass
def selection_changed(self, selection):
pass
## GTK callbacks
def _on_row_activated(self, treeview, path, column):
i = self.store.get_iter(path)
obj = self.store.get_value(i, 1)
if isinstance(obj, dataset.Dataset):
self.expand_row(path, True)
def _on_cursor_changed(self, treeview):
p = self.get_cursor()[0]
self.scroll_to_cell(p)
i = self.store.get_iter(p)
obj = self.store.get_value(i, 1)
id_list = []
if isinstance(obj, dataset.Selection):
id_list = obj[self._dimension]
self._identifier_list.set_identifiers(id_list)
def drag_data_received(self, widget, drag_context, x, y,
selection, info, timestamp):
treestore, path = selection.tree_get_row_drag_data()
iter = treestore.get_iter(path)
obj = treestore.get_value(iter,2)
if isinstance(obj, dataset.CategoryDataset):
self.add_dataset(obj)
self.set_dimension(obj.get_dim_name(0))
class IdentifierList(gtk.TreeView):
def __init__(self):
self.store = gtk.ListStore(gobject.TYPE_STRING)
gtk.TreeView.__init__(self, self.store)
self.set_headers_visible(True)
# Set up identifier column to show active identifiers
renderer = gtk.CellRendererText()
ids_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
self.insert_column(ids_column, 0)
def set_identifiers(self, identifiers):
"Show the list of identifier strings."
self.store.clear()
id_list = identifiers
id_list.sort()
for e in id_list:
self.store.append((e,))
class OldSelectionTree(gtk.TreeView):
def __init__(self):
self.store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
@@ -78,8 +387,8 @@ class SelectionTree(gtk.TreeView):
return None
while children:
if self.store.get(children, 1)[0] == selection:
return self.store.get(children, 1)[0]
if self.store.get_value(children, 1) == selection:
return self.store.get_value(children, 1)
children = self.store.iter_next(children)
return None
@@ -139,23 +448,71 @@ class SelectionTree(gtk.TreeView):
def _on_popup_menu(self):
pass
class IdentifierList(gtk.TreeView):
class DimList(gtk.TreeView):
"""A widget that displays the list of dimensions in the program."""
def __init__(self):
self.store = gtk.ListStore(gobject.TYPE_STRING)
gtk.TreeView.__init__(self, self.store)
self.set_headers_visible(True)
# Set up identifier column to show active identifiers
renderer = gtk.CellRendererText()
ids_column = gtk.TreeViewColumn('Identifiers', renderer, text=0)
self.insert_column(ids_column, 0)
dim_column = gtk.TreeViewColumn('Dimension', renderer, text=0)
self.insert_column(dim_column, 0)
self._selection_list = None
def set_identifiers(self, identifiers):
"Show the list of identifier strings."
self.store.clear()
id_list = list(identifiers)
id_list.sort()
for e in id_list:
self.store.append((e,))
self.connect('row-activated', self._on_row_activated)
self.connect('cursor-changed', self._on_cursor_changed)
def set_project(self, project):
"""Dependency injection. The widget list needs the project, but
there is not necessarily a current project when the application
is started."""
self.dim_names = project.dim_names
self.update_dims()
project.add_selection_observer(self)
project.add_dataset_observer(self)
def set_selection_tree(self, selection_tree):
"""Dependency injection. It is not known whether the selection tree
or the dimension list is created first."""
self.selection_tree = selection_tree
def get_dimension(self, dim):
"""Returns the iterator to the dimension with the given name, or
None if not found."""
i = self.store.get_iter_first()
while i:
if self.store.get(i, 0)[0] == dim:
return i
i = self.store.iter_next(i)
return None
def update_dims(self):
"""Update the list of dimensions shown"""
for dim in self.dim_names:
if not self.get_dimension(dim):
self.store.insert_after(None, (dim,))
def selection_changed(self, selection):
"""Callback function from Project."""
self.update_dims()
def dataset_changed(self):
"""Callback function from Project."""
self.update_dims()
## GTK Callbacks.
def _on_cursor_changed(self, widget):
cursor = self.get_cursor()[0]
print cursor
i = self.store.get_iter(cursor)
row = self.store.get_value(i, 0)
self.selection_tree.set_dimension(row)
self.scroll_to_cell(cursor)
def _on_row_activated(self, widget, path, column):
self.selection_tree.grab_focus()