diff --git a/src/gui/selectors/baseselector.py b/src/gui/selectors/baseselector.py index fbb8046ad..af391c60d 100644 --- a/src/gui/selectors/baseselector.py +++ b/src/gui/selectors/baseselector.py @@ -193,6 +193,8 @@ class BaseSelector(ManagedWindow.ManagedWindow): id_list = self.get_selected_ids() if id_list and id_list[0]: result = self.get_from_handle_func()(id_list[0]) + if result is None and self.get_from_handle_func2: + result = self.get_from_handle_func2()(id_list[0]) self.close() elif val != gtk.RESPONSE_DELETE_EVENT: self.close() @@ -225,6 +227,9 @@ class BaseSelector(ManagedWindow.ManagedWindow): def get_from_handle_func(self): assert False, "Must be defined in the subclass" + def get_from_handle_func2(self): + return None + def get_handle_column(self): # return 3 assert False, "Must be defined in the subclass" diff --git a/src/gui/selectors/selectcitation.py b/src/gui/selectors/selectcitation.py index 49b91fe58..12592d7ce 100644 --- a/src/gui/selectors/selectcitation.py +++ b/src/gui/selectors/selectcitation.py @@ -65,5 +65,8 @@ class SelectCitation(BaseSelector): def get_from_handle_func(self): return self.db.get_citation_from_handle + def get_from_handle_func2(self): + return self.db.get_source_from_handle + def get_handle_column(self): return 11 diff --git a/src/gui/views/treemodels/citationmodel.py b/src/gui/views/treemodels/citationmodel.py index f9bfe9d58..861ac0bbf 100644 --- a/src/gui/views/treemodels/citationmodel.py +++ b/src/gui/views/treemodels/citationmodel.py @@ -65,6 +65,10 @@ COLUMN_CONFIDENCE = 4 COLUMN_SOURCE = 5 COLUMN_CHANGE = 9 +COLUMN2_HANDLE = 0 +COLUMN2_ID = 1 +COLUMN2_TITLE = 2 + INVALID_DATE_FORMAT = config.get('preferences.invalid-date-format') #------------------------------------------------------------------------- @@ -262,11 +266,12 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): self.gen_cursor = None self.map = None self.fmap = None + self.map2 = None + self.fmap2 = None self.smap = None # Can't call FlatBaseModel.destroy(self), because it fails when a treemodel # is passed, so can't just do: # CitationBaseModel.destroy(self) - self.hmap = None self.number_items = None TreeBaseModel.destroy(self) @@ -275,10 +280,22 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): CitationBaseModel """ self.number_items = self.db.get_number_of_citations - # FIXME: What should the number in the next line be? - # FIXME: Only the first element of hmap ever seems to be populated. - # Why is this, and is it correct? - self.hmap = [self.column_header] + [None] * len(self.smap) + self.map2 = db.get_raw_source_data + self.fmap2 = [ + self.column2_src_title, + self.column2_src_id, + None, + None, + None, + None, + None, + None, + None, + None, + None, + self.column2_handle, + None + ] def get_tree_levels(self): """ @@ -294,24 +311,25 @@ class CitationTreeModel(CitationBaseModel, TreeBaseModel): data The object data. """ source_handle = data[COLUMN_SOURCE] - if source_handle: - source = self.db.get_source_from_handle(source_handle) - if source: - source_name = source.get_title() - sort_key = self.sort_func(data) - # add as node: parent, child, sortkey, handle; parent and child are - # nodes in the treebasemodel, and will be used as iters - self.add_node(source_name, handle, sort_key, handle) - else: - log.warn("Citation %s still has a pointer (handle %s) to a deleted source" % - (data[COLUMN_ID], source_handle)) + source = self.db.get_source_from_handle(source_handle) + if source is not None: + source_name = source.get_title() + sort_key = self.sort_func(data) + # add as node: parent, child, sortkey, handle; parent and child are + # nodes in the treebasemodel, and will be used as iters + if self.get_node(source_handle) is None: + self.add_node(None, source_handle, source_name, source_handle, + secondary=True) + self.add_node(source_handle, handle, sort_key, handle) else: - log.warn("Citation %s does not have a source" % unicode(data[COLUMN_PAGE]), - exc_info=True) + log.warn("Citation %s does not have a source" % + unicode(data[COLUMN_PAGE]), exc_info=True) - def column_header(self, node): - """ - Return a column heading. This is called for nodes with no associated - Gramps handle. - """ - return node.name + def column2_handle(self, data): + return unicode(data[COLUMN2_HANDLE]) + + def column2_src_title(self, data): + return unicode(data[COLUMN2_TITLE]) + + def column2_src_id(self, data): + return unicode(data[COLUMN2_ID]) diff --git a/src/gui/views/treemodels/treebasemodel.py b/src/gui/views/treemodels/treebasemodel.py index b2afbc818..c9c4df51d 100644 --- a/src/gui/views/treemodels/treebasemodel.py +++ b/src/gui/views/treemodels/treebasemodel.py @@ -78,10 +78,10 @@ class Node(object): children A list of (sortkey, nodeid) tuples for the children of the node. This list is always kept sorted. """ - __slots__ = ('name', 'sortkey', 'ref', 'handle', 'parent', 'prev', - 'next', 'children')#, '__weakref__') + __slots__ = ('name', 'sortkey', 'ref', 'handle', 'secondary', 'parent', + 'prev', 'next', 'children')#, '__weakref__') - def __init__(self, ref, parent, sortkey, handle): + def __init__(self, ref, parent, sortkey, handle, secondary): self.name = sortkey if sortkey: self.sortkey = map(conv_unicode_tosrtkey_ongtk, sortkey) @@ -89,17 +89,19 @@ class Node(object): self.sortkey = None self.ref = ref self.handle = handle + self.secondary = secondary self.parent = parent self.prev = None self.next = None self.children = [] - def set_handle(self, handle): + def set_handle(self, handle, secondary=False): """ Assign the handle of a Gramps object to this node. """ if not self.handle: self.handle = handle + self.secondary = secondary else: print ('WARNING: Attempt to add handle twice to the node (%s)' % handle) @@ -353,10 +355,12 @@ class TreeBaseModel(gtk.GenericTreeModel): self.gen_cursor = None self.number_items = None # function self.map = None + self.map2 = None self.smap = None self.fmap = None - self.hmap = None + self.smap2 = None + self.fmap2 = None def displayed(self): """ @@ -404,7 +408,7 @@ class TreeBaseModel(gtk.GenericTreeModel): self.handle2node.clear() self.nodemap.clear() #start with creating the new iters - topnode = Node(None, None, None, None) + topnode = Node(None, None, None, None, False) self.nodemap.add_node(topnode) self.tree[None] = topnode @@ -537,7 +541,8 @@ class TreeBaseModel(gtk.GenericTreeModel): status_col.end() status.end() - def add_node(self, parent, child, sortkey, handle, add_parent=True): + def add_node(self, parent, child, sortkey, handle, add_parent=True, + secondary=False): """ Add a node to the map. @@ -560,10 +565,12 @@ class TreeBaseModel(gtk.GenericTreeModel): if child in self.tree: #a node is added that is already present, child_node = self.tree[child] - self._add_dup_node(child_node, parent, child, sortkey, handle) + self._add_dup_node(child_node, parent, child, sortkey, handle, + secondary) else: parent_node = self.tree[parent] - child_node = Node(child, id(parent_node), sortkey, handle) + child_node = Node(child, id(parent_node), sortkey, handle, + secondary) parent_node.add_child(child_node, self.nodemap) self.tree[child] = child_node self.nodemap.add_node(child_node) @@ -580,7 +587,7 @@ class TreeBaseModel(gtk.GenericTreeModel): if handle: self.handle2node[handle] = child_node - def _add_dup_node(self, node, parent, child, sortkey, handle): + def _add_dup_node(self, node, parent, child, sortkey, handle, secondary): """ How to handle adding a node a second time Default: if group nodes can have handles, it is allowed to add it @@ -592,7 +599,7 @@ class TreeBaseModel(gtk.GenericTreeModel): % (str(parent), str(child))) return if handle: - node.set_handle(handle) + node.set_handle(handle, secondary) if not self._in_build: self.__total += 1 self.__displayed += 1 @@ -774,30 +781,34 @@ class TreeBaseModel(gtk.GenericTreeModel): if col == self.color_column(): return None - # Look for header fuction for column and call it - if self.hmap[col] is not None: - return self.hmap[col](node) - - # If no header fuction return an empty string - return u'' + # Return the node name for the first column + if col == 0: + return self.column_header(node) else: # return values for 'data' row, calling a function # according to column_defs table - return self._get_value(node.handle, col) + return self._get_value(node.handle, col, node.secondary) - def _get_value(self, handle, col): + def _get_value(self, handle, col, secondary=False): """ Returns the contents of a given column of a gramps object """ - try: - if handle in self.lru_data: - data = self.lru_data[handle] - else: + if handle in self.lru_data: + data = self.lru_data[handle] + else: + if not secondary: data = self.map(handle) - if not self._in_build: - self.lru_data[handle] = data - return (self.fmap[col](data)) + else: + data = self.map2(handle) + if not self._in_build: + self.lru_data[handle] = data + + try: + if not secondary: + return (self.fmap[col](data)) + else: + return (self.fmap2[col](data)) except: return None