export module for PAF for PalmOS

svn: r432
This commit is contained in:
Jason Zedlitz 2001-09-27 07:31:48 +00:00
parent 17ac560c72
commit 73b291691c
2 changed files with 946 additions and 0 deletions

View File

@ -0,0 +1,620 @@
#
# WritePafPalm.py - export module to write pdb files for use with PAF for PalmOS
#
# Copyright (C) 2001 Jesper Zedlitz <jesper@zedlitz.de>
#
# 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
#
"Export to PAF for PalmOS"
from RelLib import *
import os
import string
import time
import const
import utils
import intl
_ = intl.gettext
from gtk import *
from gnome.ui import *
from libglade import *
import const
from latin_ansel import latin_to_ansel
from latin_utf8 import latin_to_utf8
cnvtxt = latin_to_ansel
database_name = "Untitled"
description = ""
topDialog = None
db = None
people_list = []
family_list = []
source_list = []
string_list = {}
number_of_records = 0
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def entire_database():
global people_list
global family_list
global source_list
people_list = db.getPersonMap().values()
family_list = db.getFamilyMap().values()
source_list = db.getSourceMap().values()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def active_person_descendants():
global people_list
global family_list
global source_list
people_list = []
family_list = []
source_list = []
descend(active_person)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def active_person_ancestors_and_descendants():
global people_list
global family_list
global source_list
people_list = []
family_list = []
source_list = []
descend(active_person)
ancestors(active_person)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def active_person_ancestors():
global people_list
global family_list
global source_list
people_list = []
family_list = []
source_list = []
ancestors(active_person)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def interconnected():
global people_list
global family_list
global source_list
people_list = []
family_list = []
source_list = []
walk(active_person)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def descend(person):
if person == None or person in people_list:
return
people_list.append(person)
add_persons_sources(person)
for family in person.getFamilyList():
add_familys_sources(family)
family_list.append(family)
father = family.getFather()
mother = family.getMother()
if father != None and father not in people_list:
people_list.append(father)
add_persons_sources(father)
if mother != None and mother not in people_list:
people_list.append(mother)
add_persons_sources(mother)
for child in family.getChildList():
descend(child)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ancestors(person):
if person == None or person in people_list:
return
people_list.append(person)
add_persons_sources(person)
family = person.getMainFamily()
if family == None or family in family_list:
return
add_familys_sources(family)
family_list.append(family)
ancestors(family.getMother())
ancestors(family.getFather())
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def walk(person):
if person == None or person in people_list:
return
people_list.append(person)
add_persons_sources(person)
families = person.getFamilyList()
families.append(person.getMainFamily())
for f in person.getAltFamilyList():
families.append(f[0])
for family in families:
if family == None or family in family_list:
continue
add_familys_sources(family)
family_list.append(family)
walk(family.getFather())
walk(family.getMother())
for child in family.getChildList():
walk(child)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def add_persons_sources(person):
elist = person.getEventList()[:]
elist.append(person.getBirth())
elist.append(person.getDeath())
for event in elist:
if private and event.getPrivacy():
continue
source_ref = event.getSourceRef()
if source_ref != None:
source_list.append(source_ref)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def add_familys_sources(family):
for event in family.getEventList():
if private and event.getPrivacy():
continue
source_ref = event.getSourceRef()
if source_ref != None:
source_list.append(source_ref)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def sortById(first,second):
fid = first.getId()
sid = second.getId()
if fid == sid:
return 0
elif fid < sid:
return -1
else:
return 1
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def sortByName(first,second):
fsn = first.getPrimaryName().getSurname()
ssn = second.getPrimaryName().getSurname()
if fsn == ssn:
ffn = first.getPrimaryName().getFirstName()
sfn = second.getPrimaryName().getFirstName()
if ffn == sfn:
return 0
elif ffn < sfn:
return -1
else:
return 1
elif fsn < ssn:
return -1
else:
return 1
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def probably_alive(person):
if person == None:
return 1
if restrict == 0:
return 0
death = person.getDeath()
birth = person.getBirth()
if death.getDate() != "":
return 0
if birth.getDate() != "":
year = birth.getDateObj().getYear()
time_struct = time.localtime(time.time())
current_year = time_struct[0]
if year != -1 and current_year - year > 110:
return 0
return 1
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_year( event ):
year = 0
if event != None:
dateObj = event.getDateObj()
if dateObj != None:
year = dateObj.getYear()
if year < 0:
year = 0
return year
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_place( event ):
place = ""
if event != None:
place = event.getPlaceName()
if place == "":
place = " "
return place
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_date( event ):
date = ""
if event != None:
date = event.getDate()
if date == "":
date = " "
return date
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def text_ref( s ):
global string_list
global number_of_records
text_offset = string_list[s]
data = chr( (number_of_records-1)/256 ) + chr( (number_of_records-1) % 256 )
data = data + chr( text_offset/256 ) + chr( text_offset % 256 )
return data
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def write_16_bit( i ):
return chr( i / 256 ) + chr ( i % 256 )
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def write_32_bit( i ):
return write_16_bit( i / 65536 ) + write_16_bit( i % 65536 )
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def exportData(database, filename):
global database_name
global description
global string_list
global number_of_records
g = open(filename,"wb")
number_of_records = len(people_list)+len(family_list)+1
g.write("%s-PAFg" % (database_name))
g.write("\0"*( 27-len(database_name) ) )
g.write("\0\x08\0\4")
g.write("\xb7\xd7\x66\xf1") # creation time in seconds since 1904-01-01
g.write("\xb7\xd7\x66\xf1") # modification time
g.write("\0\0\0\0") # backup time
g.write("\0\0\0\0\0\0")
offset_infoblock = 80 + 8 * number_of_records
g.write( write_16_bit( offset_infoblock ) )
g.write("\0\0\0\0GdatPAFg\0\0\0\0\0\0\0\0")
g.write( write_16_bit( number_of_records ) )
# collect all string contained in the data
for person in people_list:
string_list[person.getPrimaryName().getFirstName()] = 0
string_list[person.getPrimaryName().getSurname()] = 0
string_list[ get_place( person.getBirth() ) ] = 0
string_list[ get_date( person.getBirth() ) ] = 0
string_list[ get_place( person.getDeath() ) ] = 0
string_list[ get_date( person.getDeath() ) ] = 0
string_list[ person.getNote() ] = 0
for family in family_list:
string_list[ get_place( family.getMarriage() ) ] = 0
string_list[ get_date( family.getMarriage() ) ] = 0
strings = string_list.keys()
strings.sort()
offset = 0
text_block = ""
for s in strings:
text_block = text_block + s + "\0"
string_list[s] = offset
offset = offset + len(s) +1
id_to_record = {}
fid_to_record = {}
record_nr = len(people_list)
for family in family_list:
fid_to_record[ family.getId() ] = record_nr
record_nr = record_nr +1
next_pointer = offset_infoblock + 512
person_data = []
people_list.sort(sortByName)
record_nr = 0
for person in people_list:
id_to_record[ person.getId() ] = record_nr
record_nr = record_nr +1
data = "\0\0"
if person.getNote() != "":
data = data + "\x10"
else:
data = data + "\0"
data = data + "\x0f"
data = data + write_16_bit( int(person.getId()[1:])+1 )
data = data + write_16_bit( get_year(person.getBirth()) )
data = data + write_16_bit( get_year(person.getDeath()) )
if person.getMainFamily() != None:
data = data + write_16_bit( fid_to_record[person.getMainFamily().getId()] )
else:
data = data + "\xff\xff"
families = person.getFamilyList()
if len(families) > 0:
data = data + "\1"
else:
data = data + "\0"
if person.getGender() == Person.female:
data = data + "\1"
else:
data = data + "\2"
if len(families) > 0:
data = data + write_16_bit( fid_to_record[ families[0].getId() ] )
data = data + text_ref( person.getPrimaryName().getSurname() )
data = data + text_ref( person.getPrimaryName().getFirstName() )
if get_year(person.getBirth()) > 0 :
data = data + text_ref( get_date(person.getBirth()) )
data = data + text_ref( get_place(person.getBirth()) )
if get_year(person.getDeath()) > 0 :
data = data + text_ref( get_date(person.getDeath()) )
data = data + text_ref( get_place(person.getDeath()) )
if person.getNote() != "":
data = data + text_ref( person.getNote() )
person_data.append(data)
# pointer to record
g.write( write_32_bit( next_pointer ) )
g.write("\0\0\0\0")
next_pointer = next_pointer + len(data)
family_data = []
for family in family_list:
data = "\0\1"
father = family.getFather()
mother = family.getMother()
if father != None:
data = data + write_16_bit( id_to_record[father.getId()] )
else:
data = data + "\xff\xff"
if mother != None:
data = data + write_16_bit( id_to_record[mother.getId()] )
else:
data = data + "\xff\xff"
data = data + write_16_bit( get_year( family.getMarriage() ) )
data = data + "\3"
children = family.getChildList()
data = data + chr( len(children) )
for child in children:
data = data + write_16_bit( id_to_record[child.getId()] )
data = data + text_ref( get_date(family.getMarriage()) )
data = data + text_ref( get_place(family.getMarriage()) )
family_data.append(data)
# pointer to record
g.write( write_32_bit( next_pointer ) )
g.write("\0\0\0\0")
next_pointer = next_pointer + len(data)
# pointer to textblock
g.write( write_32_bit( next_pointer ) )
g.write("\0\0\0\0\0\0")
infoblock = "\xb7\xd7\x66\xf1\0\0\0\0\0\0\0\0\0\0\0\0"
infoblock = infoblock + "\0\0\0\0\0\0\0\0\0\1\0\1\0\1\0\1"
infoblock = infoblock + "\0\1\0\1\0\1\0\1\0\1\0\1\0\1\0\1"
infoblock = infoblock + "\0\1\0\1\0\1\0\1\0\x03" \
+ write_16_bit( len(people_list) ) \
+ write_16_bit( len(family_list) )
infoblock = infoblock + "\0\1\0\0\0"
infoblock = infoblock + description
# owner = database.getResearcher()
# if owner.getName() != "":
infoblock = infoblock + ( "\0"*(512- len(infoblock)) )
g.write(infoblock)
for data in person_data:
g.write(data)
for data in family_data:
g.write(data)
g.write(text_block)
g.close()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
global db
global database_name
global description
global topDialog
global restrict
global private
database_name = topDialog.get_widget("dbname").get_text()
description = topDialog.get_widget("description").get_text()
restrict = topDialog.get_widget("restrict").get_active()
private = topDialog.get_widget("private").get_active()
filter_obj = topDialog.get_widget("filter").get_menu().get_active()
filter = filter_obj.get_data("filter")
name = topDialog.get_widget("filename").get_text()
filter()
exportData(db,name)
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def writeData(database,person):
global db
global topDialog
global active_person
db = database
active_person = person
base = os.path.dirname(__file__)
glade_file = base + os.sep + "pafexport.glade"
dic = {
"destroy_passed_object" : utils.destroy_passed_object,
"on_ok_clicked" : on_ok_clicked
}
topDialog = GladeXML(glade_file,"pafExport")
topDialog.signal_autoconnect(dic)
filter_obj = topDialog.get_widget("filter")
myMenu = GtkMenu()
menuitem = GtkMenuItem(_("Entire Database"))
myMenu.append(menuitem)
menuitem.set_data("filter",entire_database)
menuitem.show()
name = active_person.getPrimaryName().getRegularName()
menuitem = GtkMenuItem(_("Ancestors of %s") % name)
myMenu.append(menuitem)
menuitem.set_data("filter",active_person_ancestors)
menuitem.show()
menuitem = GtkMenuItem(_("Descendants of %s") % name)
myMenu.append(menuitem)
menuitem.set_data("filter",active_person_descendants)
menuitem.show()
menuitem = GtkMenuItem(_("Ancestors and Descendants of %s") % name)
myMenu.append(menuitem)
menuitem.set_data("filter",active_person_ancestors_and_descendants)
menuitem.show()
menuitem = GtkMenuItem(_("People somehow connected to %s") % name)
myMenu.append(menuitem)
menuitem.set_data("filter",interconnected)
menuitem.show()
filter_obj.set_menu(myMenu)
topDialog.get_widget("pafExport").show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
from Plugins import register_export
register_export(writeData,_("Export to PAF for PalmOS"))

View File

@ -0,0 +1,326 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>PAF for PalmOS Export</name>
<program_name>pafexport</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GnomeDialog</class>
<name>pafExport</name>
<title>Export PAF for PalmOS file</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_CENTER</position>
<modal>True</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>False</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox1</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area1</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>ok</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_ok_clicked</handler>
<object>pafExport</object>
<last_modification_time>Thu, 30 Nov 2000 20:58:29 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>cancel</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>pafExport</object>
<last_modification_time>Thu, 30 Nov 2000 19:30:56 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>exportTitle</name>
<label>PAF for PalmOS Export</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator1</name>
<child>
<padding>10</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GnomeFileEntry</class>
<name>fileentry1</name>
<width>350</width>
<history_id>pafExport</history_id>
<max_saved>10</max_saved>
<title>Export PAF for PalmOS</title>
<directory>False</directory>
<modal>True</modal>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkEntry</class>
<child_name>GnomeEntry:entry</child_name>
<name>filename</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
</widget>
</widget>
<widget>
<class>GtkFrame</class>
<name>frame2</name>
<border_width>5</border_width>
<label>Filter</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkOptionMenu</class>
<name>filter</name>
<border_width>5</border_width>
<can_focus>True</can_focus>
<items>
</items>
<initial_choice>0</initial_choice>
</widget>
</widget>
<widget>
<class>GtkFrame</class>
<name>frame3</name>
<border_width>5</border_width>
<label>Information</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkVBox</class>
<name>vbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label1</name>
<label>Database name: </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>5</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>dbname</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>20</text_max_length>
<text></text>
<child>
<padding>5</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<name>label2</name>
<label>Description</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>3</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>description</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkFrame</class>
<name>frame1</name>
<border_width>5</border_width>
<label>Options</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkVBox</class>
<name>vbox3</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkCheckButton</class>
<name>private</name>
<border_width>3</border_width>
<can_focus>True</can_focus>
<label>Do not include records marked &quot;Private&quot;</label>
<active>True</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>restrict</name>
<border_width>3</border_width>
<can_focus>True</can_focus>
<label>Restrict data on living people</label>
<active>True</active>
<draw_indicator>True</draw_indicator>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>