diff --git a/system/selections.py b/system/selections.py index 0e53deb..ec55d83 100644 --- a/system/selections.py +++ b/system/selections.py @@ -70,7 +70,8 @@ class DimListController: 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) + + seltree.connect('drag-data-received', self._drag_data_received) ## Set up identifier list idlist.set_model(self.idstore) @@ -89,10 +90,19 @@ class DimListController: 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.""" - print "setting project" + self.project = project self.dim_names = project.dim_names self.update_dims() project.add_selection_observer(self) @@ -120,11 +130,6 @@ class DimListController: 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: @@ -136,12 +141,16 @@ class DimListController: def selection_changed(self, selection): """Callback function from Project.""" - print 'selection changed' + + 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.""" - print 'dataset changed' self.update_dims() ## GTK Callbacks. @@ -157,12 +166,13 @@ class DimListController: 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 = obj[self._current_dim] + id_list = list(obj[self._current_dim]) id_list.sort() self.idstore.clear() @@ -170,7 +180,18 @@ class DimListController: self.idstore.append((e,)) def _sel_row_activated(self, widget, path, column): - pass + 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]) def set_dimension(self, dimname): self._current_dim = dimname @@ -182,7 +203,7 @@ class DimListController: 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, + def _drag_data_received(self, widget, drag_context, x, y, selection, info, timestamp): treestore, path = selection.tree_get_row_drag_data() @@ -191,328 +212,4 @@ class DimListController: 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) - gtk.TreeView.__init__(self, self.store) - - 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._identifier_list = None - self._dim_list = {} - - # A mapping of selection names to selection lines. - self._selections = [] - - self.set_headers_visible(True) - self._current_dim = None - self._current_selection = None - - # Set up context menu - self._menu = SimpleMenu() - self._menu.add_simple_item('Select', self._on_set_selection) - - self.connect('popup_menu', self._on_popup_menu) - self.connect('button_press_event', self._on_button_press_event) - - def set_identifier_list(self, identifier_list): - """Dependency injection. Sets the widget that should be used to - display the selected identifiers.""" - self._identifier_list = identifier_list - - 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.update_dims(project.dim_names) - self.add_selection(project.get_selection()) - - def selection_changed(self, selection): - """Callback on selection update""" - self.update_dims(selection.keys()) - self.add_selection(selection) - self._update_current_dim() - - def get_selection_iter(self, dimname, selection): - i = self._dim_list[dimname] - if not i: - return None - - children = self.store.iter_children(i) - if not children: - return None - - while children: - if self.store.get_value(children, 1) == selection: - return self.store.get_value(children, 1) - children = self.store.iter_next(children) - return None - - def dataset_changed(self): - """Callback when new datasets are created""" - self.selection_changed(self.project.get_selection()) - for sel in self.project.selections: - if not sel in self._selections: - self._selections.append(sel) - self.add_selection(sel) - - def update_dims(self, dim_list): - """Update the list of dimensions shown""" - for dim in dim_list: - if not self._dim_list.has_key(dim): - d = self.store.insert_after(None, None, (dim, None)) - self._dim_list[dim] = d - - def add_selection(self, selection): - for dim in selection.dims(): - if not self.get_selection_iter(dim, selection): - d = self._dim_list[dim] - i = self.store.insert_after(d, None, (selection.title, selection)) - - def _update_current_dim(self): - id_list = [] - if self._current_dim and self._current_selection: - id_list = self._current_selection[self._current_dim] - self._identifier_list.set_identifiers(id_list) - - # Callbacks - def _on_row_activated(self, treeview, path, column): - self.project.set_selection(self._current_dim, - self._current_selection[self._current_dim]) - - def _on_cursor_changed(self, treeview): - cursor = self.get_cursor()[0] - i = self.store.get_iter(cursor) - p = self.store.iter_parent(i) - if p == None: - self._current_dim = None - else: - self._current_dim = self.store.get_value(p, 0) - self._current_selection = self.store.get_value(i, 1) - self._update_current_dim() - - def _on_set_selection(self, *rest): - if not self._current_selection: - return - self.project.set_selection(self._current_dim, - self._current_selection[self._current_dim]) - - def _on_button_press_event(self, widget, event): - if event.button == 3: - self._menu.popup(None, None, None, event.button, event.time) - - def _on_popup_menu(self): - pass - -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) - - renderer = gtk.CellRendererText() - dim_column = gtk.TreeViewColumn('Dimension', renderer, text=0) - self.insert_column(dim_column, 0) - self._selection_list = None - - 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() - + widget.emit_stop_by_name('drag-data-received')