Some fixes
svn: r3892
This commit is contained in:
parent
b2628777c3
commit
9d5016a538
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Gramps - a GTK+/GNOME based genealogy program
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
#
|
#
|
||||||
# Copyright (C) 2003-2004 Donald N. Allingham
|
# Copyright (C) 2003-2005 Donald N. Allingham
|
||||||
#
|
#
|
||||||
# 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
|
||||||
@ -31,7 +31,6 @@ Statistics Chart report
|
|||||||
# python modules
|
# python modules
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
import os
|
|
||||||
import time
|
import time
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
|
|
||||||
@ -48,8 +47,8 @@ import gtk
|
|||||||
#
|
#
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
from Utils import pt2cm
|
from Utils import pt2cm
|
||||||
import const # gender and report type names
|
import const # gender and report type names
|
||||||
import RelLib # need Person internals for getting gender / gender name
|
from RelLib import Person # need Person internals for getting gender / gender name
|
||||||
import Utils
|
import Utils
|
||||||
import Report
|
import Report
|
||||||
import BaseDoc
|
import BaseDoc
|
||||||
@ -74,9 +73,9 @@ _lookup_items = {}
|
|||||||
def lookup_value_compare(a, b):
|
def lookup_value_compare(a, b):
|
||||||
"compare given keys according to corresponding _lookup_items values"
|
"compare given keys according to corresponding _lookup_items values"
|
||||||
if _lookup_items[a] < _lookup_items[b]:
|
if _lookup_items[a] < _lookup_items[b]:
|
||||||
return -1
|
return -1
|
||||||
if _lookup_items[a] == _lookup_items[b]:
|
if _lookup_items[a] == _lookup_items[b]:
|
||||||
return 0
|
return 0
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
@ -89,165 +88,183 @@ class Extract:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Methods for extracting statistical data from the database"""
|
"""Methods for extracting statistical data from the database"""
|
||||||
self.extractors = [
|
self.extractors = [
|
||||||
(_("Titles"), self.title),
|
(_("Titles"), self.title),
|
||||||
(_("Forenames"), self.forename),
|
(_("Forenames"), self.forename),
|
||||||
(_("Birth years"), self.birth_year),
|
(_("Birth years"), self.birth_year),
|
||||||
(_("Death years"), self.death_year),
|
(_("Death years"), self.death_year),
|
||||||
(_("Birth months"), self.birth_month),
|
(_("Birth months"), self.birth_month),
|
||||||
(_("Death months"), self.death_month),
|
(_("Death months"), self.death_month),
|
||||||
(_("Estimated ages at death"), self.death_age),
|
(_("Estimated ages at death"), self.death_age),
|
||||||
#(_("TODO: Estimated (first) marriage ages"), self.marriage_age),
|
#(_("TODO: Estimated (first) marriage ages"), self.marriage_age),
|
||||||
#(_("TODO: Estimated ages for bearing the first child"), self.first_child_age),
|
#(_("TODO: Estimated ages for bearing the first child"), self.first_child_age),
|
||||||
#(_("TODO: Estimated Ages for bearing the last child"), self.last_child_age),
|
#(_("TODO: Estimated Ages for bearing the last child"), self.last_child_age),
|
||||||
#(_("TODO: Number of children"), self.child_count),
|
#(_("TODO: Number of children"), self.child_count),
|
||||||
#(_("TODO: Cause of death"), self.death_cause),
|
#(_("TODO: Cause of death"), self.death_cause),
|
||||||
(_("Genders"), self.gender)
|
(_("Genders"), self.gender)
|
||||||
]
|
]
|
||||||
|
|
||||||
def estimate_age(self, person, date):
|
def estimate_age(self, db, person, date):
|
||||||
"""Utility method to estimate person's age at given date:
|
"""Utility method to estimate person's age at given date:
|
||||||
person -- person whose age is to be estimated
|
person -- person whose age is to be estimated
|
||||||
date -- date at which the age should be estimated
|
date -- date at which the age should be estimated
|
||||||
This expects that Person's birth and the date argument are
|
This expects that Person's birth and the date argument are
|
||||||
using the same calendar and that between those two dates
|
using the same calendar and that between those two dates
|
||||||
there haven't been any calendar discontinuations."""
|
there haven't been any calendar discontinuations."""
|
||||||
birth = person.getBirth().getDateObj()
|
birth_handle = person.get_birth_handle()
|
||||||
if not (date.getYearValid() and birth.getYearValid()):
|
if birth_handle:
|
||||||
return _("Missing date(s)")
|
birth = db.get_event_from_handle(birth_handle).get_date_object()
|
||||||
age = date.getYear() - birth.getYear()
|
if not (date.get_year_valid() and birth.get_year_valid()):
|
||||||
if date.getMonthValid() and birth.getMonthValid():
|
return _("Missing date(s)")
|
||||||
if date.getMonth() < birth.getMonth():
|
else:
|
||||||
age -= 1
|
return _("Missing date(s)")
|
||||||
else:
|
|
||||||
if (date.getMonth() == birth.getMonth() and
|
|
||||||
date.getDayValid() and birth.getDayValid() and
|
|
||||||
date.getDay() < birth.getDay()):
|
|
||||||
age -= 1
|
|
||||||
if age >= 0:
|
|
||||||
return str(age)
|
|
||||||
else:
|
|
||||||
return _("Invalid date(s)")
|
|
||||||
|
|
||||||
def title(self, person):
|
age = date.get_year() - birth.get_year()
|
||||||
title = person.getPrimaryName().getTitle()
|
if date.get_month_valid() and birth.get_month_valid():
|
||||||
if title:
|
if date.get_month() < birth.get_month():
|
||||||
return [title]
|
age -= 1
|
||||||
else:
|
elif (date.get_month() == birth.get_month() and
|
||||||
return [_("Person's missing (preferred) title")]
|
date.get_day_valid() and birth.get_day_valid() and
|
||||||
|
date.get_day() < birth.get_day()):
|
||||||
def forename(self, person):
|
age -= 1
|
||||||
# because this returns list, other methods return list too
|
if age >= 0:
|
||||||
firstnames = person.getPrimaryName().getFirstName().strip()
|
return str(age)
|
||||||
if firstnames:
|
else:
|
||||||
return [name.capitalize() for name in firstnames.split()]
|
return _("Invalid date(s)")
|
||||||
else:
|
|
||||||
return [_("Person's missing (preferred) forename")]
|
|
||||||
|
|
||||||
def birth_year(self, person):
|
def title(self, db, person):
|
||||||
year = person.getBirth().getDateObj().getYear()
|
title = person.get_primary_name().get_title()
|
||||||
if year != Date.UNDEF:
|
if title:
|
||||||
return [str(year)]
|
return [title]
|
||||||
else:
|
else:
|
||||||
return [_("Person's missing birth year")]
|
return [_("Person's missing (preferred) title")]
|
||||||
|
|
||||||
|
def forename(self, db, person):
|
||||||
|
# because this returns list, other methods return list too
|
||||||
|
firstnames = person.get_primary_name().get_first_name().strip()
|
||||||
|
if firstnames:
|
||||||
|
return [name.capitalize() for name in firstnames.split()]
|
||||||
|
else:
|
||||||
|
return [_("Person's missing (preferred) forename")]
|
||||||
|
|
||||||
def death_year(self, person):
|
def birth_year(self, db, person):
|
||||||
year = person.getDeath().getDateObj().getYear()
|
birth_handle = person.get_birth_handle()
|
||||||
if year != Date.UNDEF:
|
if birth_handle:
|
||||||
return [str(year)]
|
birth = db.get_event_from_handle(birth_handle).get_date_object()
|
||||||
else:
|
year = birth.get_year()
|
||||||
return [_("Person's missing death year")]
|
if year:
|
||||||
|
return [str(year)]
|
||||||
|
return [_("Person's missing birth year")]
|
||||||
|
|
||||||
|
def death_year(self, db, person):
|
||||||
|
death_handle = person.get_death_handle()
|
||||||
|
if death_handle:
|
||||||
|
death = db.get_event_from_handle(death_handle).get_date_object()
|
||||||
|
year = death.get_year()
|
||||||
|
if year:
|
||||||
|
return [str(year)]
|
||||||
|
return [_("Person's missing death year")]
|
||||||
|
|
||||||
def birth_month(self, person):
|
def birth_month(self, db, person):
|
||||||
month = person.getBirth().getDateObj().start
|
birth_handle = person.get_birth_handle()
|
||||||
if month.getMonthValid():
|
if birth_handle:
|
||||||
return [month.getMonthStr()]
|
birth = db.get_event_from_handle(birth_handle).get_date_object()
|
||||||
else:
|
month = birth.get_month()
|
||||||
return [_("Person's missing birth month")]
|
if month:
|
||||||
|
return ["Month text here"]#month.getMonthStr()]
|
||||||
|
return [_("Person's missing birth month")]
|
||||||
|
|
||||||
def death_month(self, person):
|
def death_month(self, db, person):
|
||||||
month = person.getDeath().getDateObj().start
|
death_handle = person.get_death_handle()
|
||||||
if month.getMonthValid():
|
if death_handle:
|
||||||
return [month.getMonthStr()]
|
death = db.get_event_from_handle(death_handle).get_date_object()
|
||||||
else:
|
month = death.get_month()
|
||||||
return [_("Person's missing death month")]
|
if month:
|
||||||
|
return ["Month text here"]#[month.getMonthStr()]
|
||||||
|
return [_("Person's missing death month")]
|
||||||
|
|
||||||
def death_age(self, person):
|
def death_age(self, db, person):
|
||||||
return [self.estimate_age(person, person.getDeath().getDateObj())]
|
birth_handle = person.get_birth_handle()
|
||||||
|
if birth_handle:
|
||||||
|
birth = db.get_event_from_handle(birth_handle).get_date_object()
|
||||||
|
return [self.estimate_age(person, person.getDeath().getDateObj())]
|
||||||
|
|
||||||
def marriage_age(self, person):
|
def marriage_age(self, db, person):
|
||||||
return "Marriage age stat unimplemented"
|
return "Marriage age stat unimplemented"
|
||||||
|
|
||||||
def first_child_age(self, person):
|
def first_child_age(self, db, person):
|
||||||
return "First child bearing age stat unimplemented"
|
return "First child bearing age stat unimplemented"
|
||||||
|
|
||||||
def last_child_age(self, person):
|
def last_child_age(self, db, person):
|
||||||
return "Last child bearing age stat unimplemented"
|
return "Last child bearing age stat unimplemented"
|
||||||
|
|
||||||
def child_count(self, person):
|
def child_count(self, db, person):
|
||||||
return "Child count stat unimplemented"
|
return "Child count stat unimplemented"
|
||||||
|
|
||||||
def death_cause(self, person):
|
def death_cause(self, db, person):
|
||||||
return "Death cause stat unimplemented"
|
return "Death cause stat unimplemented"
|
||||||
|
|
||||||
def gender(self, person):
|
def gender(self, db, person):
|
||||||
# TODO: why there's no Person.getGenderName?
|
# TODO: why there's no Person.getGenderName?
|
||||||
# It could be used by getDisplayInfo & this...
|
# It could be used by getDisplayInfo & this...
|
||||||
Person = RelLib.Person
|
if person.gender == Person.male:
|
||||||
if person.gender == Person.male:
|
gender = const.male
|
||||||
gender = const.male
|
elif person.gender == Person.female:
|
||||||
elif person.gender == Person.female:
|
gender = const.female
|
||||||
gender = const.female
|
else:
|
||||||
else:
|
gender = const.unknown
|
||||||
gender = const.unknown
|
return [gender]
|
||||||
return [gender]
|
|
||||||
|
|
||||||
def collect_data(self, db, filter_func, extract_func, genders,
|
def collect_data(self, db, filter_func, extract_func, genders,
|
||||||
year_from, year_to, no_years):
|
year_from, year_to, no_years):
|
||||||
"""goes through the database and collects the selected personal
|
"""goes through the database and collects the selected personal
|
||||||
data persons fitting the filter and birth year criteria. The
|
data persons fitting the filter and birth year criteria. The
|
||||||
arguments are:
|
arguments are:
|
||||||
db - the GRAMPS database
|
db - the GRAMPS database
|
||||||
filter_func - filtering function selected by the StatisticsDialog
|
filter_func - filtering function selected by the StatisticsDialog
|
||||||
extract_func - extraction method selected by the StatisticsDialog
|
extract_func - extraction method selected by the StatisticsDialog
|
||||||
genders - which gender(s) to include into statistics
|
genders - which gender(s) to include into statistics
|
||||||
year_from - use only persons who've born this year of after
|
year_from - use only persons who've born this year of after
|
||||||
year_to - use only persons who've born this year or before
|
year_to - use only persons who've born this year or before
|
||||||
no_years - use also people without any birth year
|
no_years - use also people without any birth year
|
||||||
"""
|
"""
|
||||||
Person = RelLib.Person
|
items = {}
|
||||||
items = {}
|
# go through the people and collect data
|
||||||
# go through the people and collect data
|
for person_handle in filter_func.apply(db, db.get_person_handles(sort_handles=False)):
|
||||||
for person in filter_func.apply(db, db.getPersonMap().values()):
|
|
||||||
|
|
||||||
# check whether person has suitable gender
|
person = db.get_person_from_handle(person_handle)
|
||||||
if person.gender != genders and genders != Person.unknown:
|
# check whether person has suitable gender
|
||||||
continue
|
if person.gender != genders and genders != Person.unknown:
|
||||||
|
continue
|
||||||
# check whether birth year is within required range
|
|
||||||
birth = person.getBirth().getDateObj()
|
# check whether birth year is within required range
|
||||||
if birth.getYearValid():
|
birth_handle = person.get_birth_handle()
|
||||||
year = birth.getYear()
|
if birth_handle:
|
||||||
if not (year >= year_from and year <= year_to):
|
birth = db.get_event_from_handle(birth_handle).get_date_object()
|
||||||
continue
|
if birth.get_year_valid():
|
||||||
else:
|
year = birth.get_year()
|
||||||
# if death before range, person's out of range too...
|
if not (year >= year_from and year <= year_to):
|
||||||
death = person.getDeath().getDateObj()
|
continue
|
||||||
if death.getYearValid() and death.getYear() < year_from:
|
else:
|
||||||
continue
|
# if death before range, person's out of range too...
|
||||||
if not no_years:
|
death_handle = person.get_death_handle()
|
||||||
# do not accept people who are not known to be in range
|
if death_handle:
|
||||||
continue
|
death = db.get_event_from_handle(death_handle).get_date_object()
|
||||||
|
if death.get_year_valid() and death.get_year() < year_from:
|
||||||
|
continue
|
||||||
|
if not no_years:
|
||||||
|
# do not accept people who are not known to be in range
|
||||||
|
continue
|
||||||
|
|
||||||
# get the information
|
# get the information
|
||||||
value = extract_func(person)
|
value = extract_func(db,person)
|
||||||
# list of information found
|
# list of information found
|
||||||
for key in value:
|
for key in value:
|
||||||
if key in items.keys():
|
if key in items.keys():
|
||||||
items[key] += 1
|
items[key] += 1
|
||||||
else:
|
else:
|
||||||
items[key] = 1
|
items[key] = 1
|
||||||
return items
|
return items
|
||||||
|
|
||||||
# GLOBAL: ready instance for others to use
|
# GLOBAL: ready instance for others to use
|
||||||
_Extract = Extract()
|
_Extract = Extract()
|
||||||
@ -262,7 +279,7 @@ class StatisticsChart(Report.Report):
|
|||||||
def __init__(self, database, person, options_class):
|
def __init__(self, database, person, options_class):
|
||||||
"""
|
"""
|
||||||
Creates the Statistics object that produces the report.
|
Creates the Statistics object that produces the report.
|
||||||
Uses the Extractor class to extract the data from the database.
|
Uses the Extractor class to extract the data from the database.
|
||||||
|
|
||||||
The arguments are:
|
The arguments are:
|
||||||
|
|
||||||
@ -270,65 +287,66 @@ class StatisticsChart(Report.Report):
|
|||||||
person - currently selected person
|
person - currently selected person
|
||||||
options_class - instance of the Options class for this report
|
options_class - instance of the Options class for this report
|
||||||
|
|
||||||
To see what the options are, check the options help in the options class.
|
To see what the options are, check the options help in the options class.
|
||||||
"""
|
"""
|
||||||
Report.Report.__init__(self,database,person,options_class)
|
Report.Report.__init__(self,database,person,options_class)
|
||||||
|
|
||||||
filter_num = options_class.get_filter_number()
|
filter_num = options_class.get_filter_number()
|
||||||
filters = options_class.get_report_filters(person)
|
filters = options_class.get_report_filters(person)
|
||||||
filters.extend(GenericFilter.CustomFilters.get_filters())
|
filters.extend(GenericFilter.CustomFilters.get_filters())
|
||||||
filterfun = filters[filter_num]
|
filterfun = filters[filter_num]
|
||||||
|
|
||||||
year_from = options_dict['year_from']
|
year_from = options_class.handler.options_dict['year_from']
|
||||||
year_to = options_dict['year_to']
|
year_to = options_class.handler.options_dict['year_to']
|
||||||
gender = options_dict['gender']
|
gender = options_class.handler.options_dict['gender']
|
||||||
|
|
||||||
extract = _Extract.extractors[options_dict['extract']]
|
extract = _Extract.extractors[options_class.handler.options_dict['extract']]
|
||||||
# extract requested items from the database and count them
|
# extract requested items from the database and count them
|
||||||
self.items = extractor.collect_data(self.db, filterfun, extract[1], gender,
|
self.items = _Extract.collect_data(database, filterfun, extract[1],
|
||||||
year_from, year_to, options_dict['no_years'])
|
gender, year_from, year_to,
|
||||||
# generate sorted item lookup index index
|
options_class.handler.options_dict['no_years'])
|
||||||
self.index_items(options_dict['sort'], options_dict['reverse'])
|
# generate sorted item lookup index index
|
||||||
|
self.index_items(options_class.handler.options_dict['sort'],
|
||||||
|
options_class.handler.options_dict['reverse'])
|
||||||
|
|
||||||
# title needs both data extraction method name + gender name
|
# title needs both data extraction method name + gender name
|
||||||
Person = RelLib.Person
|
if gender == Person.male:
|
||||||
if gender == Person.male:
|
genderstr = _("men")
|
||||||
genderstr = _("men")
|
elif gender == Person.female:
|
||||||
elif gender == Person.female:
|
genderstr = _("women")
|
||||||
genderstr = _("women")
|
else:
|
||||||
else:
|
genderstr = None
|
||||||
genderstr = None
|
|
||||||
|
|
||||||
if genderstr:
|
if genderstr:
|
||||||
self.title = "%s (%s): %04d-%04d" % (extract[0], genderstr, year_from, year_to)
|
self.title = "%s (%s): %04d-%04d" % (extract[0], genderstr, year_from, year_to)
|
||||||
else:
|
else:
|
||||||
self.title = "%s: %04d-%04d" % (extract[0], year_from, year_to)
|
self.title = "%s: %04d-%04d" % (extract[0], year_from, year_to)
|
||||||
|
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
|
|
||||||
def index_items(self, sort, reverse):
|
def index_items(self, sort, reverse):
|
||||||
"""creates & stores a sorted index for the items"""
|
"""creates & stores a sorted index for the items"""
|
||||||
global _lookup_items
|
global _lookup_items
|
||||||
|
|
||||||
# sort by item keys
|
# sort by item keys
|
||||||
index = self.items.keys()
|
index = self.items.keys()
|
||||||
index.sort()
|
index.sort()
|
||||||
if reverse:
|
if reverse:
|
||||||
index.reverse()
|
index.reverse()
|
||||||
|
|
||||||
if sort == _SORT_VALUE:
|
if sort == _SORT_VALUE:
|
||||||
# set for the sorting function
|
# set for the sorting function
|
||||||
_lookup_items = self.items
|
_lookup_items = self.items
|
||||||
|
|
||||||
# then sort by value
|
# then sort by value
|
||||||
index.sort(lookup_value_compare)
|
index.sort(lookup_value_compare)
|
||||||
if reverse:
|
if reverse:
|
||||||
index.reverse()
|
index.reverse()
|
||||||
|
|
||||||
self.index = index
|
self.index = index
|
||||||
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
"""
|
"""
|
||||||
Define the graphics styles used by the report. Paragraph definitions
|
Define the graphics styles used by the report. Paragraph definitions
|
||||||
@ -340,7 +358,7 @@ class StatisticsChart(Report.Report):
|
|||||||
SC-title - Contains the SC-Title paragraph style used for
|
SC-title - Contains the SC-Title paragraph style used for
|
||||||
the title of the document
|
the title of the document
|
||||||
"""
|
"""
|
||||||
g = BaseDoc.GraphicsStyle()
|
g = BaseDoc.GraphicsStyle()
|
||||||
g.set_line_width(0.8)
|
g.set_line_width(0.8)
|
||||||
g.set_color((0,0,0))
|
g.set_color((0,0,0))
|
||||||
g.set_fill_color((255,0,0))
|
g.set_fill_color((255,0,0))
|
||||||
@ -361,62 +379,62 @@ class StatisticsChart(Report.Report):
|
|||||||
g.set_width(self.doc.get_usable_width())
|
g.set_width(self.doc.get_usable_width())
|
||||||
self.doc.add_draw_style("SC-title",g)
|
self.doc.add_draw_style("SC-title",g)
|
||||||
|
|
||||||
|
|
||||||
def write_report(self):
|
def write_report(self):
|
||||||
"output the selected statistics..."
|
"output the selected statistics..."
|
||||||
|
|
||||||
font = self.doc.style_list['SC-Text'].get_font()
|
font = self.doc.style_list['SC-Text'].get_font()
|
||||||
|
|
||||||
# set layout variables
|
# set layout variables
|
||||||
width = self.doc.get_usable_width()
|
width = self.doc.get_usable_width()
|
||||||
row_h = pt2cm(font.get_size())
|
row_h = pt2cm(font.get_size())
|
||||||
max_y = self.doc.get_usable_height() - row_h
|
max_y = self.doc.get_usable_height() - row_h
|
||||||
pad = row_h * 0.5
|
pad = row_h * 0.5
|
||||||
|
|
||||||
# calculate maximum key string size
|
# calculate maximum key string size
|
||||||
max_size = 0
|
max_size = 0
|
||||||
max_value = 0
|
max_value = 0
|
||||||
for key in self.index:
|
for key in self.index:
|
||||||
max_size = max(self.doc.string_width(font, key), max_size)
|
max_size = max(self.doc.string_width(font, key), max_size)
|
||||||
max_value = max(self.items[key], max_value)
|
max_value = max(self.items[key], max_value)
|
||||||
# horizontal area for the gfx bars
|
# horizontal area for the gfx bars
|
||||||
start = pt2cm(max_size) + 1.0
|
start = pt2cm(max_size) + 1.0
|
||||||
size = width - 1.5 - start
|
size = width - 1.5 - start
|
||||||
|
|
||||||
# start page
|
# start page
|
||||||
self.doc.start_page()
|
self.doc.start_page()
|
||||||
|
|
||||||
# start output
|
# start output
|
||||||
self.doc.center_text('SC-title', self.title, width/2, 0)
|
self.doc.center_text('SC-title', self.title, width/2, 0)
|
||||||
#print self.title
|
#print self.title
|
||||||
|
|
||||||
yoffset = pt2cm(self.doc.style_list['SC-Title'].get_font().get_size())
|
yoffset = pt2cm(self.doc.style_list['SC-Title'].get_font().get_size())
|
||||||
for key in self.index:
|
for key in self.index:
|
||||||
yoffset += (row_h + pad)
|
yoffset += (row_h + pad)
|
||||||
if yoffset > max_y:
|
if yoffset > max_y:
|
||||||
# for graphical report, page_break() doesn't seem to work
|
# for graphical report, page_break() doesn't seem to work
|
||||||
self.doc.end_page()
|
self.doc.end_page()
|
||||||
self.doc.start_page()
|
self.doc.start_page()
|
||||||
yoffset = 0
|
yoffset = 0
|
||||||
|
|
||||||
# right align the text to the value
|
# right align the text to the value
|
||||||
x = start - pt2cm(self.doc.string_width(font, key)) - 1.0
|
x = start - pt2cm(self.doc.string_width(font, key)) - 1.0
|
||||||
self.doc.draw_text('SC-text', key, x, yoffset)
|
self.doc.draw_text('SC-text', key, x, yoffset)
|
||||||
#print key + ":",
|
#print key + ":",
|
||||||
|
|
||||||
value = self.items[key]
|
value = self.items[key]
|
||||||
stop = start + (size * value / max_value)
|
stop = start + (size * value / max_value)
|
||||||
path = ((start, yoffset),
|
path = ((start, yoffset),
|
||||||
(stop, yoffset),
|
(stop, yoffset),
|
||||||
(stop, yoffset + row_h),
|
(stop, yoffset + row_h),
|
||||||
(start, yoffset + row_h))
|
(start, yoffset + row_h))
|
||||||
self.doc.draw_path('SC-bar', path)
|
self.doc.draw_path('SC-bar', path)
|
||||||
self.doc.draw_text('SC-text', str(value), stop + 0.5, yoffset)
|
self.doc.draw_text('SC-text', str(value), stop + 0.5, yoffset)
|
||||||
#print "%d/%d" % (value, max_value)
|
#print "%d/%d" % (value, max_value)
|
||||||
|
|
||||||
self.doc.end_page()
|
self.doc.end_page()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
@ -429,39 +447,39 @@ class StatisticsChartOptions(ReportOptions.ReportOptions):
|
|||||||
Defines options and provides their handling interface.
|
Defines options and provides their handling interface.
|
||||||
"""
|
"""
|
||||||
_sorts = [
|
_sorts = [
|
||||||
(_SORT_VALUE, _("Item count")),
|
(_SORT_VALUE, _("Item count")),
|
||||||
(_SORT_KEY, _("Item name"))
|
(_SORT_KEY, _("Item name"))
|
||||||
]
|
]
|
||||||
_genders = [
|
_genders = [
|
||||||
(RelLib.Person.unknown, _("Both")),
|
(Person.unknown, _("Both")),
|
||||||
(RelLib.Person.male, _("Men")),
|
(Person.male, _("Men")),
|
||||||
(RelLib.Person.female, _("Women"))
|
(Person.female, _("Women"))
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self,name, person_id=None):
|
def __init__(self,name, person_id=None):
|
||||||
ReportOptions.ReportOptions.__init__(self, name, person_id)
|
ReportOptions.ReportOptions.__init__(self, name, person_id)
|
||||||
|
|
||||||
def set_new_options(self):
|
def set_new_options(self):
|
||||||
# Options specific for this report
|
# Options specific for this report
|
||||||
self.options_dict = {
|
self.options_dict = {
|
||||||
'year_to' : time.localtime()[0],
|
'year_to' : time.localtime()[0],
|
||||||
'year_from' : 1700,
|
'year_from' : 1700,
|
||||||
'no_years' : 0,
|
'no_years' : 0,
|
||||||
'extract' : 0,
|
'extract' : 0,
|
||||||
'gender' : 0,
|
'gender' : 0,
|
||||||
'sort' : _SORT_VALUE,
|
'sort' : _SORT_VALUE,
|
||||||
'reverse' : 0
|
'reverse' : 0
|
||||||
}
|
}
|
||||||
self.options_help = {
|
self.options_help = {
|
||||||
'year_to' : ("=num", _("Birth year until which to include people"),
|
'year_to' : ("=num", _("Birth year until which to include people"),
|
||||||
_("smaller than %d") % self.options_dict['year_to']),
|
_("smaller than %d") % self.options_dict['year_to']),
|
||||||
'year_from' : ("=num", _("Birth year from which to include people"),
|
'year_from' : ("=num", _("Birth year from which to include people"),
|
||||||
_("earlier than 'year_to' value")),
|
_("earlier than 'year_to' value")),
|
||||||
'no_years' : ("=num", _("Include people without birth years"), [_("No"), _("Yes")]),
|
'no_years' : ("=num", _("Include people without birth years"), [_("No"), _("Yes")]),
|
||||||
'gender' : ("=num", _('Genders included'), self._genders),
|
'gender' : ("=num", _('Genders included'), self._genders),
|
||||||
'extract' : ("=num", _('Data to show'), [item[0] for item in _Extract.extractors]),
|
'extract' : ("=num", _('Data to show'), [item[0] for item in _Extract.extractors]),
|
||||||
'sort' : ("=num", _('Sorted by'), self._sorts),
|
'sort' : ("=num", _('Sorted by'), self._sorts),
|
||||||
'reverse' : ("=num", _("Sort in reverse order"), [_("Yes"), _("No")])
|
'reverse' : ("=num", _("Sort in reverse order"), [_("Yes"), _("No")])
|
||||||
}
|
}
|
||||||
|
|
||||||
def enable_options(self):
|
def enable_options(self):
|
||||||
@ -469,122 +487,126 @@ class StatisticsChartOptions(ReportOptions.ReportOptions):
|
|||||||
self.enable_dict = {
|
self.enable_dict = {
|
||||||
'filter' : 0,
|
'filter' : 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def make_default_style(self, default_style):
|
def make_default_style(self, default_style):
|
||||||
"""Make the default output style for the Statistics report."""
|
"""Make the default output style for the Statistics report."""
|
||||||
f = BaseDoc.FontStyle()
|
f = BaseDoc.FontStyle()
|
||||||
f.set_size(10)
|
f.set_size(10)
|
||||||
f.set_type_face(BaseDoc.FONT_SERIF)
|
f.set_type_face(BaseDoc.FONT_SERIF)
|
||||||
p = BaseDoc.ParagraphStyle()
|
p = BaseDoc.ParagraphStyle()
|
||||||
p.set_font(f)
|
p.set_font(f)
|
||||||
p.set_alignment(BaseDoc.PARA_ALIGN_RIGHT)
|
p.set_alignment(BaseDoc.PARA_ALIGN_RIGHT)
|
||||||
p.set_description(_("The style used for the items and values."))
|
p.set_description(_("The style used for the items and values."))
|
||||||
default_style.add_style("SC-Text",p)
|
default_style.add_style("SC-Text",p)
|
||||||
|
|
||||||
f = BaseDoc.FontStyle()
|
f = BaseDoc.FontStyle()
|
||||||
f.set_size(14)
|
f.set_size(14)
|
||||||
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
|
f.set_type_face(BaseDoc.FONT_SANS_SERIF)
|
||||||
p = BaseDoc.ParagraphStyle()
|
p = BaseDoc.ParagraphStyle()
|
||||||
p.set_font(f)
|
p.set_font(f)
|
||||||
p.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
|
p.set_alignment(BaseDoc.PARA_ALIGN_CENTER)
|
||||||
p.set_description(_("The style used for the title of the page."))
|
p.set_description(_("The style used for the title of the page."))
|
||||||
default_style.add_style("SC-Title",p)
|
default_style.add_style("SC-Title",p)
|
||||||
|
|
||||||
def get_report_filters(self, person):
|
def get_report_filters(self, person):
|
||||||
"""Set up the list of possible content filters."""
|
"""Set up the list of possible content filters."""
|
||||||
|
|
||||||
name = person.getPrimaryName().getName()
|
if person:
|
||||||
|
name = person.get_primary_name().get_name()
|
||||||
all = GenericFilter.GenericFilter()
|
handle = person.get_handle()
|
||||||
all.set_name(_("Entire Database"))
|
else:
|
||||||
all.add_rule(GenericFilter.Everyone([]))
|
name = 'PERSON'
|
||||||
|
handle = ''
|
||||||
des = GenericFilter.GenericFilter()
|
|
||||||
des.set_name(_("Descendants of %s") % name)
|
all = GenericFilter.GenericFilter()
|
||||||
des.add_rule(GenericFilter.IsDescendantOf([person.getId(), 1]))
|
all.set_name(_("Entire Database"))
|
||||||
|
all.add_rule(GenericFilter.Everyone([]))
|
||||||
ans = GenericFilter.GenericFilter()
|
|
||||||
ans.set_name(_("Ancestors of %s") % name)
|
des = GenericFilter.GenericFilter()
|
||||||
ans.add_rule(GenericFilter.IsAncestorOf([person.getId(), 1]))
|
des.set_name(_("Descendants of %s") % name)
|
||||||
|
des.add_rule(GenericFilter.IsDescendantOf([handle, 1]))
|
||||||
com = GenericFilter.GenericFilter()
|
|
||||||
com.set_name(_("People with common ancestor with %s") % name)
|
ans = GenericFilter.GenericFilter()
|
||||||
com.add_rule(GenericFilter.HasCommonAncestorWith([person.getId()]))
|
ans.set_name(_("Ancestors of %s") % name)
|
||||||
|
ans.add_rule(GenericFilter.IsAncestorOf([handle, 1]))
|
||||||
return [all, des, ans, com]
|
|
||||||
|
com = GenericFilter.GenericFilter()
|
||||||
|
com.set_name(_("People with common ancestor with %s") % name)
|
||||||
|
com.add_rule(GenericFilter.HasCommonAncestorWith([handle]))
|
||||||
|
|
||||||
|
return [all, des, ans, com]
|
||||||
|
|
||||||
def add_user_options(self, dialog):
|
def add_user_options(self, dialog):
|
||||||
"""
|
"""
|
||||||
Override the base class add_user_options task to add
|
Override the base class add_user_options task to add
|
||||||
report specific options
|
report specific options
|
||||||
"""
|
"""
|
||||||
# what data to extract from database
|
# what data to extract from database
|
||||||
self.extract_menu = gtk.Menu()
|
self.extract_menu = gtk.Menu()
|
||||||
idx = 0
|
idx = 0
|
||||||
for item in _Extract.extractors:
|
for item in _Extract.extractors:
|
||||||
menuitem = gtk.MenuItem(item[0])
|
menuitem = gtk.MenuItem(item[0])
|
||||||
menuitem.set_data('extract', idx)
|
menuitem.set_data('extract', idx)
|
||||||
self.extract_menu.append(menuitem)
|
self.extract_menu.append(menuitem)
|
||||||
idx += 1
|
idx += 1
|
||||||
self.extract_menu.show_all()
|
self.extract_menu.show_all()
|
||||||
|
|
||||||
tip = _("Select which data is collected and which statistics is shown.")
|
tip = _("Select which data is collected and which statistics is shown.")
|
||||||
extract_style = gtk.OptionMenu()
|
extract_style = gtk.OptionMenu()
|
||||||
extract_style.set_menu(self.extract_menu)
|
extract_style.set_menu(self.extract_menu)
|
||||||
dialog.add_option(self.options_help['extract'][1], extract_style, tip)
|
dialog.add_option(self.options_help['extract'][1], extract_style, tip)
|
||||||
|
|
||||||
# how to sort the data
|
# how to sort the data
|
||||||
self.sort_menu = gtk.Menu()
|
self.sort_menu = gtk.Menu()
|
||||||
for item in self._sorts:
|
for item in self._sorts:
|
||||||
menuitem = gtk.MenuItem(item[1])
|
menuitem = gtk.MenuItem(item[1])
|
||||||
menuitem.set_data('sort', item[0])
|
menuitem.set_data('sort', item[0])
|
||||||
self.sort_menu.append(menuitem)
|
self.sort_menu.append(menuitem)
|
||||||
self.sort_menu.show_all()
|
self.sort_menu.show_all()
|
||||||
|
|
||||||
tip = _("Select how the statistical data is sorted.")
|
tip = _("Select how the statistical data is sorted.")
|
||||||
sort_style = gtk.OptionMenu()
|
sort_style = gtk.OptionMenu()
|
||||||
sort_style.set_menu(self.sort_menu)
|
sort_style.set_menu(self.sort_menu)
|
||||||
dialog.add_option(self.options_help['sort'][1], sort_style, tip)
|
dialog.add_option(self.options_help['sort'][1], sort_style, tip)
|
||||||
|
|
||||||
# sorting order
|
# sorting order
|
||||||
tip = _("Check to reverse the sorting order.")
|
tip = _("Check to reverse the sorting order.")
|
||||||
self.reverse = gtk.CheckButton(self.options_help['reverse'][1])
|
self.reverse = gtk.CheckButton(self.options_help['reverse'][1])
|
||||||
self.reverse.set_active(0)
|
self.reverse.set_active(0)
|
||||||
dialog.add_option(None, self.reverse, tip)
|
dialog.add_option(None, self.reverse, tip)
|
||||||
self.reverse.show()
|
self.reverse.show()
|
||||||
|
|
||||||
# year range
|
# year range
|
||||||
self.from_box = gtk.Entry(4)
|
self.from_box = gtk.Entry(4)
|
||||||
self.from_box.set_text(str(self.options_dict['year_from']))
|
self.from_box.set_text(str(self.options_dict['year_from']))
|
||||||
self.to_box = gtk.Entry(4)
|
self.to_box = gtk.Entry(4)
|
||||||
self.to_box.set_text(str(self.options_dict['year_to']))
|
self.to_box.set_text(str(self.options_dict['year_to']))
|
||||||
|
|
||||||
box = gtk.HBox()
|
box = gtk.HBox()
|
||||||
box.add(self.from_box)
|
box.add(self.from_box)
|
||||||
box.add(gtk.Label("-"))
|
box.add(gtk.Label("-"))
|
||||||
box.add(self.to_box)
|
box.add(self.to_box)
|
||||||
tip = _("Select year range within which people need to be born to be selected for statistics.")
|
tip = _("Select year range within which people need to be born to be selected for statistics.")
|
||||||
dialog.add_option(_('People born between'), box, tip)
|
dialog.add_option(_('People born between'), box, tip)
|
||||||
box.show_all()
|
box.show_all()
|
||||||
|
|
||||||
# include people without birth year?
|
# include people without birth year?
|
||||||
tip = _("Check this if you want people who have no birth date or year to be accounted also in the statistics.")
|
tip = _("Check this if you want people who have no birth date or year to be accounted also in the statistics.")
|
||||||
self.no_years = gtk.CheckButton(self.options_help['no_years'][1])
|
self.no_years = gtk.CheckButton(self.options_help['no_years'][1])
|
||||||
self.no_years.set_active(0)
|
self.no_years.set_active(0)
|
||||||
dialog.add_option(None, self.no_years, tip)
|
dialog.add_option(None, self.no_years, tip)
|
||||||
self.no_years.show()
|
self.no_years.show()
|
||||||
|
|
||||||
# gender selection
|
# gender selection
|
||||||
Person = RelLib.Person
|
|
||||||
self.gender_menu = gtk.Menu()
|
self.gender_menu = gtk.Menu()
|
||||||
for item in self._genders:
|
for item in self._genders:
|
||||||
menuitem = gtk.MenuItem(item[1])
|
menuitem = gtk.MenuItem(item[1])
|
||||||
menuitem.set_data('gender', item[0])
|
menuitem.set_data('gender', item[0])
|
||||||
self.gender_menu.append(menuitem)
|
self.gender_menu.append(menuitem)
|
||||||
self.gender_menu.show_all()
|
self.gender_menu.show_all()
|
||||||
|
|
||||||
tip = _("Select which genders are included into statistics.")
|
tip = _("Select which genders are included into statistics.")
|
||||||
genders = gtk.OptionMenu()
|
genders = gtk.OptionMenu()
|
||||||
genders.set_menu(self.gender_menu)
|
genders.set_menu(self.gender_menu)
|
||||||
dialog.add_option(self.options_help['gender'][1], genders, tip)
|
dialog.add_option(self.options_help['gender'][1], genders, tip)
|
||||||
|
|
||||||
@ -592,13 +614,13 @@ class StatisticsChartOptions(ReportOptions.ReportOptions):
|
|||||||
"""
|
"""
|
||||||
Parses the custom options that we have added.
|
Parses the custom options that we have added.
|
||||||
"""
|
"""
|
||||||
self.options_dict['year_to'] = int(self.to_box.get_text())
|
self.options_dict['year_to'] = int(self.to_box.get_text())
|
||||||
self.options_dict['year_from'] = int(self.from_box.get_text())
|
self.options_dict['year_from'] = int(self.from_box.get_text())
|
||||||
self.options_dict['no_years'] = self.no_years.get_active()
|
self.options_dict['no_years'] = int(self.no_years.get_active())
|
||||||
self.options_dict['gender'] = self.gender_menu.get_active().get_data('gender')
|
self.options_dict['gender'] = self.gender_menu.get_active().get_data('gender')
|
||||||
self.options_dict['extract'] = self.extract_menu.get_active().get_data('extract')
|
self.options_dict['extract'] = self.extract_menu.get_active().get_data('extract')
|
||||||
self.options_dict['sort'] = self.sort_menu.get_active().get_data('sort')
|
self.options_dict['sort'] = self.sort_menu.get_active().get_data('sort')
|
||||||
self.options_dict['reverse'] = self.reverse.get_active()
|
self.options_dict['reverse'] = int(self.reverse.get_active())
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user