gramps/src/ReportBase/_Bibliography.py
2008-06-16 15:01:46 +00:00

231 lines
7.9 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007 Brian G. Matherly
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Contain and organize bibliographic information.
"""
import string
from gen.lib import SourceRef as SourceRef
class Citation:
"""
Store information about a citation and all of its references.
"""
def __init__(self):
"""
Initialize members.
"""
self.__src_handle = None
self.__ref_list = []
def get_source_handle(self):
"""
Provide the handle to the source that this citation is for.
@return: Source Handle
@rtype: handle
"""
return self.__src_handle
def set_source_handle(self, handle):
"""
Set the handle for the source that this citation is for.
@param handle: Source Handle
@type handle: handle
"""
self.__src_handle = handle
def get_ref_list(self):
"""
List all the references to this citation.
@return: a list of references
@rtype: list of L{Relib.SourceRef} objects
"""
return self.__ref_list
def add_reference(self, source_ref):
"""
Add a reference to this citation. If a similar reference exists, don't
add another one.
@param source_ref: Source Reference
@type source_ref: L{Relib.SourceRef}
@return: The key of the added reference among all the references.
@rtype: char
"""
first_letter = ''
second_letter = ''
letter_count = len(string.lowercase)
ref_count = len(self.__ref_list)
if ref_count > letter_count:
# If there are more than 26 references, we need to use two
# characters to uniquely identify them all.
first_letter = string.lowercase[ ref_count / letter_count ]
second_letter = string.lowercase[ ref_count % letter_count ]
key = first_letter + second_letter
self.__ref_list.append((key, source_ref))
return key
class Bibliography:
"""
Store and organize multiple citations into a bibliography.
"""
MODE_DATE = 2**0
MODE_PAGE = 2**1
MODE_CONF = 2**2
MODE_NOTE = 2**3
MODE_ALL = MODE_DATE | MODE_PAGE | MODE_CONF | MODE_NOTE
def __init__(self, mode=MODE_ALL):
"""
A bibliography will store citations (sources) and references to those
citations (source refs). Duplicate entries will not be added. To change
what is considered duplicate, you can tell the bibliography what source
ref information you are interested in by passing in the mode.
Possible modes include:
MODE_DATE
MODE_PAGE
MODE_CONF
MODE_NOTE
MODE_ALL
If you only care about pages, set "mode=MODE_PAGE".
If you only care about dates and pages, set "mode=MODE_DATE|MODE_PAGE".
If you care about everything, set "mode=MODE_ALL".
"""
self.__citation_list = []
self.mode = mode
def add_reference(self, source_ref):
"""
Add a reference to a source to this bibliography. If the source already
exists, don't add it again. If a similar reference exists, don't
add another one.
@param source_ref: Source Reference
@type source_ref: L{Relib.SourceRef}
@return: A tuple containing the index of the source among all the
sources and the key of the reference among all the references. If
there is no reference information, the second element will be None.
@rtype: (int,char) or (int,None)
"""
source_handle = source_ref.get_reference_handle()
cindex = 0
rkey = ""
citation = None
citation_found = False
for citation in self.__citation_list:
if citation.get_source_handle() == source_handle:
citation_found = True
break
cindex += 1
if not citation_found:
citation = Citation()
citation.set_source_handle(source_handle)
cindex = len(self.__citation_list)
self.__citation_list.append(citation)
if self.__sref_has_info(source_ref):
for key, ref in citation.get_ref_list():
if self.__srefs_are_equal(ref, source_ref):
# if a reference like this already exists, don't add
# another one
return (cindex, key)
rkey = citation.add_reference(source_ref)
return (cindex, rkey)
def get_citation_count(self):
"""
Report the number of citations in this bibliography.
@return: number of citations
@rtype: int
"""
return len(self.__citation_list)
def get_citation_list(self):
"""
Return a list containing all the citations in this bibliography.
@return: citation list
@rtype: list of L{Citation} objects
"""
return self.__citation_list
def __sref_has_info(self, source_ref):
"""
Determine if this source_ref has any useful information based on the
current mode.
"""
if ( self.mode & self.MODE_PAGE ) == self.MODE_PAGE:
if source_ref.get_page() != "":
return True
if ( self.mode & self.MODE_DATE ) == self.MODE_DATE:
date = source_ref.get_date_object()
if date is not None and not date.is_empty():
return True
if ( self.mode & self.MODE_CONF ) == self.MODE_CONF:
confidence = source_ref.get_confidence_level()
if confidence is not None and confidence != SourceRef.CONF_NORMAL:
return True
if ( self.mode & self.MODE_NOTE ) == self.MODE_NOTE:
if len(source_ref.get_note_list()) != 0:
return True
# Can't find anything interesting.
return False
def __srefs_are_equal(self, source_ref1, source_ref2):
"""
Determine if two source references are equal based on the
current mode.
"""
if self.mode == self.MODE_ALL:
return source_ref1.is_equal(source_ref2)
if ( self.mode & self.MODE_PAGE ) == self.MODE_PAGE:
if source_ref1.get_page() != source_ref2.get_page():
return False
if ( self.mode & self.MODE_DATE ) == self.MODE_DATE:
date1 = source_ref1.get_date_object()
date2 = source_ref2.get_date_object()
if date1.is_equal(date2):
return False
if ( self.mode & self.MODE_CONF ) == self.MODE_CONF:
conf1 = source_ref1.get_confidence_level()
conf2 = source_ref2.get_confidence_level()
if conf1 != conf2:
return False
if ( self.mode & self.MODE_NOTE ) == self.MODE_NOTE:
nl1 = source_ref1.get_note_list()
nl2 = source_ref2.get_note_list()
if len(nl1) != len(nl2):
return False
for notehandle in nl1:
if notehandle not in nl2:
return False
# Can't find anything different. They must be equal.
return True