Add a new place report

svn: r11008
This commit is contained in:
Gary Burton 2008-09-01 20:08:39 +00:00
parent c5a8e3457e
commit 3ed982112e
5 changed files with 543 additions and 1 deletions

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2007-2008 Brian G. Matherly # Copyright (C) 2007-2008 Brian G. Matherly
# Copyright (C) 2008 Gary Burton
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -900,6 +901,117 @@ class GuiPersonListOption(gtk.HBox):
self.__model.remove(i) self.__model.remove(i)
self.__update_value() self.__update_value()
#-------------------------------------------------------------------------
#
# GuiPlaceListOption class
#
#-------------------------------------------------------------------------
class GuiPlaceListOption(gtk.HBox):
"""
This class displays a widget that allows multiple places from the
database to be selected.
"""
def __init__(self, option, dbstate, uistate, track, tooltip):
"""
@param option: The option to display.
@type option: MenuOption.PlaceListOption
@return: nothing
"""
gtk.HBox.__init__(self)
self.__option = option
self.__dbstate = dbstate
self.__db = dbstate.get_database()
self.__uistate = uistate
self.__track = track
self.__model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
self.__tree_view = gtk.TreeView(self.__model)
self.__tree_view.set_size_request(150, 150)
col1 = gtk.TreeViewColumn(_('Place' ), gtk.CellRendererText(), text=0)
col2 = gtk.TreeViewColumn(_('ID' ), gtk.CellRendererText(), text=1)
col1.set_resizable(True)
col2.set_resizable(True)
col1.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
col2.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
col1.set_sort_column_id(0)
col2.set_sort_column_id(1)
self.__tree_view.append_column(col1)
self.__tree_view.append_column(col2)
self.__scrolled_window = gtk.ScrolledWindow()
self.__scrolled_window.add(self.__tree_view)
self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
self.__scrolled_window.set_shadow_type(gtk.SHADOW_OUT)
self.pack_start(self.__scrolled_window, expand=True, fill=True)
value = self.__option.get_value()
for gid in value.split():
place = self.__db.get_place_from_gramps_id(gid)
if place:
place_name = place.get_title()
self.__model.append([place_name, gid])
# now setup the '+' and '-' pushbutton for adding/removing places from
# the container
self.__add_place = widgets.SimpleButton(gtk.STOCK_ADD,
self.__add_place_clicked)
self.__del_place = widgets.SimpleButton(gtk.STOCK_REMOVE,
self.__del_place_clicked)
self.__vbbox = gtk.VButtonBox()
self.__vbbox.add(self.__add_place)
self.__vbbox.add(self.__del_place)
self.__vbbox.set_layout(gtk.BUTTONBOX_SPREAD)
self.pack_end(self.__vbbox, expand=False)
tooltip.set_tip(self.__tree_view, self.__option.get_help())
def __update_value(self):
"""
Parse the object and return.
"""
gidlist = ''
i = self.__model.get_iter_first()
while (i):
gid = self.__model.get_value(i, 1)
gidlist = gidlist + gid + ' '
i = self.__model.iter_next(i)
self.__option.set_value(gidlist)
def __add_place_clicked(self, obj): # IGNORE:W0613 - obj is unused
"""
Handle the add place button.
"""
# places we already have must be excluded
# so we don't list them multiple times
skip_list = set()
i = self.__model.get_iter_first()
while (i):
gid = self.__model.get_value(i, 1) # get the GID stored in column #1
place = self.__db.get_place_from_gramps_id(gid)
skip_list.add(place.get_handle())
i = self.__model.iter_next(i)
select_class = selector_factory('Place')
sel = select_class(self.__dbstate, self.__uistate,
self.__track, skip=skip_list)
place = sel.run()
if place:
place_name = place.get_title()
gid = place.get_gramps_id()
self.__model.append([place_name, gid])
self.__update_value()
def __del_place_clicked(self, obj): # IGNORE:W0613 - obj is unused
"""
Handle the delete place button.
"""
(path, column) = self.__tree_view.get_cursor()
if (path):
i = self.__model.get_iter(path)
self.__model.remove(i)
self.__update_value()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# GuiSurnameColourOption class # GuiSurnameColourOption class
@ -1332,6 +1444,10 @@ def make_gui_option(option, tooltips, dbstate, uistate, track):
widget = GuiSurnameColourOption(option, dbstate, widget = GuiSurnameColourOption(option, dbstate,
uistate, track, uistate, track,
tooltips) tooltips)
elif isinstance(option, _MenuOptions.PlaceListOption):
widget = GuiPlaceListOption(option, dbstate,
uistate, track,
tooltips)
else: else:
raise AttributeError("can't make GuiOption: unknown option type: '%s'" % option) raise AttributeError("can't make GuiOption: unknown option type: '%s'" % option)
return widget, label return widget, label

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2007-2008 Brian G. Matherly # Copyright (C) 2007-2008 Brian G. Matherly
# Copyright (C) 2008 Gary Burton
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -518,6 +519,28 @@ class PersonListOption(Option):
""" """
Option.__init__(self, label, "") Option.__init__(self, label, "")
#-------------------------------------------------------------------------
#
# PlaceListOption class
#
#-------------------------------------------------------------------------
class PlaceListOption(Option):
"""
This class describes a widget that allows multiple places from the
database to be selected.
"""
def __init__(self, label):
"""
@param label: A label to be applied to this option.
Example: "Places"
@type label: string
@param value: A set of GIDs as initial values for this option.
Example: "111 222 333 444"
@type value: string
@return: nothing
"""
Option.__init__(self, label, "")
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# SurnameColourOption class # SurnameColourOption class

View File

@ -3,6 +3,7 @@
# #
# Copyright (C) 2001-2006 Donald N. Allingham # Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Brian Matherly # Copyright (C) 2008 Brian Matherly
# Copyright (C) 2008 Gary Burton
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -24,7 +25,7 @@ from _MenuOptions import (NumberOption, BooleanOption, TextOption,
EnumeratedListOption, FilterOption, StringOption, EnumeratedListOption, FilterOption, StringOption,
ColourOption, PersonOption, PersonListOption, ColourOption, PersonOption, PersonListOption,
SurnameColourOption, FamilyOption, DestinationOption, SurnameColourOption, FamilyOption, DestinationOption,
NoteOption, MediaOption, StyleOption) NoteOption, MediaOption, StyleOption, PlaceListOption)
from _GuiOptions import GuiMenuOptions, make_gui_option from _GuiOptions import GuiMenuOptions, make_gui_option
from _Options import Options, OptionListCollection, OptionList, OptionHandler from _Options import Options, OptionListCollection, OptionList, OptionHandler

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2004-2007 Donald N. Allingham # Copyright (C) 2004-2007 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -747,6 +748,7 @@ class ReportOptions(_Options.Options):
FTD- FTM Style Descendant report FTD- FTM Style Descendant report
IDS- Individual Complete Report IDS- Individual Complete Report
IVS- Individual Summary Report IVS- Individual Summary Report
PLC- Place Report
SBT- Simple Boot Title SBT- Simple Boot Title
TLG- Timeline Graph TLG- Timeline Graph
""" """

400
src/plugins/PlaceReport.py Normal file
View File

@ -0,0 +1,400 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Gary Burton
#
# 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$
"""Place Report"""
#------------------------------------------------------------------------
#
# python modules
#
#------------------------------------------------------------------------
from gettext import gettext as _
#------------------------------------------------------------------------
#
# gramps modules
#
#------------------------------------------------------------------------
from PluginUtils import PluginManager, PlaceListOption, FilterOption
from Filters import CustomFilters, GenericFilter
from ReportBase import Report, MenuReportOptions, \
CATEGORY_TEXT, MODE_GUI, MODE_BKI, MODE_CLI
import BaseDoc
import DateHandler
import Sort
from BasicUtils import name_displayer as _nd
class PlaceReport(Report):
"""
Place Report class
"""
def __init__(self, database, options_class):
"""
Create the PlaceReport object produces the Place report.
The arguments are:
database - the GRAMPS database instance
options_class - instance of the Options class for this report
This report needs the following parameters (class variables)
that come in the options class.
places - List of places to report on.
"""
Report.__init__(self, database, options_class)
menu = options_class.menu
places = menu.get_option_by_name('places').get_value()
filter_option = menu.get_option_by_name('filter')
self.filter = filter_option.get_filter()
self.sort = Sort.Sort(database)
if self.filter.get_name() != '':
# Use the selected filter to provide a list of place handles
plist = self.database.get_place_handles(sort_handles=False)
self.place_handles = self.filter.apply(self.database, plist)
else:
# Use the place handles selected without a filter
self.place_handles = self.__get_place_handles(places)
def write_report(self):
"""
The routine the actually creates the report. At this point, the document
is opened and ready for writing.
"""
# Write the title line. Set in INDEX marker so that this section will be
# identified as a major category if this is included in a Book report.
title = _("Place Report")
mark = BaseDoc.IndexMark(title, BaseDoc.INDEX_TYPE_TOC, 1)
self.doc.start_paragraph("PLC-ReportTitle")
self.doc.write_text(title, mark)
self.doc.end_paragraph()
self.__write_all_places()
def __write_all_places(self):
"""
This procedure writes out each of the selected places.
"""
place_nbr = 1
for handle in self.place_handles:
self.__write_place(handle, place_nbr)
self.__write_referenced_events(handle)
self.__write_referenced_persons(handle)
place_nbr += 1
def __write_place(self, handle, place_nbr):
"""
This procedure writes out the details of a single place
"""
place = self.database.get_place_from_handle(handle)
location = place.get_main_location()
place_details = [_("Gramps ID: %s ") % place.get_gramps_id(),
_("Street: %s ") % location.get_street(),
_("Parish: %s ") % location.get_parish(),
_("City: %s ") % location.get_city(),
_("County: %s ") % location.get_county(),
_("State: %s") % location.get_state(),
_("Country: %s ") % location.get_country()]
self.doc.start_paragraph("PLC-PlaceTitle")
self.doc.write_text(("%(nbr)s. %(place)s") %
{'nbr' : place_nbr,
'place' : place.get_title()})
self.doc.end_paragraph()
for item in place_details:
self.doc.start_paragraph("PLC-PlaceDetails")
self.doc.write_text(item)
self.doc.end_paragraph()
def __write_referenced_events(self, handle):
"""
This procedure writes out each of the events related to the place
"""
event_handles = [event_handle for (object_type, event_handle) in \
self.database.find_backlink_handles(handle)]
event_handles.sort(self.sort.by_date)
if event_handles:
self.doc.start_paragraph("PLC-Section")
title = _("Events that happened at this place")
self.doc.write_text(title)
self.doc.end_paragraph()
self.doc.start_table("EventTable", "PLC-EventTable")
column_titles = [_("Date"), _("Type of Event"), _("Description")]
self.doc.start_row()
for title in column_titles:
self.doc.start_cell("PLC-TableColumn")
self.doc.start_paragraph("PLC-ColumnTitle")
self.doc.write_text(title)
self.doc.end_paragraph()
self.doc.end_cell()
self.doc.end_row()
for handle in event_handles:
event = self.database.get_event_from_handle(handle)
if event:
date = DateHandler.get_date(event)
descr = event.get_description()
event_type = str(event.get_type())
event_details = [date, event_type, descr]
self.doc.start_row()
for detail in event_details:
self.doc.start_cell("PLC-Cell")
self.doc.start_paragraph("PLC-Details")
self.doc.write_text("%s " % detail)
self.doc.end_paragraph()
self.doc.end_cell()
self.doc.end_row()
if event_handles:
self.doc.end_table()
def __write_referenced_persons(self, handle):
"""
This procedure writes out each of the people related to the place
"""
event_handles = [event_handle for (object_type, event_handle) in \
self.database.find_backlink_handles(handle)]
person_list = []
for evt_handle in event_handles:
ref_handles = [x \
for x in self.database.find_backlink_handles(evt_handle)]
for (ref_type, ref_handle) in ref_handles:
if ref_type == 'Person':
person_list.append(ref_handle)
else:
family = self.database.get_family_from_handle(ref_handle)
father = family.get_father_handle()
if father:
person_list.append(father)
mother = family.get_mother_handle()
if mother:
person_list.append(mother)
# Weed out the duplicates where a person has multiple events at the
# place
person_list = list(set(person_list))
person_list.sort(self.sort.by_last_name)
if person_list:
self.doc.start_paragraph("PLC-Section")
title = _("People associated with this place")
self.doc.write_text(title)
self.doc.end_paragraph()
for handle in person_list:
person = self.database.get_person_from_handle(handle)
if person:
self.doc.start_paragraph("PLC-Details")
self.doc.write_text("%s (%s)" % (_nd.display(person),
person.get_gramps_id()))
self.doc.end_paragraph()
def __get_place_handles(self, places):
"""
This procedure converts a string of place GIDs to a list of handles
"""
place_handles = []
for place_gid in places.split():
place = self.database.get_place_from_gramps_id(place_gid)
place_handles.append(place.get_handle())
place_handles.sort(self.sort.by_place_title)
return place_handles
#------------------------------------------------------------------------
#
# AncestorOptions
#
#------------------------------------------------------------------------
class PlaceOptions(MenuReportOptions):
"""
Defines options and provides handling interface.
"""
def __init__(self, name, dbase):
MenuReportOptions.__init__(self, name, dbase)
def add_menu_options(self, menu):
"""
Add options to the menu for the place report.
"""
category_name = _("Report Options")
opt = FilterOption(_("Select using filter"), 0)
opt.set_help(_("Select places using a filter"))
filter_list = []
filter_list.append(GenericFilter())
filter_list.extend(CustomFilters.get_filters('Place'))
opt.set_filters(filter_list)
menu.add_option(category_name, "filter", opt)
places = PlaceListOption(_("Select places individually"))
places.set_help(_("List of places to report on"))
menu.add_option(category_name, "places", places)
def make_default_style(self, default_style):
"""
Make the default output style for the Place report.
"""
self.default_style = default_style
self.__report_title_style()
self.__place_title_style()
self.__place_details_style()
self.__column_title_style()
self.__section_style()
self.__event_table_style()
self.__details_style()
self.__cell_style()
self.__table_column_style()
def __report_title_style(self):
"""
Define the style used for the report title
"""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SANS_SERIF, size=16, bold=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_header_level(1)
para.set_top_margin(0.25)
para.set_bottom_margin(0.25)
para.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
para.set_description(_('The style used for the title of the report.'))
self.default_style.add_paragraph_style("PLC-ReportTitle", para)
def __place_title_style(self):
"""
Define the style used for the place title
"""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SERIF, size=12, italic=0, bold=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set(first_indent=-1.5, lmargin=1.5)
para.set_top_margin(0.75)
para.set_bottom_margin(0.25)
para.set_description(_('The style used for place title.'))
self.default_style.add_paragraph_style("PLC-PlaceTitle", para)
def __place_details_style(self):
"""
Define the style used for the place details
"""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SERIF, size=10)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set(first_indent=0.0, lmargin=1.5)
para.set_description(_('The style used for place details.'))
self.default_style.add_paragraph_style("PLC-PlaceDetails", para)
def __column_title_style(self):
"""
Define the style used for the event table column title
"""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SERIF, size=10, bold=1)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set(first_indent=-1.5, lmargin=1.5)
para.set_description(_('The style used for a column title.'))
self.default_style.add_paragraph_style("PLC-ColumnTitle", para)
def __section_style(self):
"""
Define the style used for each section
"""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SERIF, size=10, italic=0, bold=0)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set(first_indent=-1.5, lmargin=1.5)
para.set_top_margin(0.5)
para.set_bottom_margin(0.25)
para.set_description(_('The style used for each section.'))
self.default_style.add_paragraph_style("PLC-Section", para)
def __event_table_style(self):
"""
Define the style used for event table
"""
table = BaseDoc.TableStyle()
table.set_width(80)
table.set_columns(3)
table.set_column_width(0, 20)
table.set_column_width(1, 20)
table.set_column_width(2, 40)
self.default_style.add_table_style("PLC-EventTable", table)
def __details_style(self):
"""
Define the style used for person and event details
"""
font = BaseDoc.FontStyle()
font.set(face=BaseDoc.FONT_SERIF, size=10)
para = BaseDoc.ParagraphStyle()
para.set_font(font)
para.set_description(_('The style used for event and person details.'))
self.default_style.add_paragraph_style("PLC-Details", para)
def __cell_style(self):
"""
Define the style used for cells in the event table
"""
cell = BaseDoc.TableCellStyle()
self.default_style.add_cell_style("PLC-Cell", cell)
def __table_column_style(self):
"""
Define the style used for event table columns
"""
cell = BaseDoc.TableCellStyle()
cell.set_bottom_border(1)
self.default_style.add_cell_style('PLC-TableColumn', cell)
#------------------------------------------------------------------------
#
# Register the plugin
#
#------------------------------------------------------------------------
pmgr = PluginManager.get_instance()
pmgr.register_report(
name = 'place_report',
category = CATEGORY_TEXT,
report_class = PlaceReport,
options_class = PlaceOptions,
modes = MODE_GUI | MODE_BKI | MODE_CLI,
translated_name = _("Place Report"),
status = _("Stable"),
description = _("Produces a textual place report"),
author_name = "Gary Burton",
author_email = "gary.burton@zen.co.uk"
)