Speed ups: cache names---don't re-lookup name; added outer edge to indicate parents; removed simple access

svn: r11714
This commit is contained in:
Doug Blank 2009-01-25 11:19:13 +00:00
parent 2018064fe1
commit d2b481b1a3

View File

@ -58,10 +58,13 @@ if gtk.pygtk_version < (2,3,93):
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from BasicUtils import name_displayer from BasicUtils import name_displayer
from Simple import SimpleAccess
from gettext import gettext as _ from gettext import gettext as _
from DataViews import Gramplet, register from DataViews import Gramplet, register
from gen.lib import Person import gen.lib
def gender_code(is_male):
if is_male: return 1
return 0
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -127,7 +130,7 @@ class FanChartWidget(gtk.Widget):
self.angle = {} self.angle = {}
self.data = {} self.data = {}
for i in range(self.generations): for i in range(self.generations):
self.data[i] = [None for j in range(2 ** i)] self.data[i] = [(None, None, None) for j in range(2 ** i)]
self.angle[i] = [] self.angle[i] = []
angle = 0 angle = 0
slice = 360.0 / (2 ** i) slice = 360.0 / (2 ** i)
@ -205,14 +208,13 @@ class FanChartWidget(gtk.Widget):
cr.rotate(self.rotate_value * math.pi/180) cr.rotate(self.rotate_value * math.pi/180)
for generation in range(self.generations - 1, 0, -1): for generation in range(self.generations - 1, 0, -1):
for p in range(len(self.data[generation])): for p in range(len(self.data[generation])):
person = self.data[generation][p] (text, person, parents) = self.data[generation][p]
if person: if person:
start, stop, male, state = self.angle[generation][p] start, stop, male, state = self.angle[generation][p]
name = name_displayer.display(person)
gender = person.get_gender()
if state in [self.NORMAL, self.EXPANDED]: if state in [self.NORMAL, self.EXPANDED]:
self.draw_person(cr, gender, name, start, stop, self.draw_person(cr, gender_code(male),
generation, state) text, start, stop,
generation, state, parents)
cr.set_source_rgb(1, 1, 1) # white cr.set_source_rgb(1, 1, 1) # white
cr.move_to(0,0) cr.move_to(0,0)
cr.arc(0, 0, self.center, 0, 2 * math.pi) cr.arc(0, 0, self.center, 0, 2 * math.pi)
@ -222,7 +224,7 @@ class FanChartWidget(gtk.Widget):
cr.arc(0, 0, self.center, 0, 2 * math.pi) cr.arc(0, 0, self.center, 0, 2 * math.pi)
cr.stroke() cr.stroke()
# Draw center person: # Draw center person:
person = self.data[0][0] (text, person, parents) = self.data[0][0]
cr.restore() cr.restore()
if person: if person:
cr.save() cr.save()
@ -234,7 +236,8 @@ class FanChartWidget(gtk.Widget):
cr.update_layout(self.layout) cr.update_layout(self.layout)
cr.show_layout(self.layout) cr.show_layout(self.layout)
def draw_person(self, cr, gender, name, start, stop, generation, state): def draw_person(self, cr, gender, name, start, stop, generation,
state, parents):
""" """
Display the piece of pie for a given person. start and stop Display the piece of pie for a given person. start and stop
are in degrees. are in degrees.
@ -243,12 +246,25 @@ class FanChartWidget(gtk.Widget):
start_rad = start * math.pi/180 start_rad = start * math.pi/180
stop_rad = stop * math.pi/180 stop_rad = stop * math.pi/180
r,g,b = self.GENCOLOR[generation % len(self.GENCOLOR)] r,g,b = self.GENCOLOR[generation % len(self.GENCOLOR)]
if gender == Person.MALE: if gender == gen.lib.Person.MALE:
r -= r * .10 r -= r * .10
g -= g * .10 g -= g * .10
b -= b * .10 b -= b * .10
cr.set_source_rgb(r/255., g/255., b/255.)
radius = generation * self.pixels_per_generation + self.center radius = generation * self.pixels_per_generation + self.center
# If max generation, and they have parents:
if generation == self.generations - 1 and parents:
# draw an indicator
cr.move_to(0, 0)
#cr.set_source_rgba(1, 0.2, 0.2, 0.6) # pink
cr.set_source_rgb(255, 255, 255) # white
cr.arc(0, 0, radius + 5, start_rad, stop_rad)
cr.fill()
cr.move_to(0, 0)
cr.set_source_rgb(0, 0, 0) # black
cr.arc(0, 0, radius + 5, start_rad, stop_rad)
cr.line_to(0, 0)
cr.stroke()
cr.set_source_rgb(r/255., g/255., b/255.)
cr.move_to(0, 0) cr.move_to(0, 0)
cr.arc(0, 0, radius, start_rad, stop_rad) cr.arc(0, 0, radius, start_rad, stop_rad)
cr.move_to(0, 0) cr.move_to(0, 0)
@ -263,6 +279,7 @@ class FanChartWidget(gtk.Widget):
else: # EXPANDED else: # EXPANDED
cr.set_line_width(3) cr.set_line_width(3)
cr.stroke() cr.stroke()
cr.set_line_width(1)
if self.last_x == None or self.last_y == None: if self.last_x == None or self.last_y == None:
self.draw_text(cr, name, radius - self.pixels_per_generation/2, self.draw_text(cr, name, radius - self.pixels_per_generation/2,
start, stop) start, stop)
@ -461,25 +478,27 @@ class FanChartWidget(gtk.Widget):
selected = None selected = None
if (0 < generation < self.generations): if (0 < generation < self.generations):
for p in range(len(self.angle[generation])): for p in range(len(self.angle[generation])):
start, stop, male, state = self.angle[generation][p] if self.data[generation][p][1]: # there is a person there
if state == self.COLLAPSED: continue start, stop, male, state = self.angle[generation][p]
if start <= pos <= stop: if state == self.COLLAPSED: continue
selected = p if start <= pos <= stop:
break selected = p
if selected == None: # click in open area break
# save the mouse location for movements # Handle the click:
if selected == None: # clicked in open area
if radius < self.center: if radius < self.center:
print "TODO: select children" print "TODO: select child, spouse"
self.queue_draw() self.queue_draw()
return True return True
else: else:
# save the mouse location for movements
self.last_x, self.last_y = event.x, event.y self.last_x, self.last_y = event.x, event.y
return True return True
# Do things based on state, event.state, or button, event.button # Do things based on state, event.state, or button, event.button
if event.button == 1: # left mouse if event.button == 1: # left mouse
self.change_slice(generation, selected) self.change_slice(generation, selected)
elif event.button == 3: # right mouse elif event.button == 3: # right mouse
person = self.data[generation][selected] text, person, parents = self.data[generation][selected]
if person and self.right_click_callback: if person and self.right_click_callback:
self.right_click_callback(person) self.right_click_callback(person)
self.queue_draw() self.queue_draw()
@ -490,7 +509,6 @@ class FanChartGramplet(Gramplet):
The Gramplet code that realizes the FanChartWidget. The Gramplet code that realizes the FanChartWidget.
""" """
def init(self): def init(self):
self.sa = SimpleAccess(self.dbstate.db)
self.set_tooltip("Click to expand/contract person\nRight-click to make person active") self.set_tooltip("Click to expand/contract person\nRight-click to make person active")
self.generations = 6 self.generations = 6
self.gui.fan = FanChartWidget(self.generations, self.gui.fan = FanChartWidget(self.generations,
@ -501,42 +519,88 @@ class FanChartGramplet(Gramplet):
# Make sure it is visible: # Make sure it is visible:
self.gui.fan.show() self.gui.fan.show()
def db_changed(self):
"""
Method called when database changes.
"""
# reset the db connection
self.sa = SimpleAccess(self.dbstate.db)
def active_changed(self, handle): def active_changed(self, handle):
""" """
Method called when active person changes. Method called when active person changes.
""" """
# Reset everything but rotation angle (leave it as is) # Reset everything but rotation angle (leave it as is)
self.gui.fan.reset_generations()
self.update() self.update()
def have_parents(self, person):
"""
Returns True if a person has parents.
"""
if person:
m = self.get_parent(person, "female")
f = self.get_parent(person, "male")
return m != None or f != None
return False
def get_parent(self, person, gender):
"""
Get the father if gender == "male", or get mother otherwise.
"""
if person:
parent_handle_list = person.get_parent_family_handle_list()
if parent_handle_list:
family_id = parent_handle_list[0]
family = self.dbstate.db.get_family_from_handle(family_id)
if family:
if gender == "male":
person_handle = gen.lib.Family.get_father_handle(family)
else:
person_handle = gen.lib.Family.get_mother_handle(family)
if person_handle:
return self.dbstate.db.get_person_from_handle(person_handle)
return None
def main(self): def main(self):
""" """
Fill the data structures with the active data. This initializes all Fill the data structures with the active data. This initializes all
data. data.
""" """
self.gui.fan.data[0][0] = self.dbstate.get_active_person() self.gui.fan.reset_generations()
person = self.dbstate.get_active_person()
if not person:
name = None
else:
name = name_displayer.display(person)
parents = self.have_parents(person)
self.gui.fan.data[0][0] = (name, person, parents)
for current in range(1, self.generations): for current in range(1, self.generations):
parent = 0 parent = 0
for p in self.gui.fan.data[current - 1]: # name, person, parents
self.gui.fan.data[current][parent] = self.sa.father(p) for (n,p,q) in self.gui.fan.data[current - 1]:
if self.gui.fan.data[current][parent] is None: # Get father's details:
person = self.get_parent(p, "male")
if person:
name = name_displayer.display(person)
else:
name = None
if current == self.generations - 1:
parents = self.have_parents(person)
else:
parents = None
self.gui.fan.data[current][parent] = (name, person, parents)
if person is None:
# start,stop,male/right,state # start,stop,male/right,state
self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED
parent += 1 parent += 1
self.gui.fan.data[current][parent] = self.sa.mother(p) # Get mother's details:
if self.gui.fan.data[current][parent] is None: person = self.get_parent(p, "female")
# start,stop,male/left,state if person:
name = name_displayer.display(person)
else:
name = None
parents = self.have_parents(person)
self.gui.fan.data[current][parent] = (name, person, parents)
if person is None:
# start,stop,male/right,state
self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED
parent += 1 parent += 1
self.gui.fan.queue_draw() self.gui.fan.queue_draw()
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Register the Gramplet # Register the Gramplet