Refractor so common base fan chart gramplet and view are shared

Fan chart view allows now configuration: max generation to set, 4 color schemes


svn: r20307
This commit is contained in:
Benny Malengier
2012-09-01 15:13:44 +00:00
parent 455d077c2c
commit c86f383122
11 changed files with 498 additions and 746 deletions
+12 -347
View File
@@ -38,7 +38,6 @@ from gi.repository import Pango
from gi.repository import Gtk
import math
from gi.repository import Gdk
from cgi import escape
try:
import cairo
except ImportError:
@@ -49,33 +48,31 @@ except ImportError:
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.display.name import displayer as name_displayer
from gen.ggettext import gettext as _
from gen.plug import Gramplet
from gen.utils.db import (find_children, find_parents, find_witnessed_people)
from libformatting import FormattingHelper
import gen.lib
from gen.errors import WindowActiveError
from gui.editors import EditPerson
import gui.utils
from gui.widgets.fanchart import FanChartWidget
from gui.widgets.fanchart import FanChartWidget, FanChartGrampsGUI
class FanChartGramplet(Gramplet):
class FanChartGramplet(FanChartGrampsGUI, Gramplet):
"""
The Gramplet code that realizes the FanChartWidget.
"""
def init(self):
self.set_tooltip(_("Click to expand/contract person\nRight-click for options\nClick and drag in open area to rotate"))
self.generations = 6
self.format_helper = FormattingHelper(self.dbstate)
self.gui.fan = FanChartWidget(self.generations, self.dbstate,
context_popup_callback=self.on_popup)
self.gui.fan.format_helper = self.format_helper
def __init__(self, gui, nav_group=0):
Gramplet.__init__(self, gui, nav_group)
FanChartGrampsGUI.__init__(self, 6, 0, self.on_childmenu_changed)
self.set_fan(FanChartWidget(self.dbstate, self.on_popup))
# Replace the standard textview with the fan chart widget:
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add_with_viewport(self.gui.fan)
self.gui.get_container_widget().add_with_viewport(self.fan)
# Make sure it is visible:
self.gui.fan.show()
self.fan.show()
def init(self):
self.set_tooltip(_("Click to expand/contract person\nRight-click for options\nClick and drag in open area to rotate"))
def active_changed(self, handle):
"""
@@ -84,340 +81,8 @@ class FanChartGramplet(Gramplet):
# Reset everything but rotation angle (leave it as is)
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 not m is f is None
return False
def have_children(self, person):
"""
Returns True if a person has children.
"""
if person:
for family_handle in person.get_family_handle_list():
family = self.dbstate.db.get_family_from_handle(family_handle)
if family and len(family.get_child_ref_list()) > 0:
return True
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):
"""
Fill the data structures with the active data. This initializes all
data.
"""
self.gui.fan.reset_generations()
active_handle = self.get_active('Person')
person = self.dbstate.db.get_person_from_handle(active_handle)
if not person:
name = None
else:
name = name_displayer.display(person)
parents = self.have_parents(person)
child = self.have_children(person)
self.gui.fan.data[0][0] = (name, person, parents, child)
for current in range(1, self.generations):
parent = 0
# name, person, parents, children
for (n,p,q,c) in self.gui.fan.data[current - 1]:
# 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, None)
if person is None:
# start,stop,male/right,state
self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED
parent += 1
# Get mother's details:
person = self.get_parent(p, "female")
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, None)
if person is None:
# start,stop,male/right,state
self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED
parent += 1
self.gui.fan.queue_draw()
def on_childmenu_changed(self, obj, person_handle):
"""Callback for the pulldown menu selection, changing to the person
attached with menu item."""
self.set_active('Person', person_handle)
return True
def edit_person_cb(self, obj,person_handle):
person = self.dbstate.db.get_person_from_handle(person_handle)
if person:
try:
EditPerson(self.dbstate, self.uistate, [], person)
except WindowActiveError:
pass
return True
return False
def copy_person_to_clipboard_cb(self, obj,person_handle):
"""Renders the person data into some lines of text and puts that into the clipboard"""
person = self.dbstate.db.get_person_from_handle(person_handle)
if person:
cb = Gtk.Clipboard.get_for_display(Gdk.Display.get_default(),
Gdk.SELECTION_CLIPBOARD)
cb.set_text( self.format_helper.format_person(person,11))
return True
return False
def on_popup(self, obj, event, person_handle):
"""
Builds the full menu (including Siblings, Spouses, Children,
and Parents) with navigation. Copied from PedigreeView.
"""
menu = Gtk.Menu()
menu.set_title(_('People Menu'))
person = self.dbstate.db.get_person_from_handle(person_handle)
if not person:
return 0
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
go_item = Gtk.ImageMenuItem(name_displayer.display(person))
go_item.set_image(go_image)
go_item.connect("activate",self.on_childmenu_changed,person_handle)
go_item.show()
menu.append(go_item)
edit_item = Gtk.ImageMenuItem(Gtk.STOCK_EDIT)
edit_item.connect("activate",self.edit_person_cb,person_handle)
edit_item.show()
menu.append(edit_item)
clipboard_item = Gtk.ImageMenuItem(Gtk.STOCK_COPY)
clipboard_item.connect("activate",self.copy_person_to_clipboard_cb,person_handle)
clipboard_item.show()
menu.append(clipboard_item)
# collect all spouses, parents and children
linked_persons = []
# Go over spouses and build their menu
item = Gtk.MenuItem(label=_("Spouses"))
fam_list = person.get_family_handle_list()
no_spouses = 1
for fam_id in fam_list:
family = self.dbstate.db.get_family_from_handle(fam_id)
if family.get_father_handle() == person.get_handle():
sp_id = family.get_mother_handle()
else:
sp_id = family.get_father_handle()
spouse = self.dbstate.db.get_person_from_handle(sp_id)
if not spouse:
continue
if no_spouses:
no_spouses = 0
item.set_submenu(Gtk.Menu())
sp_menu = item.get_submenu()
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
sp_item = Gtk.ImageMenuItem(name_displayer.display(spouse))
sp_item.set_image(go_image)
linked_persons.append(sp_id)
sp_item.connect("activate",self.on_childmenu_changed,sp_id)
sp_item.show()
sp_menu.append(sp_item)
if no_spouses:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over siblings and build their menu
item = Gtk.MenuItem(label=_("Siblings"))
pfam_list = person.get_parent_family_handle_list()
no_siblings = 1
for f in pfam_list:
fam = self.dbstate.db.get_family_from_handle(f)
sib_list = fam.get_child_ref_list()
for sib_ref in sib_list:
sib_id = sib_ref.ref
if sib_id == person.get_handle():
continue
sib = self.dbstate.db.get_person_from_handle(sib_id)
if not sib:
continue
if no_siblings:
no_siblings = 0
item.set_submenu(Gtk.Menu())
sib_menu = item.get_submenu()
if find_children(self.dbstate.db,sib):
label = Gtk.Label(label='<b><i>%s</i></b>' % escape(name_displayer.display(sib)))
else:
label = Gtk.Label(label=escape(name_displayer.display(sib)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
sib_item = Gtk.ImageMenuItem(None)
sib_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
sib_item.add(label)
linked_persons.append(sib_id)
sib_item.connect("activate",self.on_childmenu_changed,sib_id)
sib_item.show()
sib_menu.append(sib_item)
if no_siblings:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over children and build their menu
item = Gtk.MenuItem(label=_("Children"))
no_children = 1
childlist = find_children(self.dbstate.db,person)
for child_handle in childlist:
child = self.dbstate.db.get_person_from_handle(child_handle)
if not child:
continue
if no_children:
no_children = 0
item.set_submenu(Gtk.Menu())
child_menu = item.get_submenu()
if find_children(self.dbstate.db,child):
label = Gtk.Label(label='<b><i>%s</i></b>' % escape(name_displayer.display(child)))
else:
label = Gtk.Label(label=escape(name_displayer.display(child)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
child_item = Gtk.ImageMenuItem(None)
child_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
child_item.add(label)
linked_persons.append(child_handle)
child_item.connect("activate",self.on_childmenu_changed,child_handle)
child_item.show()
child_menu.append(child_item)
if no_children:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over parents and build their menu
item = Gtk.MenuItem(label=_("Parents"))
no_parents = 1
par_list = find_parents(self.dbstate.db,person)
for par_id in par_list:
par = self.dbstate.db.get_person_from_handle(par_id)
if not par:
continue
if no_parents:
no_parents = 0
item.set_submenu(Gtk.Menu())
par_menu = item.get_submenu()
if find_parents(self.dbstate.db,par):
label = Gtk.Label(label='<b><i>%s</i></b>' % escape(name_displayer.display(par)))
else:
label = Gtk.Label(label=escape(name_displayer.display(par)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
par_item = Gtk.ImageMenuItem(None)
par_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
par_item.add(label)
linked_persons.append(par_id)
par_item.connect("activate",self.on_childmenu_changed,par_id)
par_item.show()
par_menu.append(par_item)
if no_parents:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over parents and build their menu
item = Gtk.MenuItem(label=_("Related"))
no_related = 1
for p_id in find_witnessed_people(self.dbstate.db,person):
#if p_id in linked_persons:
# continue # skip already listed family members
per = self.dbstate.db.get_person_from_handle(p_id)
if not per:
continue
if no_related:
no_related = 0
item.set_submenu(Gtk.Menu())
per_menu = item.get_submenu()
label = Gtk.Label(label=escape(name_displayer.display(per)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
per_item = Gtk.ImageMenuItem(None)
per_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
per_item.add(label)
per_item.connect("activate",self.on_childmenu_changed,p_id)
per_item.show()
per_menu.append(per_item)
if no_related:
item.set_sensitive(0)
item.show()
menu.append(item)
menu.popup(None, None, None, None, event.button, event.time)
return 1
@@ -146,4 +146,3 @@ class QuickViewGramplet(Gramplet):
qv_list = get_quick_report_list(code_map[qv_option.get_value()])
for pdata in qv_list:
list_option.add_item(pdata.id, pdata.name)
-1
View File
@@ -17,7 +17,6 @@ SUBDIRS = maps
pkgpython_PYTHON = \
libcairodoc.py\
libformatting.py\
libgedcom.py\
libgrampsxml.py\
libgrdb.py\
-200
View File
@@ -1,200 +0,0 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2007 Donald N. Allingham, Martin Hawlisch
#
# 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$
"""Format of commonly used expressions, making use of a cache to not
recompute
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from cgi import escape
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
import gen.datehandler
from gen.display.name import displayer as name_displayer
from gen.utils.db import get_birth_or_fallback, get_death_or_fallback, get_marriage_or_fallback
#-------------------------------------------------------------------------
#
# FormattingHelper class
#
#-------------------------------------------------------------------------
class FormattingHelper(object):
"""Format of commonly used expressions, making use of a cache to not
recompute
"""
def __init__(self, dbstate):
self.dbstate = dbstate
self._text_cache = {}
self._markup_cache = {}
def format_relation(self, family, line_count, use_markup=False):
""" Format a relation between parents of a family
"""
if not family:
return ""
if use_markup:
if family.handle in self._markup_cache:
if line_count in self._markup_cache[family.handle]:
return self._markup_cache[family.handle][line_count]
else:
if family.handle in self._text_cache:
if line_count in self._text_cache[family.handle]:
return self._text_cache[family.handle][line_count]
text = ""
marriage = get_marriage_or_fallback(self.dbstate.db, family)
if marriage and use_markup and marriage.get_type() != gen.lib.EventType.MARRIAGE:
mdate = "<i>%s %s</i>" % (marriage.get_type().get_abbreviation(),
escape(gen.datehandler.get_date(marriage)))
mplace = "<i>%s</i>" % escape(self.get_place_name(marriage.get_place_handle()))
name = "<i>%s</i>" % str(marriage.get_type())
elif marriage and use_markup:
mdate = "%s %s" % (marriage.get_type().get_abbreviation(),
escape(gen.datehandler.get_date(marriage)))
mplace = escape(self.get_place_name(marriage.get_place_handle()))
name = str(marriage.get_type())
elif marriage:
mdate = "%s %s" % (marriage.get_type().get_abbreviation(),
gen.datehandler.get_date(marriage))
mplace = self.get_place_name(marriage.get_place_handle())
name = str(marriage.get_type())
else:
mdate = ""
mplace = ""
name = ""
if line_count >= 1:
text += mdate
text += "\n"
if line_count >= 2:
text += name
text += "\n"
if line_count >= 3:
text += mplace
text += "\n"
if not text:
text = str(family.get_relationship())
if use_markup:
if not family.handle in self._markup_cache:
self._markup_cache[family.handle] = {}
self._markup_cache[family.handle][line_count] = text
else:
if not family.handle in self._text_cache:
self._text_cache[family.handle] = {}
self._text_cache[family.handle][line_count] = text
return text
def get_place_name(self, place_handle):
""" Obtain a place name
"""
text = ""
place = self.dbstate.db.get_place_from_handle(place_handle)
if place:
place_title = place.get_title()
if place_title != "":
if len(place_title) > 25:
text = place_title[:24]+"..."
else:
text = place_title
return text
def format_person( self, person, line_count, use_markup=False):
"""fromat how info about a person should be presented
"""
if not person:
return ""
if use_markup:
if person.handle in self._markup_cache:
if line_count in self._markup_cache[person.handle]:
return self._markup_cache[person.handle][line_count]
name = escape(name_displayer.display(person))
else:
if person.handle in self._text_cache:
if line_count in self._text_cache[person.handle]:
return self._text_cache[person.handle][line_count]
name = name_displayer.display(person)
text = name
if line_count >= 3:
birth = get_birth_or_fallback(self.dbstate.db, person)
if birth and use_markup and birth.get_type() != \
gen.lib.EventType.BIRTH:
bdate = "<i>%s</i>" % escape(gen.datehandler.get_date(birth))
bplace = "<i>%s</i>" % escape(self.get_place_name(
birth.get_place_handle()))
elif birth and use_markup:
bdate = escape(gen.datehandler.get_date(birth))
bplace = escape(self.get_place_name(birth.get_place_handle()))
elif birth:
bdate = gen.datehandler.get_date(birth)
bplace = self.get_place_name(birth.get_place_handle())
else:
bdate = ""
bplace = ""
death = get_death_or_fallback(self.dbstate.db, person)
if death and use_markup and death.get_type() != \
gen.lib.EventType.DEATH:
ddate = "<i>%s</i>" % escape(gen.datehandler.get_date(death))
dplace = "<i>%s</i>" % escape(self.get_place_name(
death.get_place_handle()))
elif death and use_markup:
ddate = escape(gen.datehandler.get_date(death))
dplace = escape(self.get_place_name(death.get_place_handle()))
elif death:
ddate = gen.datehandler.get_date(death)
dplace = self.get_place_name(death.get_place_handle())
else:
ddate = ""
dplace = ""
if line_count < 5:
text = "%s\n* %s\n+ %s" % (name, bdate, ddate)
else:
text = "%s\n* %s\n %s\n+ %s\n %s" % (name, bdate, bplace,
ddate, dplace)
if use_markup:
if not person.handle in self._markup_cache:
self._markup_cache[person.handle] = {}
self._markup_cache[person.handle][line_count] = text
else:
if not person.handle in self._text_cache:
self._text_cache[person.handle] = {}
self._text_cache[person.handle][line_count] = text
return text
def clear_cache( self):
"""clear the cache of kept format strings
"""
self._text_cache = {}
self._markup_cache = {}
-18
View File
@@ -40,24 +40,6 @@ authors_email = ["http://gramps-project.org"],
#load_on_reg = True
)
#------------------------------------------------------------------------
#
# libformatting
#
#------------------------------------------------------------------------
register(GENERAL,
id = 'libformatting',
name = "FormattingHelper lib",
description = _("Provides a FormattingHelper class for common strings"),
version = '1.0',
gramps_target_version = '4.0',
status = STABLE,
fname = 'libformatting.py',
authors = ["The Gramps project"],
authors_email = ["http://gramps-project.org"],
#load_on_reg = True
)
#------------------------------------------------------------------------
#
# libgedcom
+1 -1
View File
@@ -50,7 +50,7 @@ from gi.repository import GdkPixbuf
import gen.lib
from gen.display.name import displayer as _nd
from gui.views.navigationview import NavigationView
from libformatting import FormattingHelper
from gen.utils.libformatting import FormattingHelper
from gen.errors import WindowActiveError
from gen.const import HOME_DIR, ROOT_DIR
from gui.managedwindow import ManagedWindow
+74 -351
View File
@@ -35,7 +35,6 @@
from gi.repository import Gdk
from gi.repository import Gtk
import cairo
from cgi import escape
from gen.ggettext import gettext as _
#-------------------------------------------------------------------------
@@ -43,37 +42,40 @@ from gen.ggettext import gettext as _
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.display.name import displayer as name_displayer
from gen.utils.db import (find_children, find_parents, find_witnessed_people)
from libformatting import FormattingHelper
import gen.lib
from gui.widgets.fanchart import FanChartWidget
from gui.widgets.fanchart import FanChartWidget, FanChartGrampsGUI
from gui.views.navigationview import NavigationView
from gen.errors import WindowActiveError
from gui.views.bookmarks import PersonBookmarks
from gui.editors import EditPerson
# the print settings to remember between print sessions
PRINT_SETTINGS = None
class FanChartView(NavigationView):
class FanChartView(FanChartGrampsGUI, NavigationView):
"""
The Gramplet code that realizes the FanChartWidget.
"""
#settings in the config file
CONFIGSETTINGS = (
('interface.fanview-maxgen', 9),
('interface.fanview-background', 0),
)
def __init__(self, pdata, dbstate, uistate, nav_group=0):
self.dbstate = dbstate
self.uistate = uistate
NavigationView.__init__(self, _('Fan Chart'),
pdata, dbstate, uistate,
dbstate.db.get_bookmarks(),
PersonBookmarks,
nav_group)
nav_group)
FanChartGrampsGUI.__init__(self,
self._config.get('interface.fanview-maxgen'),
self._config.get('interface.fanview-background'),
self.on_childmenu_changed)
dbstate.connect('active-changed', self.active_changed)
dbstate.connect('database-changed', self.change_db)
self.dbstate = dbstate
self.uistate = uistate
self.generations = 9
self.format_helper = FormattingHelper(self.dbstate)
self.additional_uis.append(self.additional_ui())
@@ -81,9 +83,7 @@ class FanChartView(NavigationView):
return 'Person'
def build_widget(self):
self.fan = FanChartWidget(self.generations, self.dbstate,
context_popup_callback=self.on_popup)
self.fan.format_helper = self.format_helper
self.set_fan(FanChartWidget(self.dbstate, self.on_popup))
self.scrolledwindow = Gtk.ScrolledWindow(None, None)
self.scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC)
@@ -188,110 +188,10 @@ class FanChartView(NavigationView):
self.change_active(handle)
self.main()
def have_parents(self, person):
def get_active(self, object):
"""overrule get_active, to support call as in Gramplets
"""
Returns True if a person has parents.
"""
if person:
m = self.get_parent(person, False)
f = self.get_parent(person, True)
return not m is f is None
return False
def have_children(self, person):
"""
Returns True if a person has children.
"""
if person:
for family_handle in person.get_family_handle_list():
family = self.dbstate.db.get_family_from_handle(family_handle)
if family and len(family.get_child_ref_list()) > 0:
return True
return False
def get_parent(self, person, father):
"""
Get the father of the family if father == True, otherwise mother
"""
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 father:
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):
"""
Fill the data structures with the active data. This initializes all
data.
"""
self.fan.reset_generations()
person = self.dbstate.db.get_person_from_handle(self.get_active())
if not person:
name = None
else:
name = name_displayer.display(person)
parents = self.have_parents(person)
child = self.have_children(person)
self.fan.data[0][0] = (name, person, parents, child)
for current in range(1, self.generations):
parent = 0
# name, person, parents, children
for (n,p,q,c) in self.fan.data[current - 1]:
# Get father's details:
person = self.get_parent(p, True)
if person:
name = name_displayer.display(person)
else:
name = None
if current == self.generations - 1:
parents = self.have_parents(person)
else:
parents = None
self.fan.data[current][parent] = (name, person, parents, None)
if person is None:
# start,stop,male/right,state
self.fan.angle[current][parent][3] = self.fan.COLLAPSED
parent += 1
# Get mother's details:
person = self.get_parent(p, False)
if person:
name = name_displayer.display(person)
else:
name = None
if current == self.generations - 1:
parents = self.have_parents(person)
else:
parents = None
self.fan.data[current][parent] = (name, person, parents, None)
if person is None:
# start,stop,male/right,state
self.fan.angle[current][parent][3] = self.fan.COLLAPSED
parent += 1
self.fan.queue_draw()
def on_childmenu_changed(self, obj, person_handle):
"""Callback for the pulldown menu selection, changing to the person
attached with menu item."""
self.change_active(person_handle)
return True
def edit_person_cb(self, obj,person_handle):
person = self.dbstate.db.get_person_from_handle(person_handle)
if person:
try:
EditPerson(self.dbstate, self.uistate, [], person)
except WindowActiveError:
pass
return True
return False
return NavigationView.get_active(self)
def person_rebuild(self, *args):
self.update()
@@ -301,239 +201,6 @@ class FanChartView(NavigationView):
self.person_rebuild()
if self.active:
self.bookmarks.redraw()
def copy_person_to_clipboard_cb(self, obj, person_handle):
"""Renders the person data into some lines of text and puts that into the clipboard"""
person = self.dbstate.db.get_person_from_handle(person_handle)
if person:
cb = Gtk.Clipboard.get_for_display(Gdk.Display.get_default(),
Gdk.SELECTION_CLIPBOARD)
cb.set_text( self.format_helper.format_person(person,11), -1)
return True
return False
def on_popup(self, obj, event, person_handle):
"""
Builds the full menu (including Siblings, Spouses, Children,
and Parents) with navigation. Copied from PedigreeView.
"""
#store menu for GTK3 to avoid it being destroyed before showing
self.menu = Gtk.Menu()
menu = self.menu
menu.set_title(_('People Menu'))
person = self.dbstate.db.get_person_from_handle(person_handle)
if not person:
return 0
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO,Gtk.IconSize.MENU)
go_image.show()
go_item = Gtk.ImageMenuItem(name_displayer.display(person))
go_item.set_image(go_image)
go_item.connect("activate",self.on_childmenu_changed,person_handle)
go_item.show()
menu.append(go_item)
edit_item = Gtk.ImageMenuItem.new_from_stock(stock_id=Gtk.STOCK_EDIT, accel_group=None)
edit_item.connect("activate", self.edit_person_cb, person_handle)
edit_item.show()
menu.append(edit_item)
clipboard_item = Gtk.ImageMenuItem.new_from_stock(stock_id=Gtk.STOCK_COPY, accel_group=None)
clipboard_item.connect("activate",self.copy_person_to_clipboard_cb,person_handle)
clipboard_item.show()
menu.append(clipboard_item)
# collect all spouses, parents and children
linked_persons = []
# Go over spouses and build their menu
item = Gtk.MenuItem(label=_("Spouses"))
fam_list = person.get_family_handle_list()
no_spouses = 1
for fam_id in fam_list:
family = self.dbstate.db.get_family_from_handle(fam_id)
if family.get_father_handle() == person.get_handle():
sp_id = family.get_mother_handle()
else:
sp_id = family.get_father_handle()
spouse = self.dbstate.db.get_person_from_handle(sp_id)
if not spouse:
continue
if no_spouses:
no_spouses = 0
item.set_submenu(Gtk.Menu())
sp_menu = item.get_submenu()
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO, Gtk.IconSize.MENU)
go_image.show()
sp_item = Gtk.ImageMenuItem(name_displayer.display(spouse))
sp_item.set_image(go_image)
linked_persons.append(sp_id)
sp_item.connect("activate",self.on_childmenu_changed,sp_id)
sp_item.show()
sp_menu.append(sp_item)
if no_spouses:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over siblings and build their menu
item = Gtk.MenuItem(label=_("Siblings"))
pfam_list = person.get_parent_family_handle_list()
no_siblings = 1
for f in pfam_list:
fam = self.dbstate.db.get_family_from_handle(f)
sib_list = fam.get_child_ref_list()
for sib_ref in sib_list:
sib_id = sib_ref.ref
if sib_id == person.get_handle():
continue
sib = self.dbstate.db.get_person_from_handle(sib_id)
if not sib:
continue
if no_siblings:
no_siblings = 0
item.set_submenu(Gtk.Menu())
sib_menu = item.get_submenu()
if find_children(self.dbstate.db,sib):
label = Gtk.Label(label='<b><i>%s</i></b>' % escape(name_displayer.display(sib)))
else:
label = Gtk.Label(label=escape(name_displayer.display(sib)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO, Gtk.IconSize.MENU)
go_image.show()
sib_item = Gtk.ImageMenuItem(None)
sib_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
sib_item.add(label)
linked_persons.append(sib_id)
sib_item.connect("activate", self.on_childmenu_changed, sib_id)
sib_item.show()
sib_menu.append(sib_item)
if no_siblings:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over children and build their menu
item = Gtk.MenuItem(label=_("Children"))
no_children = 1
childlist = find_children(self.dbstate.db, person)
for child_handle in childlist:
child = self.dbstate.db.get_person_from_handle(child_handle)
if not child:
continue
if no_children:
no_children = 0
item.set_submenu(Gtk.Menu())
child_menu = item.get_submenu()
if find_children(self.dbstate.db,child):
label = Gtk.Label(label='<b><i>%s</i></b>' % escape(name_displayer.display(child)))
else:
label = Gtk.Label(label=escape(name_displayer.display(child)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO, Gtk.IconSize.MENU)
go_image.show()
child_item = Gtk.ImageMenuItem(None)
child_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
child_item.add(label)
linked_persons.append(child_handle)
child_item.connect("activate", self.on_childmenu_changed, child_handle)
child_item.show()
child_menu.append(child_item)
if no_children:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over parents and build their menu
item = Gtk.MenuItem(label=_("Parents"))
no_parents = 1
par_list = find_parents(self.dbstate.db,person)
for par_id in par_list:
par = self.dbstate.db.get_person_from_handle(par_id)
if not par:
continue
if no_parents:
no_parents = 0
item.set_submenu(Gtk.Menu())
par_menu = item.get_submenu()
if find_parents(self.dbstate.db,par):
label = Gtk.Label(label='<b><i>%s</i></b>' % escape(name_displayer.display(par)))
else:
label = Gtk.Label(label=escape(name_displayer.display(par)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO, Gtk.IconSize.MENU)
go_image.show()
par_item = Gtk.ImageMenuItem(None)
par_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0,0)
par_item.add(label)
linked_persons.append(par_id)
par_item.connect("activate",self.on_childmenu_changed,par_id)
par_item.show()
par_menu.append(par_item)
if no_parents:
item.set_sensitive(0)
item.show()
menu.append(item)
# Go over parents and build their menu
item = Gtk.MenuItem(label=_("Related"))
no_related = 1
for p_id in find_witnessed_people(self.dbstate.db,person):
#if p_id in linked_persons:
# continue # skip already listed family members
per = self.dbstate.db.get_person_from_handle(p_id)
if not per:
continue
if no_related:
no_related = 0
item.set_submenu(Gtk.Menu())
per_menu = item.get_submenu()
label = Gtk.Label(label=escape(name_displayer.display(per)))
go_image = Gtk.Image.new_from_stock(Gtk.STOCK_JUMP_TO, Gtk.IconSize.MENU)
go_image.show()
per_item = Gtk.ImageMenuItem(None)
per_item.set_image(go_image)
label.set_use_markup(True)
label.show()
label.set_alignment(0, 0)
per_item.add(label)
per_item.connect("activate", self.on_childmenu_changed, p_id)
per_item.show()
per_menu.append(per_item)
if no_related:
item.set_sensitive(0)
item.show()
menu.append(item)
menu.popup(None, None, None, None, event.button, event.time)
return 1
def printview(self, obj):
"""
@@ -544,6 +211,62 @@ class FanChartView(NavigationView):
prt = CairoPrintSave(widthpx, self.fan.on_draw, self.uistate.window)
prt.run()
def on_childmenu_changed(self, obj, person_handle):
"""Callback for the pulldown menu selection, changing to the person
attached with menu item."""
self.change_active(person_handle)
return True
def can_configure(self):
"""
See :class:`~gui.views.pageview.PageView
:return: bool
"""
return True
def _get_configure_page_funcs(self):
"""
Return a list of functions that create gtk elements to use in the
notebook pages of the Configure dialog
:return: list of functions
"""
return [self.config_panel]
def config_panel(self, configdialog):
"""
Function that builds the widget in the configuration dialog
"""
table = Gtk.Table(3, 2)
table.set_border_width(12)
table.set_col_spacings(6)
table.set_row_spacings(6)
configdialog.add_spinner(table, _("Max generations"), 0,
'interface.fanview-maxgen', (1, 11),
callback=self.cb_update_maxgen)
configdialog.add_combo(table,
_('Background'),
4, 'interface.fanview-background',
((0, _('Color Scheme 1')),
(1, _('Color Scheme 2')),
(2, _('Gender Colors')),
(3, _('White'))),
callback=self.cb_update_background)
return _('Layout'), table
def cb_update_maxgen(self, spinbtn, constant):
self.maxgen = spinbtn.get_value_as_int()
self._config.set(constant, self.maxgen)
self.update()
def cb_update_background(self, obj, constant):
entry = obj.get_active()
self._config.set(constant, entry)
self.background = int(entry)
self.update()
#------------------------------------------------------------------------
#
# CairoPrintSave class
+1 -1
View File
@@ -60,7 +60,7 @@ from gen.display.name import displayer as name_displayer
from gen.utils.alive import probably_alive
from gen.utils.file import media_path_full
from gen.utils.db import find_children, find_parents, find_witnessed_people
from libformatting import FormattingHelper
from gen.utils.libformatting import FormattingHelper
from gui.thumbnails import get_thumbnail_path
from gen.errors import WindowActiveError
from gui.editors import EditPerson, EditFamily