From 915d07a518a42cc87bd01b446614c359e963a6e8 Mon Sep 17 00:00:00 2001 From: Jason Zedlitz Date: Thu, 27 Sep 2001 07:31:48 +0000 Subject: [PATCH] export module for PAF for PalmOS svn: r432 --- src/plugins/WritePafPalm.py | 620 ++++++++++++++++++++++++++++++++++++ src/plugins/pafexport.glade | 326 +++++++++++++++++++ 2 files changed, 946 insertions(+) create mode 100644 src/plugins/WritePafPalm.py create mode 100644 src/plugins/pafexport.glade diff --git a/src/plugins/WritePafPalm.py b/src/plugins/WritePafPalm.py new file mode 100644 index 000000000..165726a9e --- /dev/null +++ b/src/plugins/WritePafPalm.py @@ -0,0 +1,620 @@ +# +# WritePafPalm.py - export module to write pdb files for use with PAF for PalmOS +# +# Copyright (C) 2001 Jesper Zedlitz +# +# 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")) diff --git a/src/plugins/pafexport.glade b/src/plugins/pafexport.glade new file mode 100644 index 000000000..ee6b24729 --- /dev/null +++ b/src/plugins/pafexport.glade @@ -0,0 +1,326 @@ + + + + + PAF for PalmOS Export + pafexport + + src + pixmaps + C + True + True + + + + GnomeDialog + pafExport + Export PAF for PalmOS file + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + True + False + False + False + False + False + + + GtkVBox + GnomeDialog:vbox + dialog-vbox1 + False + 8 + + 4 + True + True + + + + GtkHButtonBox + GnomeDialog:action_area + dialog-action_area1 + GTK_BUTTONBOX_END + 8 + 85 + 27 + 7 + 0 + + 0 + False + True + GTK_PACK_END + + + + GtkButton + ok + True + True + + clicked + on_ok_clicked + pafExport + Thu, 30 Nov 2000 20:58:29 GMT + + GNOME_STOCK_BUTTON_OK + + + + GtkButton + cancel + True + True + + clicked + destroy_passed_object + pafExport + Thu, 30 Nov 2000 19:30:56 GMT + + GNOME_STOCK_BUTTON_CANCEL + + + + + GtkVBox + vbox1 + False + 0 + + 0 + True + True + + + + GtkLabel + exportTitle + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 0 + False + False + + + + + GtkHSeparator + hseparator1 + + 10 + True + True + + + + + GnomeFileEntry + fileentry1 + 350 + pafExport + 10 + Export PAF for PalmOS + False + True + + 5 + False + False + + + + GtkEntry + GnomeEntry:entry + filename + True + True + True + 0 + + + + + + GtkFrame + frame2 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkOptionMenu + filter + 5 + True + + + 0 + + + + + GtkFrame + frame3 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox2 + False + 0 + + + GtkHBox + hbox1 + False + 0 + + 0 + False + False + + + + GtkLabel + label1 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 5 + 0 + + 0 + False + False + + + + + GtkEntry + dbname + True + True + True + 20 + + + 5 + True + True + + + + + + GtkLabel + label2 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 3 + + 0 + False + False + + + + + GtkEntry + description + True + True + True + 0 + + + 0 + False + False + + + + + + + GtkFrame + frame1 + 5 + + 0 + GTK_SHADOW_ETCHED_IN + + 0 + True + True + + + + GtkVBox + vbox3 + False + 0 + + + GtkCheckButton + private + 3 + True + + True + True + + 0 + False + False + + + + + GtkCheckButton + restrict + 3 + True + + True + True + + 0 + False + False + + + + + + + + +