# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2003-2007 Donald N. Allingham # Copyright (C) 2007-2008 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$ # Written by Alex Roitman, # largely based on the BaseDoc classes by Don Allingham #------------------------------------------------------------------------- # # Standard Python modules # #------------------------------------------------------------------------- import os from gettext import gettext as _ #------------------------------------------------------------------------ # # Set up logging # #------------------------------------------------------------------------ import logging log = logging.getLogger(".BookReport") #------------------------------------------------------------------------- # # SAX interface # #------------------------------------------------------------------------- try: from xml.sax import make_parser, handler, SAXParseException from xml.sax.saxutils import escape except: from _xmlplus.sax import make_parser, handler, SAXParseException from _xmlplus.sax.saxutils import escape #------------------------------------------------------------------------- # # GTK/Gnome modules # #------------------------------------------------------------------------- import gtk from gtk import glade from gtk import RESPONSE_OK #------------------------------------------------------------------------- # # gramps modules # #------------------------------------------------------------------------- import const import Utils import ListModel import Errors import BaseDoc from QuestionDialog import WarningDialog, ErrorDialog from gen.plug import PluginManager from gen.plug.menu import PersonOption, FilterOption, FamilyOption import ManagedWindow # Import from specific modules in ReportBase from ReportBase import CATEGORY_BOOK, book_categories from ReportBase._BookFormatComboBox import BookFormatComboBox from ReportBase._ReportDialog import ReportDialog from ReportBase._DocReportDialog import DocReportDialog from ReportBase._CommandLineReport import CommandLineReport from ReportBase._ReportOptions import ReportOptions from BasicUtils import name_displayer as _nd #------------------------------------------------------------------------ # # Private Constants # #------------------------------------------------------------------------ _UNSUPPORTED = _("Unsupported") #------------------------------------------------------------------------ # # Private Functions # #------------------------------------------------------------------------ def _initialize_options(options, dbstate): """ Validates all options by making sure that their values are consistent with the database. menu: The Menu class dbase: the database the options will be applied to """ dbase = dbstate.get_database() if not hasattr(options, "menu"): return menu = options.menu for name in menu.get_all_option_names(): option = menu.get_option_by_name(name) if isinstance(option, PersonOption): person = dbstate.get_active_person() option.set_value(person.get_gramps_id()) elif isinstance(option, FamilyOption): person = dbstate.get_active_person() family_list = person.get_family_handle_list() if family_list: family_handle = family_list[0] else: family_handle = dbase.get_family_handles()[0] family = dbase.get_family_from_handle(family_handle) option.set_value(family.get_gramps_id()) def _get_subject(options, dbase): """ Attempts to determine the subject of a set of options. The subject would likely be a person (using a PersonOption) or a filter (using a FilterOption) options: The ReportOptions class dbase: the database for which it corresponds """ if not hasattr(options, "menu"): return _("Not Applicable") menu = options.menu option_names = menu.get_all_option_names() for name in option_names: option = menu.get_option_by_name(name) if isinstance(option, FilterOption): return option.get_filter().get_name() elif isinstance(option, PersonOption): gid = option.get_value() person = dbase.get_person_from_gramps_id(gid) return _nd.display(person) elif isinstance(option, FamilyOption): family = dbase.get_family_from_gramps_id(option.get_value()) family_id = family.get_gramps_id() fhandle = family.get_father_handle() mhandle = family.get_mother_handle() if fhandle: father = dbase.get_person_from_handle(fhandle) father_name = _nd.display(father) else: father_name = _("unknown father") if mhandle: mother = dbase.get_person_from_handle(mhandle) mother_name = _nd.display(mother) else: mother_name = _("unknown mother") name = _("%s and %s (%s)") % (father_name, mother_name, family_id) return name return _("Not Applicable") #------------------------------------------------------------------------ # # Book Item class # #------------------------------------------------------------------------ class BookItem: """ Interface into the book item -- a smallest element of the book. """ def __init__(self, dbase, name): """ Create a new empty BookItem. name: the book item is retreived from the book item registry using name for lookup """ self.dbase = dbase self.style_name = "default" pmgr = PluginManager.get_instance() for item in pmgr.get_book_item_list(): if item[4] == name: self.translated_name = item[0] if item[5]: self.category = _UNSUPPORTED else: self.category = book_categories[item[1]] self.write_item = item[2] self.name = item[4] self.option_class = item[3](self.name, self.dbase) self.option_class.load_previous_values() def get_name(self): """ Return the name of the item. """ return self.name def get_translated_name(self): """ Return the translated name of the item. """ return self.translated_name def get_category(self): """ Return the category of the item. """ return self.category def get_write_item(self): """ Return the report-writing function of the item. """ return self.write_item def set_style_name(self, style_name): """ Set the style name for the item. style_name: name of the style to set. """ self.style_name = style_name def get_style_name(self): """ Return the style name of the item. """ return self.style_name #------------------------------------------------------------------------ # # Book class # #------------------------------------------------------------------------ class Book: """ Interface into the user-defined book -- a collection of book items. """ def __init__(self, obj=None): """ Create a new empty Book. obj: if not None, creates the Book from the values in obj, instead of creating an empty Book. """ self.name = "" self.dbname = "" if obj: self.item_list = obj.item_list else: self.item_list = [] def set_name(self, name): """ Set the name of the book. name: the name to set. """ self.name = name def get_name(self): """ Return the name of the book. """ return self.name def get_dbname(self): """ Return the name of the database file used for the book. """ return self.dbname def set_dbname(self, name): """ Set the name of the database file used for the book. name: a filename to set. """ self.dbname = name def clear(self): """ Clears the contents of the book. """ self.item_list = [] def append_item(self, item): """ Add an item to the book. item: an item to append. """ self.item_list.append(item) def insert_item(self, index, item): """ Inserts an item into the given position in the book. index: a position index. item: an item to append. """ self.item_list.insert(index, item) def pop_item(self, index): """ Pop an item from given position in the book. index: a position index. """ return self.item_list.pop(index) def get_item(self, index): """ Return an item at a given position in the book. index: a position index. """ return self.item_list[index] def set_item(self, index, item): """ Set an item at a given position in the book. index: a position index. item: an item to set. """ self.item_list[index] = item def get_item_list(self): """ Return list of items in the current book. """ return self.item_list #------------------------------------------------------------------------ # # BookList class # #------------------------------------------------------------------------ class BookList: """ Interface into the user-defined list of books. BookList is loaded from a specified XML file if it exists. """ def __init__(self, filename, dbase): """ Create a new BookList from the books that may be defined in the specified file. file: XML file that contains book items definitions """ self.dbase = dbase self.bookmap = {} self.file = os.path.join(const.HOME_DIR, filename) self.parse() def delete_book(self, name): """ Remove a book from the list. Since each book must have a unique name, the name is used to delete the book. name: name of the book to delete """ del self.bookmap[name] def get_book_map(self): """ Return the map of names to books. """ return self.bookmap def get_book(self, name): """ Return the Book associated with the name name: name associated with the desired Book. """ return self.bookmap[name] def get_book_names(self): "Return a list of all the book names in the BookList" return self.bookmap.keys() def set_book(self, name, book): """ Add or replaces a Book in the BookList. name: name assocated with the Book to add or replace. book: definition of the Book """ self.bookmap[name] = book def save(self): """ Saves the current BookList to the associated file. """ f = open(self.file, "w") f.write("\n") f.write('\n') for name in self.bookmap.keys(): book = self.get_book(name) dbname = book.get_dbname() f.write('\n' % (name, dbname) ) for item in book.get_item_list(): f.write(' \n' % (item.get_name(),item.get_translated_name() ) ) options = item.option_class.handler.options_dict for option_name in options.keys(): option_value = options[option_name] if isinstance(option_value, (list, tuple)): f.write(' \n') else: option_type = Utils.type_name(option_value) value = escape(unicode(option_value)) value = value.replace('"', '"') f.write('