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
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_functions = _get_sort_functions(Sort.Sort(database))
self.sort_name = sort_functions[sort_func_num][0]
self.sort_func = sort_functions[sort_func_num][1]
self.calendar = 0
self.calendar = config.get('preferences.calendar-format-report')
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()
# Generate the actual timeline
self.generate_timeline(low, high)
if low == high:
if self.standalone:
self.doc.close()
ErrorDialog(_("Report could not be created"),
_("The range of dates chosen was not valid"))
return
def generate_timeline(self, low, high):
st_size = self.name_size()
style_sheet = self.doc.get_style_sheet()
font = style_sheet.get_paragraph_style('TLG-Name').get_font()
incr = pt2cm(font.get_size())
pad = incr*.75
x1,x2,y1,y2 = (0,0,0,0)
start = st_size+0.5
stop = self.doc.get_usable_width()-0.5
size = (stop-start)
pad = incr * 0.75
x1,x2,y1,y2 = (0, 0, 0, 0)
start = st_size + 0.5
stop = self.doc.get_usable_width() - 0.5
size = (stop - start)
self.header = 2.0
self.doc.start_page()
index = 1
current = 1;
length = len(self.plist)
self._user.begin_progress(_('Timeline'), _('Sorting dates...'), 1)
# Sort the people as requested
self._user.begin_progress(_('Timeline'), _('Sorting dates...'), 0)
self.plist.sort(key=self.sort_func)
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'),
_('Calculating timeline...'), len(self.plist))
self.calendar = config.get('preferences.calendar-format-report')
_('Calculating timeline...'), length)
for p_id in self.plist:
self._user.step_progress()
p = self.database.get_person_from_handle(p_id)
birth = get_birth_or_fallback(self.database, p)
if birth:
@ -194,7 +194,6 @@ class TimeLine(Report):
if (y2 + incr) >= self.doc.get_usable_height():
if current != length:
self.build_grid(low, high,start,stop)
self.doc.end_page()
self.doc.start_page()
self.build_grid(low, high,start,stop)
@ -203,11 +202,11 @@ class TimeLine(Report):
else:
index += 1;
current += 1
self._user.end_progress()
self.build_grid(low, high,start,stop)
self.doc.end_page()
self._user.step_progress()
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 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
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()
title_font = style_sheet.get_paragraph_style('TLG-Title').get_font()
normal_font = style_sheet.get_paragraph_style('TLG-Name').get_font()
label_font = style_sheet.get_paragraph_style('TLG-Label').get_font()
def draw_columns(self, start_pos, stop_pos):
"""
Draws the columns out of vertical lines.
byline = _("Sorted by %s") % self.sort_name
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)
start_pos - x position of the lowest leftmost grid line
stop_pos - x position of the rightmost grid line
"""
top_y = self.header
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
delta = (stop_pos - start_pos)/ 5
for val in range(0,6):
year_str = str(year_low + (incr*val))
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.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):
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.database.iter_person_handles())
self.calendar = config.get('preferences.calendar-format-report')
self._user.begin_progress(_('Timeline'),
_('Finding date range...'),
len(self.plist))
for p_id in self.plist:
p = self.database.get_person_from_handle(p_id)
birth = get_birth_or_fallback(self.database, p)
if birth:
b = birth.get_date_object().to_calendar(self.calendar).get_year()
else:
b = None
(low, high) = min_max_year(low, high, b)
death = get_death_or_fallback(self.database, p)
if death:
d = death.get_date_object().to_calendar(self.calendar).get_year()
else:
d = None
if b:
low = min(low,b)
high = max(high,b)
if d:
low = min(low,d)
high = max(high,d)
(low, high) = min_max_year(low, high, d)
self._user.step_progress()
# round the dates to the nearest decade
low = int((low/10))*10
high = int(((high+9)/10))*10
if low is not None:
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
# on a decade.
low -= 50 - ((high-low) % 50)
if low is None:
low = high
if high is None:
high = low
if low is not None and high is not None:
low -= 50 - ((high-low) % 50)
self._user.end_progress()
return (low, high)
def name_size(self):