2007-12-24 Douglas S. Blank <dblank@cs.brynmawr.edu>

* src/DataViews/_MyGrampsView.py: new DataView for Gadgets
	* src/DataViews/__init__.py: import things from _MyGrampsView
	* src/Config/_GrampsConfigKeys.py: added data-views
	* src/glade/gramps.glade: added My Gramps Gadget gui
	* src/plugins/DefaultGadgets.py: sample gadgets



svn: r9573
This commit is contained in:
Doug Blank 2007-12-24 14:56:15 +00:00
parent 677a0e280f
commit 50492711e8
6 changed files with 840 additions and 5 deletions

View File

@ -1,3 +1,10 @@
2007-12-24 Douglas S. Blank <dblank@cs.brynmawr.edu>
* src/DataViews/_MyGrampsView.py: new DataView for Gadgets
* src/DataViews/__init__.py: import things from _MyGrampsView
* src/Config/_GrampsConfigKeys.py: added data-views
* src/glade/gramps.glade: added My Gramps Gadget gui
* src/plugins/DefaultGadgets.py: sample gadgets
2007-12-24 Brian Matherly <brian@gramps-project.org>
* src/ReportBase/Makefile.am: Add _DocReportDialog.py to the Makefile

View File

@ -160,6 +160,7 @@ MAX_SIB_AGE_DIFF = ('behavior', 'max-sib-age-diff', 1)
MIN_GENERATION_YEARS = ('behavior', 'min-generation-years', 1)
AVG_GENERATION_GAP = ('behavior', 'avg-generation-gap', 1)
GENERATION_DEPTH = ('behavior', 'generation-depth', 1)
DATA_VIEWS = ('interface','data-views', 2)
default_value = {
DEFAULT_SOURCE : False,
@ -276,4 +277,7 @@ default_value = {
MIN_GENERATION_YEARS : 13,
AVG_GENERATION_GAP : 20,
GENERATION_DEPTH : 15,
DATA_VIEWS: ('PersonView,RelationshipView,FamilyListView,PedigreeView,'
'EventView,SourceView,PlaceView,MediaView,RepositoryView,'
'NoteView'),
}

View File

@ -0,0 +1,381 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
#
# 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: _MyGrampsView.py $
"""
MyGrampsView interface
"""
__author__ = "Doug Blank"
__revision__ = "$Revision: $"
import gtk
import PageView
import const
import gobject
import traceback
import time
AVAILABLE_GADGETS = []
debug = False
def register_gadget(data_dict):
global AVAILABLE_GADGETS
AVAILABLE_GADGETS.append(data_dict)
def register(**data):
if "type" in data:
if data["type"].lower() == "gadget":
register_gadget(data)
def get_gadget_opts(name, opts):
for data in AVAILABLE_GADGETS:
if data.get("name", None) == name:
my_data = data.copy()
my_data.update(opts)
return my_data
return {}
def make_requested_gadget(viewpage, name, opts, dbstate):
for data in AVAILABLE_GADGETS:
if data.get("name", None) == name:
gui = GuiGadget(viewpage, dbstate, **opts)
if opts.get("content", None):
opts["content"](gui)
return gui
return None
class Gadget(object):
def __init__(self, gui):
self._idle_id = 0
self._generator = None
self._need_to_update = False
self.gui = gui
self.dbstate = gui.dbstate
self.init()
self.dbstate.connect('database-changed', self._db_changed)
self.dbstate.connect('active-changed', self.active_changed)
def active_changed(self, handle):
pass
def _db_changed(self, dbstate):
if debug: print "%s is _connecting" % self.gui.title
self.dbstate = dbstate
self.gui.dbstate = dbstate
self.db_changed()
self.update()
def db_changed(self):
if debug: print "%s is connecting" % self.gui.title
pass
def init(self): # once, constructor
pass
def main(self): # once per db open
pass
def update(self, *handles):
self.main()
if self._idle_id != 0:
if debug: print "%s interrupt!" % self.gui.title
self.interrupt()
if debug: print "%s creating generator" % self.gui.title
self._generator = self.background()
if debug: print "%s adding to gobject" % self.gui.title
self._idle_id = gobject.idle_add(self._updater,
priority=gobject.PRIORITY_LOW)
def background(self): # return false finishes
if debug: print "%s dummy" % self.gui.title
yield False
def interrupt(self):
"""
Force the generator to stop running.
"""
if self._idle_id == 0:
if debug: print "%s removing from gobject" % self.gui.title
gobject.source_remove(self._idle_id)
self._idle_id = 0
def _updater(self):
if debug: print "%s _updater" % self.gui.title
try:
retval = self._generator.next()
if retval == False:
self._idle_id = 0
return retval
except StopIteration:
self._idle_id = 0
return False
except Exception, e:
#self._error = e
traceback.print_exc()
self._idle_id = 0
return False
except:
self._idle_id = 0
return False
def append_text(self, text):
self.gui.buffer.insert_at_cursor(text)
def clear_text(self):
self.gui.buffer.set_text('')
def set_text(self, text):
self.gui.buffer.set_text(text)
class GuiGadget:
"""
Class that handles the plugin interfaces for the MyGrampsView.
"""
TARGET_TYPE_FRAME = 80
LOCAL_DRAG_TYPE = 'GADGET'
LOCAL_DRAG_TARGET = (LOCAL_DRAG_TYPE, 0, TARGET_TYPE_FRAME)
def __init__(self, viewpage, dbstate, title, **kwargs):
self.viewpage = viewpage
self.dbstate = dbstate
self.title = title
########## Set defaults
self.expand = kwargs.get("expand", False)
self.height = kwargs.get("height", 200)
self.column = kwargs.get("column", -1)
self.row = kwargs.get("row", -1)
self.state = kwargs.get("state", "maximized")
##########
self.xml = gtk.glade.XML(const.GLADE_FILE, 'gvgadget', "gramps")
self.mainframe = self.xml.get_widget('gvgadget')
self.textview = self.xml.get_widget('gvtextview')
self.buffer = self.textview.get_buffer()
self.scrolledwindow = self.xml.get_widget('gvscrolledwindow')
self.titlelabel = self.xml.get_widget('gvtitle')
self.titlelabel.set_text("<b><i>%s</i></b>" % self.title)
self.titlelabel.set_use_markup(True)
self.xml.get_widget('gvclose').connect('clicked', self.close)
self.xml.get_widget('gvstate').connect('clicked', self.change_state)
self.xml.get_widget('gvproperties').connect('clicked',
self.set_properties)
self.xml.get_widget('gvcloseimage').set_from_stock(gtk.STOCK_CLOSE,
gtk.ICON_SIZE_MENU)
self.xml.get_widget('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
gtk.ICON_SIZE_MENU)
self.xml.get_widget('gvpropertiesimage').set_from_stock(gtk.STOCK_PROPERTIES,
gtk.ICON_SIZE_MENU)
# source:
drag = self.xml.get_widget('gvproperties')
drag.drag_source_set(gtk.gdk.BUTTON1_MASK,
[GuiGadget.LOCAL_DRAG_TARGET],
gtk.gdk.ACTION_COPY)
def close(self, obj):
del self.viewpage.gadget_map[self.title]
del self.viewpage.frame_map[str(self.mainframe)]
self.mainframe.destroy()
def change_state(self, obj):
if self.state == "maximized":
self.scrolledwindow.hide()
self.xml.get_widget('gvstateimage').set_from_stock(gtk.STOCK_ADD,
gtk.ICON_SIZE_MENU)
self.state = "minimized"
else:
self.scrolledwindow.show()
self.xml.get_widget('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
gtk.ICON_SIZE_MENU)
self.state = "maximized"
if self.expand:
column = self.mainframe.get_parent() # column
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe,(not expand),fill,padding,pack)
def set_properties(self, obj):
self.expand = not self.expand
if self.state == "maximized":
column = self.mainframe.get_parent() # column
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe,self.expand,fill,padding,pack)
def append_text(self, text):
self.buffer.insert_at_cursor(text)
def clear_text(self):
self.buffer.set_text('')
def set_text(self, text):
self.buffer.set_text(text)
class MyGrampsView(PageView.PageView):
"""
MyGrampsView interface
"""
def __init__(self, dbstate, uistate):
"""
Creates a MyGrampsView, with the current dbstate and uistate
"""
PageView.PageView.__init__(self, _('My Gramps'), dbstate, uistate)
self.column_count = 3
def change_db(self, event):
"""
"""
# FIXME: remove/add widgets from new db ini file
pass
def build_widget(self):
"""
Builds the container widget for the interface. Must be overridden by the
the base class. Returns a gtk container widget.
"""
frame = gtk.ScrolledWindow()
frame.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
hbox = gtk.HBox(homogeneous=True)
# Set up drag and drop
frame.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
gtk.DEST_DEFAULT_HIGHLIGHT |
gtk.DEST_DEFAULT_DROP,
[('GADGET', 0, 80)],
gtk.gdk.ACTION_COPY)
frame.connect('drag_drop', self.drop_widget)
frame.add_with_viewport(hbox)
# Create the columns:
self.columns = []
for i in range(self.column_count):
self.columns.append(gtk.VBox())
hbox.pack_start(self.columns[-1],expand=True)
# Load the gadgets
self.gadget_map = {} # title->gadget
self.frame_map = {} # frame->gadget
# FIXME
# get the user's gadgets from .gramps
# and/or from open database
# Load the user's gadgets:
for (name, opts) in [('Stats Gadget', {}),
('Top Surnames Gadget', {}),
#('Families Gadget', {}),
#('Families Gadget', {"title": "My Peeps"}),
('Hello World Gadget', {}),
('Log Gadget', {}),
#('Events Gadget', {}),
]:
all_opts = get_gadget_opts(name, opts)
if "title" not in all_opts:
all_opts["title"] = "Untitled Gadget"
# uniqify titles:
unique = all_opts["title"]
cnt = 1
while unique in self.gadget_map:
unique = all_opts["title"] + ("-%d" % cnt)
cnt += 1
all_opts["title"] = unique
if all_opts["title"] not in self.gadget_map:
g = make_requested_gadget(self, name, all_opts, self.dbstate)
if g:
self.gadget_map[all_opts["title"]] = g
self.frame_map[str(g.mainframe)] = g
else:
print "Can't make gadget of type '%s'." % name
else:
print "Ignoring duplicate named gadget '%s'." % all_opts["title"]
# put the gadgets where they go:
cnt = 0
for gadget in self.gadget_map.values():
# see if the user wants this in a particular location:
# and if there are that many columns
if gadget.column >= 0 and gadget.column < len(self.columns):
pos = gadget.column
else:
# else, spread them out:
pos = cnt % len(self.columns)
if gadget.state == "minimized": # starts max, change to min it
gadget.state = "maximized"
gadget.change_state(gadget) # minimize it
# to make as big as possible, set to True:
self.columns[pos].pack_start(gadget.mainframe, expand=gadget.expand)
# set height on gadget.scrolledwindow here:
gadget.scrolledwindow.set_size_request(-1, gadget.height)
cnt += 1
return frame
def drop_widget(self, source, context, x, y, timedata):
button = context.get_source_widget()
hbox = button.get_parent()
mainframe = hbox.get_parent()
rect = source.get_allocation()
sx, sy = rect.width, rect.height
# first, find column:
col = 0
for i in range(len(self.columns)):
if x < (sx/len(self.columns) * (i + 1)):
col = i
break
fromcol = mainframe.get_parent()
fromcol.remove(mainframe)
# now find where to insert in column:
stack = []
for gframe in self.columns[col]:
rect = gframe.get_allocation()
if y < (rect.y + 15): # starts at 0, this allows insert before
self.columns[col].remove(gframe)
stack.append(gframe)
maingadget = self.frame_map[str(mainframe)]
if maingadget.state == "maximized":
expand = maingadget.expand
else:
expand = False
self.columns[col].pack_start(mainframe, expand=expand)
for gframe in stack:
gadget = self.frame_map[str(gframe)]
if gadget.state == "maximized":
expand = gadget.expand
else:
expand = False
self.columns[col].pack_start(gframe, expand=expand)
return True
def define_actions(self):
"""
Defines the UIManager actions. Called by the ViewManager to set up the
View. The user typically defines self.action_list and
self.action_toggle_list in this function.
"""
return ''
def get_stock(self):
"""
Returns image associated with the view, which is used for the
icon for the button.
"""
return 'gtk-home'
def build_tree(self):
return

View File

@ -26,6 +26,7 @@ Package init for the DataView package
__author__ = "Don Allingham"
__revision__ = "$Revision: $"
from _MyGrampsView import MyGrampsView, register, Gadget
from _PersonView import PersonView
from _RelationView import RelationshipView
from _FamilyList import FamilyListView
@ -37,11 +38,14 @@ from _MediaView import MediaView
from _RepositoryView import RepositoryView
from _NoteView import NoteView
def get_views():
"""
Returns a list of PageView instances
"""
return [
try:
import Config
DATA_VIEWS = eval("["+Config.get(Config.DATA_VIEWS)+"]")
except:
# Fallback if bad config line, or if no Config system
print "Ignoring malformed 'data-views' entry"
DATA_VIEWS = [
#MyGrampsView,
PersonView,
RelationshipView,
FamilyListView,
@ -54,3 +58,9 @@ def get_views():
RepositoryView,
NoteView,
]
def get_views():
"""
Returns a list of PageView instances, in order
"""
return DATA_VIEWS

View File

@ -16202,4 +16202,175 @@ Very High</property>
</child>
</widget>
<widget class="GtkWindow" id="gvwin">
<property name="visible">True</property>
<property name="title" translatable="yes">window2</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkFrame" id="gvgadget">
<property name="border_width">10</property>
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<child>
<widget class="GtkScrolledWindow" id="gvscrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="gvtextview">
<property name="visible">True</property>
<property name="editable">False</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_WORD</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkHBox" id="hbox144">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="gvproperties">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<child>
<widget class="GtkImage" id="gvpropertiesimage">
<property name="visible">True</property>
<property name="stock">gtk-properties</property>
<property name="icon_size">4</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="gvstate">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<child>
<widget class="GtkImage" id="gvstateimage">
<property name="visible">True</property>
<property name="stock">gtk-remove</property>
<property name="icon_size">4</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="gvclose">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<child>
<widget class="GtkImage" id="gvcloseimage">
<property name="visible">True</property>
<property name="stock">gtk-close</property>
<property name="icon_size">4</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="gvtitle">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;&lt;i&gt;Gramplet&lt;/i&gt;&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="xpad">7</property>
<property name="ypad">9</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>

View File

@ -0,0 +1,262 @@
from DataViews import register, Gadget
from BasicUtils import name_displayer
import DateHandler
import gen.lib
#
# Hello World, in Gramps Gadgets
#
# First, you need a function or class that takes a single argument
# a GuiGadget:
def init(gui):
gui.set_text("Hello world!")
# In this function, you can do some things to update the gadget,
# like set text of the main scroll window.
# Then, you need to register the gadget:
register(type="gadget", # case in-senstitive keyword "gadget"
name="Hello World Gadget", # gadget name, unique among gadgets
height = 20,
content = init, # function/class; takes state and container
title="Sample Gadget", # default title, user changeable, unique
)
# There are a number of arguments that you can provide, including:
# name, height, content, title, expand, minimized
# Hereare a couple of other examples, with their register lines at the
# bottom:
def make_family_content(gui):
gui.set_text("Families:")
def make_event_content(gui):
gui.set_text("Events:")
# Here is a Gadget object. It has a number of methods possibilities:
# init- run once, on construction
# db_changed- run when db-changed is triggered
# main- run once per db, main process (for fast code)
# background- run once per db, main process (for slow code)
# active_changed- run when active-changed is triggered
# You can also call update to run main and background
class LogGadget(Gadget):
def db_changed(self):
self.dbstate.connect('person-add', self.log_person_add)
self.dbstate.connect('person-delete', self.log_person_delete)
self.dbstate.connect('person-update', self.log_person_update)
self.dbstate.connect('family-add', self.log_family_add)
self.dbstate.connect('family-delete', self.log_family_delete)
self.dbstate.connect('family-update', self.log_family_update)
def active_changed(self, handle):
self.log_active_changed(handle)
def init(self):
self.set_text("Log for this Session\n--------------------\n")
def log_person_add(self, handles):
self.append_text("person-add: ")
self.get_person(handles)
def log_person_delete(self, handles):
self.append_text("person-delete: ")
self.get_person(handles)
def log_person_update(self, handles):
self.append_text("person-update: ")
self.get_person(handles)
def log_family_add(self, handles):
self.append_text("family-add: %s" % handles)
def log_family_delete(self, handles):
self.append_text("family-delete: %s" % handles)
def log_family_update(self, handles):
self.append_text("family-update: %s" % handles)
def log_active_changed(self, handles):
self.append_text("active-changed: ")
self.get_person([handles])
def get_person(self, handles):
for person_handle in handles:
person = self.dbstate.get_person_from_handle(person_handle)
if person:
self.append_text(name_displayer.display(person))
else:
self.append_text(person_handle)
self.append_text("\n")
class TopSurnamesGadget(Gadget):
def main(self):
self.set_text("Processing...\n")
def background(self):
people = self.dbstate.get_person_handles(sort_handles=False)
surnames = {}
cnt = 0
for person_handle in people:
person = self.dbstate.get_person_from_handle(person_handle)
if person:
surname = person.get_primary_name().get_surname().strip()
surnames[surname] = surnames.get(surname, 0) + 1
if cnt % 500 == 0:
yield True
cnt += 1
total_people = cnt
surname_sort = []
total = 0
cnt = 0
for surname in surnames:
surname_sort.append( (surnames[surname], surname) )
total += surnames[surname]
if cnt % 500 == 0:
yield True
cnt += 1
total_surnames = cnt
surname_sort.sort(lambda a,b: -cmp(a,b))
line = 0
### All done!
self.set_text("")
for (count, surname) in surname_sort:
self.append_text(" %s, %d%%\n" %
(surname, int((float(count)/total) * 100)))
line += 1
if line >= 10:
break
self.append_text("\nTotal unique surnames: %d\n" % total_surnames)
self.append_text("Total people: %d" % total_people)
class StatsGadget(Gadget):
def db_changed(self):
self.dbstate.connect('person-add', self.update)
self.dbstate.connect('person-delete', self.update)
self.dbstate.connect('family-add', self.update)
self.dbstate.connect('family-delete', self.update)
def background(self):
self.set_text("Processing...")
database = self.dbstate
personList = database.get_person_handles(sort_handles=False)
familyList = database.get_family_handles()
with_photos = 0
total_photos = 0
incomp_names = 0
disconnected = 0
missing_bday = 0
males = 0
females = 0
unknowns = 0
bytes = 0
namelist = []
notfound = []
pobjects = len(database.get_media_object_handles())
for photo_id in database.get_media_object_handles():
photo = database.get_object_from_handle(photo_id)
try:
bytes = bytes + posixpath.getsize(photo.get_path())
except:
notfound.append(photo.get_path())
cnt = 0
for person_handle in personList:
person = database.get_person_from_handle(person_handle)
if not person:
continue
length = len(person.get_media_list())
if length > 0:
with_photos = with_photos + 1
total_photos = total_photos + length
person = database.get_person_from_handle(person_handle)
name = person.get_primary_name()
if name.get_first_name() == "" or name.get_surname() == "":
incomp_names = incomp_names + 1
if (not person.get_main_parents_family_handle()) and (not len(person.get_family_handle_list())):
disconnected = disconnected + 1
birth_ref = person.get_birth_ref()
if birth_ref:
birth = database.get_event_from_handle(birth_ref.ref)
if not DateHandler.get_date(birth):
missing_bday = missing_bday + 1
else:
missing_bday = missing_bday + 1
if person.get_gender() == gen.lib.Person.FEMALE:
females = females + 1
elif person.get_gender() == gen.lib.Person.MALE:
males = males + 1
else:
unknowns += 1
if name.get_surname() not in namelist:
namelist.append(name.get_surname())
if cnt % 500 == 0:
yield True
cnt += 1
text = _("Individuals") + "\n"
text = text + "----------------------------\n"
text = text + "%s: %d\n" % (_("Number of individuals"),len(personList))
text = text + "%s: %d\n" % (_("Males"),males)
text = text + "%s: %d\n" % (_("Females"),females)
text = text + "%s: %d\n" % (_("Individuals with unknown gender"),unknowns)
text = text + "%s: %d\n" % (_("Individuals with incomplete names"),incomp_names)
text = text + "%s: %d\n" % (_("Individuals missing birth dates"),missing_bday)
text = text + "%s: %d\n" % (_("Disconnected individuals"),disconnected)
text = text + "\n%s\n" % _("Family Information")
text = text + "----------------------------\n"
text = text + "%s: %d\n" % (_("Number of families"),len(familyList))
text = text + "%s: %d\n" % (_("Unique surnames"),len(namelist))
text = text + "\n%s\n" % _("Media Objects")
text = text + "----------------------------\n"
text = text + "%s: %d\n" % (_("Individuals with media objects"),with_photos)
text = text + "%s: %d\n" % (_("Total number of media object references"),total_photos)
text = text + "%s: %d\n" % (_("Number of unique media objects"),pobjects)
text = text + "%s: %d %s\n" % (_("Total size of media objects"),bytes,\
_("bytes"))
if len(notfound) > 0:
text = text + "\n%s\n" % _("Missing Media Objects")
text = text + "----------------------------\n"
for p in notfound:
text = text + "%s\n" % p
self.set_text(text)
register(type="gadget",
name="Families Gadget",
height=300,
content = make_family_content,
title="Favorite Families",
)
register(type="gadget",
name="Events Gadget",
height=100,
content = make_event_content,
title="Favorite Events",
)
register(type="gadget",
name="Top Surnames Gadget",
height=230,
content = TopSurnamesGadget,
title="Top 10 Surnames",
)
register(type="gadget",
name="Stats Gadget",
height=230,
content = StatsGadget,
title="Stats",
)
register(type="gadget",
name="Log Gadget",
height=230,
content = LogGadget,
title="Session Log",
)