Cleanup Timeline Report and improve handling of data with no dates.

svn: r18385
This commit is contained in:
Brian Matherly 2011-10-30 05:26:08 +00:00
parent 8d8b66f722
commit 789e59ba50

View File

@ -99,57 +99,57 @@ class TimeLine(Report):
menu = options.menu menu = options.menu
self.filter = menu.get_option_by_name('filter').get_filter() self.filter = menu.get_option_by_name('filter').get_filter()
self.title = _("Timeline Graph for %s") % self.filter.get_name()
sort_func_num = menu.get_option_by_name('sortby').get_value() sort_func_num = menu.get_option_by_name('sortby').get_value()
sort_functions = _get_sort_functions(Sort.Sort(database)) sort_functions = _get_sort_functions(Sort.Sort(database))
self.sort_name = sort_functions[sort_func_num][0] self.sort_name = sort_functions[sort_func_num][0]
self.sort_func = sort_functions[sort_func_num][1] self.sort_func = sort_functions[sort_func_num][1]
self.calendar = 0 self.calendar = config.get('preferences.calendar-format-report')
def write_report(self): def write_report(self):
# Apply the filter
self._user.begin_progress(_('Timeline'),
_('Applying filter...'),
self.database.get_number_of_people())
self.plist = self.filter.apply(self.database,
self.database.iter_person_handles(),
self._user.step_progress)
self._user.end_progress()
# Find the range of dates to include
(low, high) = self.find_year_range() (low, high) = self.find_year_range()
# Generate the actual timeline
self.generate_timeline(low, high)
if low == high: def generate_timeline(self, low, high):
if self.standalone:
self.doc.close()
ErrorDialog(_("Report could not be created"),
_("The range of dates chosen was not valid"))
return
st_size = self.name_size() st_size = self.name_size()
style_sheet = self.doc.get_style_sheet() style_sheet = self.doc.get_style_sheet()
font = style_sheet.get_paragraph_style('TLG-Name').get_font() font = style_sheet.get_paragraph_style('TLG-Name').get_font()
incr = pt2cm(font.get_size()) incr = pt2cm(font.get_size())
pad = incr*.75 pad = incr * 0.75
x1,x2,y1,y2 = (0, 0, 0, 0)
x1,x2,y1,y2 = (0,0,0,0) start = st_size + 0.5
stop = self.doc.get_usable_width() - 0.5
start = st_size+0.5 size = (stop - start)
stop = self.doc.get_usable_width()-0.5
size = (stop-start)
self.header = 2.0 self.header = 2.0
self.doc.start_page() # Sort the people as requested
self._user.begin_progress(_('Timeline'), _('Sorting dates...'), 0)
index = 1
current = 1;
length = len(self.plist)
self._user.begin_progress(_('Timeline'), _('Sorting dates...'), 1)
self.plist.sort(key=self.sort_func) self.plist.sort(key=self.sort_func)
self._user.end_progress() self._user.end_progress()
self.doc.start_page()
self.build_grid(low, high, start, stop)
index = 1
current = 1;
length = len(self.plist)
self._user.begin_progress(_('Timeline'), self._user.begin_progress(_('Timeline'),
_('Calculating timeline...'), len(self.plist)) _('Calculating timeline...'), length)
self.calendar = config.get('preferences.calendar-format-report')
for p_id in self.plist: for p_id in self.plist:
self._user.step_progress()
p = self.database.get_person_from_handle(p_id) p = self.database.get_person_from_handle(p_id)
birth = get_birth_or_fallback(self.database, p) birth = get_birth_or_fallback(self.database, p)
if birth: if birth:
@ -194,7 +194,6 @@ class TimeLine(Report):
if (y2 + incr) >= self.doc.get_usable_height(): if (y2 + incr) >= self.doc.get_usable_height():
if current != length: if current != length:
self.build_grid(low, high,start,stop)
self.doc.end_page() self.doc.end_page()
self.doc.start_page() self.doc.start_page()
self.build_grid(low, high,start,stop) self.build_grid(low, high,start,stop)
@ -203,11 +202,11 @@ class TimeLine(Report):
else: else:
index += 1; index += 1;
current += 1 current += 1
self._user.end_progress() self._user.step_progress()
self.build_grid(low, high,start,stop) self.doc.end_page()
self.doc.end_page() self._user.end_progress()
def build_grid(self,year_low,year_high,start_pos,stop_pos): def build_grid(self, year_low, year_high, start_pos, stop_pos):
""" """
Draws the grid outline for the chart. Sets the document label, Draws the grid outline for the chart. Sets the document label,
draws the vertical lines, and adds the year labels. Arguments draws the vertical lines, and adds the year labels. Arguments
@ -218,75 +217,119 @@ class TimeLine(Report):
start_pos - x position of the lowest leftmost grid line start_pos - x position of the lowest leftmost grid line
stop_pos - x position of the rightmost grid line stop_pos - x position of the rightmost grid line
""" """
width = self.doc.get_usable_width() self.draw_title()
self.draw_columns(start_pos, stop_pos)
if year_high is not None and year_low is not None:
self.draw_year_headings(year_low, year_high, start_pos, stop_pos)
else:
self.draw_no_date_heading()
style_sheet = self.doc.get_style_sheet() def draw_columns(self, start_pos, stop_pos):
title_font = style_sheet.get_paragraph_style('TLG-Title').get_font() """
normal_font = style_sheet.get_paragraph_style('TLG-Name').get_font() Draws the columns out of vertical lines.
label_font = style_sheet.get_paragraph_style('TLG-Label').get_font()
byline = _("Sorted by %s") % self.sort_name start_pos - x position of the lowest leftmost grid line
stop_pos - x position of the rightmost grid line
self.doc.center_text('TLG-title',self.title + "\n" + byline,width/2.0,0) """
label_y = self.header - (pt2cm(normal_font.get_size())*1.2)
top_y = self.header top_y = self.header
bottom_y = self.doc.get_usable_height() bottom_y = self.doc.get_usable_height()
delta = (stop_pos - start_pos)/ 5
for val in range(0,6):
xpos = start_pos + (val * delta)
self.doc.draw_line('TLG-grid', xpos, top_y, xpos, bottom_y)
def draw_title(self):
"""
Draws the title for the page.
"""
width = self.doc.get_usable_width()
byline = _("Sorted by %s") % self.sort_name
title = _("Timeline Graph for %s") % self.filter.get_name()
self.doc.center_text('TLG-title', title + "\n" + byline, width / 2.0, 0)
def draw_year_headings(self, year_low, year_high, start_pos, stop_pos):
"""
Draws the column headings (years) for the page.
"""
style_sheet = self.doc.get_style_sheet()
label_font = style_sheet.get_paragraph_style('TLG-Label').get_font()
label_y = self.header - (pt2cm(label_font.get_size()) * 1.2)
top_y = self.header
bottom_y = self.doc.get_usable_height()
incr = (year_high - year_low)/5 incr = (year_high - year_low)/5
delta = (stop_pos - start_pos)/ 5 delta = (stop_pos - start_pos)/ 5
for val in range(0,6): for val in range(0,6):
year_str = str(year_low + (incr*val))
xpos = start_pos+(val*delta) xpos = start_pos+(val*delta)
year_str = str(year_low + (incr*val))
self.doc.center_text('TLG-label', year_str, xpos, label_y) self.doc.center_text('TLG-label', year_str, xpos, label_y)
self.doc.draw_line('TLG-grid', xpos, top_y, xpos, bottom_y)
def draw_no_date_heading(self):
"""
Draws a single heading that says "No Date Information"
"""
width = self.doc.get_usable_width()
style_sheet = self.doc.get_style_sheet()
label_font = style_sheet.get_paragraph_style('TLG-Label').get_font()
label_y = self.header - (pt2cm(label_font.get_size()) * 1.2)
self.doc.center_text('TLG-label', _("No Date Information"),
width / 2.0, label_y)
def find_year_range(self): def find_year_range(self):
low = 999999 """
high = -999999 Finds the range of years that will be displayed on the chart.
Returns a tuple of low and high years. If no dates are found, the
function returns (None, None).
"""
low = None
high = None
def min_max_year(low, high, year):
if year is not None and year != 0:
if low is not None:
low = min(low, year)
else:
low = year
if high is not None:
high = max(high, year)
else:
high = year
return (low, high)
self.plist = self.filter.apply(self.database, self._user.begin_progress(_('Timeline'),
self.database.iter_person_handles()) _('Finding date range...'),
len(self.plist))
self.calendar = config.get('preferences.calendar-format-report')
for p_id in self.plist: for p_id in self.plist:
p = self.database.get_person_from_handle(p_id) p = self.database.get_person_from_handle(p_id)
birth = get_birth_or_fallback(self.database, p) birth = get_birth_or_fallback(self.database, p)
if birth: if birth:
b = birth.get_date_object().to_calendar(self.calendar).get_year() b = birth.get_date_object().to_calendar(self.calendar).get_year()
else: (low, high) = min_max_year(low, high, b)
b = None
death = get_death_or_fallback(self.database, p) death = get_death_or_fallback(self.database, p)
if death: if death:
d = death.get_date_object().to_calendar(self.calendar).get_year() d = death.get_date_object().to_calendar(self.calendar).get_year()
else: (low, high) = min_max_year(low, high, d)
d = None self._user.step_progress()
if b:
low = min(low,b)
high = max(high,b)
if d:
low = min(low,d)
high = max(high,d)
# round the dates to the nearest decade # round the dates to the nearest decade
low = int((low/10))*10 if low is not None:
high = int(((high+9)/10))*10 low = int((low/10))*10
else:
low = high
if high is not None:
high = int(((high+9)/10))*10
else:
high = low
# Make sure the difference is a multiple of 50 so all year ranges land # Make sure the difference is a multiple of 50 so all year ranges land
# on a decade. # on a decade.
low -= 50 - ((high-low) % 50) if low is not None and high is not None:
low -= 50 - ((high-low) % 50)
if low is None:
low = high
if high is None:
high = low
self._user.end_progress()
return (low, high) return (low, high)
def name_size(self): def name_size(self):