From bad37fc4296fa55400c9e268ee469712ffb6ae71 Mon Sep 17 00:00:00 2001 From: Don Allingham Date: Wed, 30 May 2001 04:24:27 +0000 Subject: [PATCH] Support for notes and sources in more data elements, new GEDCOM parser svn: r66 --- src/Config.py | 70 ++ src/Date.py | 18 + src/EditPerson.glade | 385 ++++++-- src/EditPerson.py | 41 +- src/GrampsParser.py | 117 ++- src/PaperMenu.py | 8 +- src/ReadXML.py | 7 +- src/RelLib.py | 142 ++- src/Sources.py | 259 ++---- src/WriteXML.py | 55 +- src/config.glade | 416 ++++++--- src/const.py | 6 +- src/gramps.glade | 911 ++++++++++--------- src/gramps_main.py | 155 +++- src/latin_utf8.py | 24 +- src/plugins/IndivSummary.py | 12 +- src/plugins/ReadGedcom.py | 1553 ++++++++++++++++++++++----------- src/plugins/WriteGedcom.py | 14 +- src/plugins/familygroup.glade | 20 + 19 files changed, 2784 insertions(+), 1429 deletions(-) diff --git a/src/Config.py b/src/Config.py index 0ed6aef9d..232e640f7 100644 --- a/src/Config.py +++ b/src/Config.py @@ -29,6 +29,8 @@ import string import re import os +import PaperMenu + #------------------------------------------------------------------------- # # GTK/Gnome modules @@ -91,6 +93,9 @@ lastfile = None nameof = utils.normal_name display_attr = 0 attr_name = "" +status_bar = 0 +paper_preference = None +output_preference = None #------------------------------------------------------------------------- # @@ -139,10 +144,14 @@ def loadConfig(call): global _druid global _name_format global _callback + global paper_preference + global output_preference + global status_bar _callback = call lastfile = gnome.config.get_string("/gramps/data/LastFile") usetabs = gnome.config.get_bool("/gramps/config/UseTabs") + status_bar = gnome.config.get_int("/gramps/config/StatusBar") display_attr = gnome.config.get_bool("/gramps/config/DisplayAttr") attr_name = gnome.config.get_string("/gramps/config/DisplayAttrName") @@ -150,6 +159,8 @@ def loadConfig(call): autoload = gnome.config.get_bool("/gramps/config/autoLoad") dateFormat = gnome.config.get_int("/gramps/config/dateFormat") dateEntry = gnome.config.get_int("/gramps/config/dateEntry") + paper_preference = gnome.config.get_string("/gramps/config/paperPreference") + output_preference = gnome.config.get_string("/gramps/config/outputPreference") _name_format = gnome.config.get_int("/gramps/config/nameFormat") name = gnome.config.get_string("/gramps/researcher/name") @@ -170,6 +181,12 @@ def loadConfig(call): ListColors.evenfg = get_config_color(EVENFGCOLOR,(0,0,0)) ListColors.evenbg = get_config_color(EVENBGCOLOR,(0xffff,0xffff,0xffff)) + if paper_preference == None: + paper_preference = "Letter" + + if output_preference == None: + output_preference = "OpenOffice" + if display_attr == None: display_attr = 0 @@ -180,6 +197,8 @@ def loadConfig(call): autoload = 1 if usetabs == None: usetabs = 0 + if status_bar == None: + status_bar = 0 if hide_altnames == None: hide_altnames = 0 if dateFormat == None: @@ -265,6 +284,7 @@ def on_propertybox_apply(obj,page): global nameof global owner global usetabs + global status_bar global display_attr global attr_name global hide_altnames @@ -277,10 +297,25 @@ def on_propertybox_apply(obj,page): attr_name = string.strip(prefsTop.get_widget("attr_name").get_text()) usetabs = prefsTop.get_widget("usetabs").get_active() hide_altnames = prefsTop.get_widget("display_altnames").get_active() + paper_obj = prefsTop.get_widget("paper_size").get_menu().get_active() + output_obj = prefsTop.get_widget("output_format").get_menu().get_active() + + if prefsTop.get_widget("stat1").get_active(): + status_bar = 0 + elif prefsTop.get_widget("stat2").get_active(): + status_bar = 1 + else: + status_bar = 2 + + paper_preference = paper_obj.get_data("d") + output_preference = output_obj.get_data("d") gnome.config.set_bool("/gramps/config/UseTabs",usetabs) + gnome.config.set_int("/gramps/config/StatusBar",status_bar) gnome.config.set_bool("/gramps/config/DisplayAttr",display_attr) gnome.config.set_string("/gramps/config/DisplayAttrName",attr_name) + gnome.config.set_string("/gramps/config/paperPreference",paper_preference) + gnome.config.set_string("/gramps/config/outputPreference",output_preference) gnome.config.set_bool("/gramps/config/autoLoad",autoload) gnome.config.set_bool("/gramps/config/DisplayAltNames",hide_altnames) @@ -418,6 +453,41 @@ def display_preferences_box(): display_altnames.set_active(hide_altnames) + paper_obj = prefsTop.get_widget("paper_size") + menu = GtkMenu() + choice = 0 + for index in range(0,len(PaperMenu.paper_sizes)): + name = PaperMenu.paper_sizes[index].get_name() + if name == paper_preference: + choice = index + item = GtkMenuItem(name) + item.set_data("o",pbox) + item.set_data("d",name) + item.connect("activate", on_format_toggled) + item.show() + menu.append(item) + menu.set_active(choice) + paper_obj.set_menu(menu) + + output_obj = prefsTop.get_widget("output_format") + menu = GtkMenu() + choice = 0 + + choice = 0 + index = 0 + for name in const.output_formats: + if name == output_preference: + choice = index + item = GtkMenuItem(name) + item.set_data("o",pbox) + item.set_data("d",name) + item.connect("activate", on_format_toggled) + item.show() + menu.append(item) + index = index + 1 + menu.set_active(choice) + output_obj.set_menu(menu) + date_option = prefsTop.get_widget("date_format") date_menu = GtkMenu() for index in range(0,len(_date_format_list)): diff --git a/src/Date.py b/src/Date.py index 391c59266..4109bbff0 100644 --- a/src/Date.py +++ b/src/Date.py @@ -61,6 +61,24 @@ class Date: def get_stop_date(self): return self.stop + def getYear(self): + return self.get_start_date().getYear() + + def getMonth(self): + return self.get_start_date().getMonth() + + def getDay(self): + return self.get_start_date().getDay() + + def getStopYear(self): + return self.get_stop_date().getYear() + + def getStopMonth(self): + return self.get_stop_date().getMonth() + + def getStopDay(self): + return self.get_stop_date().getDay() + #-------------------------------------------------------------------- # # diff --git a/src/EditPerson.glade b/src/EditPerson.glade index e1f74299b..db3272f70 100644 --- a/src/EditPerson.glade +++ b/src/EditPerson.glade @@ -1261,30 +1261,6 @@ - - GtkEntry - eventDate - True - True - True - 0 - - - 1 - 2 - 1 - 2 - 3 - 3 - True - False - False - False - True - False - - - GtkLabel label105 @@ -1468,6 +1444,61 @@ + + + GtkHBox + hbox19 + False + 0 + + 1 + 2 + 1 + 2 + 3 + 3 + False + False + False + False + True + True + + + + GtkEntry + eventDate + True + True + True + 0 + + + 0 + True + True + + + + + GtkButton + edit_note + True + + clicked + on_event_note_clicked + eventList + Tue, 29 May 2001 15:07:23 GMT + + + GTK_RELIEF_NORMAL + + 4 + False + False + + + @@ -1702,30 +1733,6 @@ - - GtkEntry - attr_value - True - True - True - 0 - - - 1 - 2 - 1 - 2 - 3 - 3 - True - False - False - False - True - False - - - GtkHBox hbox14 @@ -1776,7 +1783,6 @@ GtkButton button95 - False Choose source information True @@ -1794,6 +1800,61 @@ + + + GtkHBox + hbox20 + False + 0 + + 1 + 2 + 1 + 2 + 3 + 3 + True + False + False + False + True + True + + + + GtkEntry + attr_value + True + True + True + 0 + + + 0 + True + True + + + + + GtkButton + button97 + True + + clicked + on_event_note_clicked + attr_list + Tue, 29 May 2001 15:26:54 GMT + + + GTK_RELIEF_NORMAL + + 5 + False + False + + + @@ -2014,30 +2075,6 @@ - - GtkEntry - street - True - True - True - 0 - - - 1 - 2 - 1 - 2 - 3 - 3 - True - False - False - False - True - False - - - GtkLabel label142 @@ -2128,7 +2165,6 @@ GtkButton button91 - False Choose source information True @@ -2140,7 +2176,7 @@ GTK_RELIEF_NORMAL - 4 + 5 False False @@ -2282,6 +2318,61 @@ + + + GtkHBox + hbox21 + False + 0 + + 1 + 2 + 1 + 2 + 3 + 3 + True + False + False + False + True + True + + + + GtkEntry + street + True + True + True + 0 + + + 0 + True + True + + + + + GtkButton + button98 + True + + clicked + on_event_note_clicked + addr_list + Tue, 29 May 2001 15:27:27 GMT + + + GTK_RELIEF_NORMAL + + 5 + False + False + + + @@ -2937,4 +3028,148 @@ + + GtkDialog + editnote + Gramps - Edit Note + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + True + False + + + GtkVBox + Dialog:vbox + dialog-vbox1 + False + 0 + + + GtkHBox + Dialog:action_area + dialog-action_area1 + 10 + True + 5 + + 0 + False + True + GTK_PACK_END + + + + GtkHButtonBox + hbuttonbox18 + GTK_BUTTONBOX_END + 30 + 85 + 27 + 7 + 0 + + 0 + True + True + + + + GtkButton + button99 + True + True + + clicked + on_save_note_clicked + editnote + Tue, 29 May 2001 15:06:53 GMT + + GNOME_STOCK_BUTTON_OK + GTK_RELIEF_NORMAL + + + + GtkButton + button100 + True + True + + clicked + destroy_passed_object + editnote + Tue, 29 May 2001 15:06:38 GMT + + GNOME_STOCK_BUTTON_CANCEL + GTK_RELIEF_NORMAL + + + + + + GtkVBox + vbox29 + False + 0 + + 0 + True + True + + + + GtkLabel + label153 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + 10 + False + False + + + + + GtkHSeparator + hseparator1 + + 5 + False + True + + + + + GtkScrolledWindow + scrolledwindow21 + 450 + 300 + GTK_POLICY_NEVER + GTK_POLICY_ALWAYS + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + 0 + True + True + + + + GtkText + notetext + True + True + + + + + + + diff --git a/src/EditPerson.py b/src/EditPerson.py index 4ceb55e2d..c5f2072bd 100644 --- a/src/EditPerson.py +++ b/src/EditPerson.py @@ -154,6 +154,7 @@ class EditPerson: "on_photolist_button_press_event" : on_photolist_button_press_event, "on_addphoto_clicked" : on_add_photo_clicked, "on_deletephoto_clicked" : on_delete_photo_clicked, + "on_event_note_clicked" : on_event_note_clicked, "on_showsource_clicked" : on_showsource_clicked, "on_applyPerson_clicked" : on_apply_person_clicked }) @@ -261,7 +262,7 @@ class EditPerson: current_row = self.name_list.get_data(INDEX) - if self.name_index >= 0: + if self.name_index > 0: if current_row <= 0: current_row = 0 elif self.name_index <= current_row: @@ -288,7 +289,7 @@ class EditPerson: current_row = self.web_list.get_data(INDEX) - if self.web_index >= 0: + if self.web_index > 0: if current_row <= 0: current_row = 0 elif self.web_index <= current_row: @@ -315,7 +316,7 @@ class EditPerson: current_row = self.attr_list.get_data(INDEX) - if self.attr_index >= 0: + if self.attr_index > 0: if current_row <= 0: current_row = 0 elif self.attr_index <= current_row: @@ -344,7 +345,7 @@ class EditPerson: current_row = self.address_list.get_data(INDEX) - if self.address_index >= 0: + if self.address_index > 0: if current_row <= 0: current_row = 0 elif self.address_index <= current_row: @@ -1076,6 +1077,38 @@ def on_savephoto_clicked(obj): utils.modified() utils.destroy_passed_object(obj) + +def on_save_note_clicked(obj): + textbox = obj.get_data("w") + data = obj.get_data("n") + + text = textbox.get_chars(0,-1) + if text != data.getNote(): + data.setNote(text) + utils.modified() + + utils.destroy_passed_object(obj) + +def on_event_note_clicked(obj): + row = obj.get_data(INDEX) + data = obj.get_row_data(row) + edit_person_obj = obj.get_data(EDITPERSON) + if row >= 0: + editnote = libglade.GladeXML(const.editPersonFile,"editnote") + textobj = editnote.get_widget("notetext") + en_obj = editnote.get_widget("editnote") + en_obj.set_data("n",data) + en_obj.set_data("w",textobj) + + textobj.set_point(0) + textobj.insert_defaults(data.getNote()) + textobj.set_word_wrap(1) + + editnote.signal_autoconnect({ + "on_save_note_clicked" : on_save_note_clicked, + "destroy_passed_object" : utils.destroy_passed_object + }) + #------------------------------------------------------------------------- # # diff --git a/src/GrampsParser.py b/src/GrampsParser.py index 816aa9d4a..9e0b14d60 100644 --- a/src/GrampsParser.py +++ b/src/GrampsParser.py @@ -70,19 +70,24 @@ class GrampsParser(handler.ContentHandler): self.note_list = [] self.in_note = 0 + self.in_attribute = 0 + self.in_old_attr = 0 self.in_stext = 0 self.in_scomments = 0 self.in_people = 0 self.db = database self.base = base self.in_family = 0 - self.in_sources = 0 + self.in_source_ref = 0 + self.in_source = 0 + self.in_address = 0 + self.in_event = 0 self.person = None self.family = None + self.address = None self.source = None - self.sourceRef = None + self.source_ref = None self.is_import = is_import - self.in_address = 0 self.resname = "" self.resaddr = "" @@ -141,15 +146,21 @@ class GrampsParser(handler.ContentHandler): def start_event(self,attrs): self.event = Event() self.event_type = string.capwords(attrs["type"]) - + self.in_event = 1 + #--------------------------------------------------------------------- # # # #--------------------------------------------------------------------- def start_attribute(self,attrs): + self.in_attribute = 1 self.attribute = Attribute() - self.attribute.setType(string.capwords(attrs["type"])) + if attrs.has_key('type'): + self.in_old_attr = 1 + self.attribute.setType(string.capwords(attrs["type"])) + else: + self.in_old_attr = 0 self.person.addAttribute(self.attribute) #--------------------------------------------------------------------- @@ -194,9 +205,9 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def start_people(self,attrs): - self.in_family = 0 - self.in_people = 1 - self.in_sources = 0 + self.in_family = 0 + self.in_people = 1 + self.in_source = 0 if self.is_import == 0 and attrs.has_key("default"): self.tempDefault = int(attrs["default"]) @@ -322,9 +333,9 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def start_families(self,attrs): - self.in_family = 1 - self.in_people = 0 - self.in_sources = 0 + self.in_family = 1 + self.in_people = 0 + self.in_source = 0 #--------------------------------------------------------------------- # @@ -332,9 +343,9 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def start_sources(self,attrs): - self.in_family = 0 - self.in_people = 0 - self.in_sources = 1 + self.in_family = 0 + self.in_people = 0 + self.in_source = 1 #--------------------------------------------------------------------- # @@ -342,13 +353,21 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def start_sourceref(self,attrs): - self.source = Source() + self.source_ref = SourceRef() + self.in_source_ref = 1 if self.is_import: - self.sourceRef = self.db.findSource(attrs["ref"],self.smap) + self.source = self.db.findSource(attrs["ref"],self.smap) else: - self.sourceRef = self.db.findSourceNoMap(attrs["ref"]) - self.source.setBase(self.sourceRef) - self.event.setSource(self.source) + self.source = self.db.findSourceNoMap(attrs["ref"]) + self.source_ref.setBase(self.source) + if self.in_address: + self.address.setSourceRef(self.source_ref) + elif self.in_event: + self.event.setSourceRef(self.source_ref) + elif self.in_attribute: + self.attribute.setSourceRef(self.source_ref) + else: + print "Sorry, I'm lost" #--------------------------------------------------------------------- # @@ -357,9 +376,9 @@ class GrampsParser(handler.ContentHandler): #--------------------------------------------------------------------- def start_source(self,attrs): if self.is_import: - self.sourceRef = self.db.findSource(attrs["id"],self.smap) + self.source = self.db.findSource(attrs["id"],self.smap) else: - self.sourceRef = self.db.findSourceNoMap(attrs["id"]) + self.source = self.db.findSourceNoMap(attrs["id"]) #--------------------------------------------------------------------- # @@ -397,6 +416,25 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_attribute(self,tag): + self.in_attribute = 0 + if self.in_old_attr: + self.attribute.setValue(tag) + self.in_old_attr = 0 + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def stop_attr_type(self,tag): + self.attribute.setType(tag) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def stop_attr_value(self,tag): self.attribute.setValue(tag) #--------------------------------------------------------------------- @@ -413,6 +451,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_event(self,tag): + self.in_event = 0 self.event.setName(self.event_type) if self.event_type == "Birth": @@ -497,7 +536,15 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_stitle(self,tag): - self.sourceRef.setTitle(tag) + self.source.setTitle(tag) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def stop_sourceref(self,tag): + self.in_source_ref = 0 #--------------------------------------------------------------------- # @@ -505,7 +552,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_sauthor(self,tag): - self.sourceRef.setAuthor(tag) + self.source.setAuthor(tag) #--------------------------------------------------------------------- # @@ -515,7 +562,7 @@ class GrampsParser(handler.ContentHandler): def stop_sdate(self,tag): date = Date() date.quick_set(tag) - self.source.setDate(date) + self.source_ref.setDate(date) def stop_street(self,tag): self.address.setStreet(tag) @@ -538,7 +585,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_spage(self,tag): - self.source.setPage(tag) + self.source_ref.setPage(tag) #--------------------------------------------------------------------- # @@ -546,7 +593,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_spubinfo(self,tag): - self.sourceRef.setPubInfo(tag) + self.source.setPubInfo(tag) #--------------------------------------------------------------------- # @@ -554,7 +601,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_scallno(self,tag): - self.sourceRef.setCallNumber(tag) + self.source.setCallNumber(tag) #--------------------------------------------------------------------- # @@ -562,7 +609,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_stext(self,tag): - self.source.setText(fix_spaces(tag)) + self.source_ref.setText(fix_spaces(tag)) #--------------------------------------------------------------------- # @@ -570,7 +617,7 @@ class GrampsParser(handler.ContentHandler): # #--------------------------------------------------------------------- def stop_scomments(self,tag): - self.source.setComments(fix_spaces(self.scomments_list)) + self.source_ref.setComments(fix_spaces(self.scomments_list)) #--------------------------------------------------------------------- # @@ -611,7 +658,13 @@ class GrampsParser(handler.ContentHandler): #--------------------------------------------------------------------- def stop_note(self,tag): self.in_note = 0 - if self.in_people == 1: + if self.in_address == 1: + self.address.setNote(fix_spaces(self.note_list)) + elif self.in_source_ref == 1: + self.source_ref.setNote(fix_spaces(self.note_list)) + elif self.in_event == 1: + self.event.setNote(fix_spaces(self.note_list)) + elif self.in_people == 1: self.person.setNote(fix_spaces(self.note_list)) elif self.in_family == 1: self.family.setNote(fix_spaces(self.note_list)) @@ -715,6 +768,8 @@ class GrampsParser(handler.ContentHandler): "address" : (start_address, stop_address), "aka" : (start_name, stop_aka), "attribute" : (start_attribute, stop_attribute), + "attr_type" : (None,stop_attr_type), + "attr_value" : (None,stop_attr_value), "bookmark" : (start_bmark, None), "bookmarks" : (None, None), "child" : (start_child,None), @@ -759,7 +814,7 @@ class GrampsParser(handler.ContentHandler): "scomments" : (None, stop_scomments), "sdate" : (None,stop_sdate), "source" : (start_source, None), - "sourceref" : (start_sourceref, None), + "sourceref" : (start_sourceref, stop_sourceref), "sources" : (start_sources, None), "spage" : (None, stop_spage), "spubinfo" : (None, stop_spubinfo), diff --git a/src/PaperMenu.py b/src/PaperMenu.py index 1bf454535..d4deac743 100644 --- a/src/PaperMenu.py +++ b/src/PaperMenu.py @@ -20,6 +20,7 @@ import TextDoc import gtk +import Config import intl _ = intl.gettext @@ -39,12 +40,17 @@ paper_sizes = [ def make_paper_menu(main_menu): + index = 0 myMenu = gtk.GtkMenu() for paper in paper_sizes: - menuitem = gtk.GtkMenuItem(paper.get_name()) + name = paper.get_name() + menuitem = gtk.GtkMenuItem(name) menuitem.set_data("i",paper) menuitem.show() myMenu.append(menuitem) + if name == Config.paper_preference: + myMenu.set_active(index) + index = index + 1 main_menu.set_menu(myMenu) def make_orientation_menu(main_menu): diff --git a/src/ReadXML.py b/src/ReadXML.py index 519ad14d9..f35ee4e40 100644 --- a/src/ReadXML.py +++ b/src/ReadXML.py @@ -42,7 +42,6 @@ try: import xml.sax.saxexts sax = 1 except: - from codecs import * sax = 2 #------------------------------------------------------------------------- @@ -67,7 +66,8 @@ def importData(database, filename, callback): else: parser = xml.sax.make_parser() parser.setContentHandler(GrampsParser(database,callback,basefile,1)) - xml_file = EncodedFile(gzip.open(filename,"rb"),'utf-8','latin-1') + xml_file = gzip.open(filename,"rb") +# xml_file = EncodedFile(gzip.open(filename,"rb"),'utf-8','latin-1') parser.parse(xml_file) xml_file.close() @@ -151,6 +151,9 @@ if __name__ == "__main__": t2 = time.time() print t2 - t1 + for person in db.getPersonMap().values(): + print person.getPrimaryName().getName() + diff --git a/src/RelLib.py b/src/RelLib.py index 477f0ff8a..5ffa03189 100644 --- a/src/RelLib.py +++ b/src/RelLib.py @@ -21,6 +21,21 @@ from Date import * from Researcher import * +#------------------------------------------------------------------------- +# +# Note class. +# +#------------------------------------------------------------------------- +class Note: + def __init__(self,text = ""): + self.text = text + + def set(self,text): + self.text = text + + def get(self): + return self.text + #------------------------------------------------------------------------- # # Photo class. Contains information about a photo stored in the database @@ -59,6 +74,26 @@ class Attribute: def __init__(self): self.type = "" self.value = "" + self.source_ref = SourceRef() + self.note = Note() + + def setNote(self,text): + self.note.set(text) + + def getNote(self): + return self.note.get() + + def setNoteObj(self,obj): + self.note = obj + + def getNoteObj(self,obj): + return self.note + + def setSourceRef(self,id) : + self.source_ref = id + + def getSourceRef(self) : + return self.source_ref def setType(self,val): self.type = val @@ -85,6 +120,26 @@ class Address: self.country = "" self.postal = "" self.date = Date() + self.note = Note() + self.source_ref = SourceRef() + + def setSourceRef(self,id) : + self.source_ref = id + + def getSourceRef(self) : + return self.source_ref + + def setNote(self,text): + self.note.set(text) + + def getNote(self): + return self.note.get() + + def setNoteObj(self,obj): + self.note = obj + + def getNoteObj(self,obj): + return self.note def setDate(self,text): self.date.set(text) @@ -228,7 +283,7 @@ class Person: self.addressList = [] self.attributeList = [] self.urls = [] - self.note = "" + self.note = Note() self.paf_uid = "" def setPrimaryName(self,name) : @@ -363,10 +418,17 @@ class Person: return self.MainFamily def setNote(self,text): - self.note = text + self.note.set(text) def getNote(self): + return self.note.get() + + def setNoteObj(self,obj): + self.note = obj + + def getNoteObj(self,obj): return self.note + #------------------------------------------------------------------------- # @@ -380,7 +442,8 @@ class Event: self.date = Date() self.description = "" self.name = "" - self.source = None + self.source_ref = None + self.note = Note() def set(self,name,date,place,description): self.name = name @@ -406,11 +469,11 @@ class Event: def getName(self) : return self.name - def setSource(self,id) : - self.source = id + def setSourceRef(self,id) : + self.source_ref = id - def getSource(self) : - return self.source + def getSourceRef(self) : + return self.source_ref def setPlace(self,place) : self.place = place @@ -418,6 +481,18 @@ class Event: def getPlace(self) : return self.place + def setNote(self,note) : + self.note.set(note) + + def getNote(self) : + return self.note.get() + + def setNoteObj(self,note) : + self.note = note + + def getNoteObj(self) : + return self.note + def setDescription(self,description) : self.description = description @@ -456,13 +531,19 @@ class Family: self.EventList = [] self.id = -1 self.photoList = [] - self.note = "" + self.note = Note() def getNote(self): - return self.note + return self.note.get() def setNote(self,text): - self.note = text + self.note.set(text) + + def getNoteObj(self): + return self.note + + def setNoteObj(self,obj): + self.note = obj def setId(self,id) : self.id = id @@ -532,13 +613,14 @@ class Family: # # #------------------------------------------------------------------------- -class SourceBase: +class Source: def __init__(self): self.title = "" self.author = "" self.pubinfo = "" self.callno = "" - + self.note = Note() + def setId(self,newId): self.id = newId @@ -551,6 +633,18 @@ class SourceBase: def getTitle(self): return self.title + def setNote(self,text): + self.note.set(text) + + def getNote(self): + return self.note.get() + + def setNoteObj(self,obj): + self.note = obj + + def getNoteObj(self): + return self.note + def setAuthor(self,author): self.author = author @@ -574,12 +668,12 @@ class SourceBase: # # #------------------------------------------------------------------------- -class Source: +class SourceRef: def __init__(self): self.ref = None self.page = "" self.date = Date() - self.comments = "" + self.comments = Note() self.text = "" def setBase(self,ref): @@ -600,21 +694,24 @@ class Source: def getPage(self): return self.page - def getDate(self): - return self.date - def setText(self,text): self.text = text def getText(self): return self.text - def setComments(self,comments): - self.comments = comments + def setNoteObj(self,note): + self.comments = note def getComments(self): return self.comments + def setComments(self,comments): + self.comments.set(comments) + + def getComments(self): + return self.comments.get() + #------------------------------------------------------------------------- # # @@ -637,6 +734,9 @@ class RelDataBase: self.bookmarks = [] self.path = "" + def getBookmarks(self): + return self.bookmarks + def clean_bookmarks(self): new_bookmarks = [] for person in self.bookmarks: @@ -748,7 +848,7 @@ class RelDataBase: if map.has_key(idVal): source = self.sourceMap[map[idVal]] else: - source = SourceBase() + source = Source() map[idVal] = self.addSource(source) return source @@ -763,7 +863,7 @@ class RelDataBase: if self.sourceMap.has_key(val): source = self.sourceMap[val] else: - source = SourceBase() + source = Source() self.addSourceNoMap(source,val) return source diff --git a/src/Sources.py b/src/Sources.py index 35c1a82e7..972ba6829 100644 --- a/src/Sources.py +++ b/src/Sources.py @@ -66,24 +66,22 @@ class SourceEditor: # __init__ - Creates a source editor window associated with an event # #--------------------------------------------------------------------- - def __init__(self,active_event,database): + def __init__(self,active_entry,database): self.db = database - self.active_event = active_event + self.active_entry = active_entry self.showSource = libglade.GladeXML(const.gladeFile, "sourceDisplay") self.showSource.signal_autoconnect({ "on_sourceok_clicked" : on_sourceok_clicked, - "on_selectsource_clicked" : on_selectsource_clicked, "destroy_passed_object" : utils.destroy_passed_object }) self.sourceDisplay = self.get_widget("sourceDisplay") self.source_field = self.get_widget("sourceList") - self.title_field = self.get_widget("stitle") + self.title_menu = self.get_widget("source_title") self.author_field = self.get_widget("sauthor") self.pub_field = self.get_widget("spubinfo") - self.callno_field = self.get_widget("scallno") - self.source = active_event.getSource() + self.source_ref = active_entry.getSourceRef() self.active_source = None self.draw() self.sourceDisplay.set_data(SOURCEDISP,self) @@ -98,34 +96,54 @@ class SourceEditor: return self.showSource.get_widget(name) def draw(self): - if self.source: - self.get_widget("spage").set_text(self.source.getPage()) - date = self.source.getDate() + + typeMenu = GtkMenu() + menuitem = GtkMenuItem('None') + menuitem.set_data("s",None) + menuitem.set_data("o",self) + menuitem.connect("activate",on_source_changed) + menuitem.show() + typeMenu.append(menuitem) + index = 1 + save = 0 + self.base = self.source_ref.getBase() + for src in self.db.getSourceMap().values(): + if src == self.base: + save = index + menuitem = GtkMenuItem(src.getTitle()) + menuitem.set_data("s",src) + menuitem.set_data("o",self) + menuitem.connect("activate",on_source_changed) + menuitem.show() + typeMenu.append(menuitem) + index = index + 1 + typeMenu.set_active(save) + self.title_menu.set_menu(typeMenu) + + if self.source_ref: + self.get_widget("spage").set_text(self.source_ref.getPage()) + date = self.source_ref.getDate() if date: self.get_widget("sdate").set_text(date.getDate()) text = self.get_widget("stext") text.set_point(0) - text.insert_defaults(self.source.getText()) + text.insert_defaults(self.source_ref.getText()) text.set_word_wrap(1) scom = self.get_widget("scomment") scom.set_point(0) - scom.insert_defaults(self.source.getComments()) + scom.insert_defaults(self.source_ref.getComments()) scom.set_word_wrap(1) - srcRef = self.source.getBase() - self.active_source = srcRef - if srcRef: - self.title_field.set_text(srcRef.getTitle()) - self.author_field.set_text(srcRef.getAuthor()) - self.pub_field.set_text(srcRef.getPubInfo()) - self.callno_field.set_text(srcRef.getCallNumber()) + src = self.source_ref.getBase() + self.active_source = src + if src: + self.author_field.set_text(src.getAuthor()) + self.pub_field.set_text(src.getPubInfo()) else: - self.title_field.set_text("") self.author_field.set_text("") self.pub_field.set_text("") - self.callno_field.set_text("") #------------------------------------------------------------------------- # @@ -136,31 +154,20 @@ def on_sourceok_clicked(obj): src_edit = obj.get_data(SOURCEDISP) - if src_edit.active_event: - current_source = src_edit.active_event.getSource() - if current_source == None: - if src_edit.active_source: - current_source = Source() - src_edit.active_event.setSource(current_source) - else: - return - if src_edit.active_source != current_source.getBase(): - src_edit.active_event.getSource().setBase(src_edit.active_source) - utils.modified() - if current_source.getBase() != src_edit.active_source: - current_source.setBase(src_edit.active_source) - utils.modified() - page = src_edit.get_widget("spage").get_text() - date = src_edit.get_widget("sdate").get_text() - text = src_edit.get_widget("stext").get_chars(0,-1) - comments = src_edit.get_widget("scomment").get_chars(0,-1) - - current_source.setPage(page) - current_source.getDate().set(date) - current_source.setText(text) - current_source.setComments(comments) + current_source_ref = src_edit.active_entry.getSourceRef() + if src_edit.active_source != current_source_ref.getBase(): + src_edit.active_entry.getSourceRef().setBase(src_edit.active_source) utils.modified() - + page = src_edit.get_widget("spage").get_text() + date = src_edit.get_widget("sdate").get_text() + text = src_edit.get_widget("stext").get_chars(0,-1) + comments = src_edit.get_widget("scomment").get_chars(0,-1) + + current_source_ref.setPage(page) + current_source_ref.getDate().set(date) + current_source_ref.setText(text) + current_source_ref.setComments(comments) + utils.modified() utils.destroy_passed_object(obj) #------------------------------------------------------------------------- @@ -168,164 +175,16 @@ def on_sourceok_clicked(obj): # # #------------------------------------------------------------------------- -def on_selectsource_clicked(obj): +def on_source_changed(obj): - src_edit = obj.get_data(SOURCEDISP) - SourceChoose(src_edit) + src_entry = obj.get_data("o") + src_entry.active_source = obj.get_data("s") -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -class SourceChoose: - - def __init__(self,source_info): - self.db = source_info.db - self.source_info = source_info - - self.active_source = source_info.active_source - self.selSrc = libglade.GladeXML(const.gladeFile, "sourceEditor") - self.selSrc.signal_autoconnect({ - "on_addsource_clicked" : on_addsource_clicked, - "on_updatesource_clicked" : on_updatesource_clicked, - "on_deletesource_clicked" : on_deletesource_clicked, - "on_sourceapply_clicked" : on_sourceapply_clicked, - "on_sourceList_select_row" : on_sourceList_select_row, - "destroy_passed_object" : utils.destroy_passed_object - }) - - self.title_field = self.selSrc.get_widget("source_title") - self.author_field = self.selSrc.get_widget("author") - self.pub_field = self.selSrc.get_widget("pubinfo") - self.callno_field = self.selSrc.get_widget("callno") - self.src_list = self.selSrc.get_widget("sourceList") - - if source_info.active_source: - actsrc = source_info.active_source - self.title_field.set_text(actsrc.getTitle()) - self.author_field.set_text(actsrc.getAuthor()) - self.pub_field.set_text(actsrc.getPubInfo()) - self.callno_field.set_text(actsrc.getCallNumber()) - self.active_source = source_info.active_source - - self.src_list.set_data(ACTIVESRC,self) - self.src_list.set_data(INDEX,-1) - self.redraw_sources() - - #--------------------------------------------------------------------- - # - # - # - #--------------------------------------------------------------------- - def redraw_sources(self): - - self.src_list.clear() - self.src_list.freeze() - current_row = -1 - self.index = 0 - for src in self.db.getSourceMap().values(): - self.src_list.append([src.getTitle(),src.getAuthor()]) - self.src_list.set_row_data(self.index,src) - if self.active_source == src: - current_row = self.index - self.index = self.index + 1 - - self.src_list.select_row(current_row,0) - self.src_list.moveto(current_row,0) - - self.src_list.set_data(INDEX,current_row) - self.src_list.thaw() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_addsource_clicked(obj): - src_obj = obj.get_data(ACTIVESRC) - - src_obj.active_source = SourceBase() - title = src_obj.title_field.get_text() - author = src_obj.author_field.get_text() - src_obj.src_list.append([title,author]) - src_obj.db.addSource(src_obj.active_source) - - src_obj.active_source.setTitle(title) - src_obj.active_source.setAuthor(author) - src_obj.active_source.setCallNumber(src_obj.callno_field.get_text()) - src_obj.active_source.setPubInfo(src_obj.pub_field.get_text()) - src_obj.redraw_sources() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_deletesource_clicked(obj): - src_obj = obj.get_data(ACTIVESRC) - src_obj.active_source = None - obj.set_data(INDEX,-1) - src_obj.redraw_sources() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_updatesource_clicked(obj): - - src_obj = obj.get_data(ACTIVESRC) - if src_obj.active_source: - src_obj.active_source.setTitle(src_obj.title_field.get_text()) - src_obj.active_source.setAuthor(src_obj.author_field.get_text()) - src_obj.active_source.setCallNumber(src_obj.callno_field.get_text()) - src_obj.active_source.setPubInfo(src_obj.pub_field.get_text()) - src_obj.redraw_sources() - -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_sourceList_select_row(obj,row,b,c): - obj.set_data(INDEX,row) - src_obj = obj.get_data(ACTIVESRC) - - src_obj.active_source = obj.get_row_data(row) - select_source = src_obj.active_source - - if select_source: - src_obj.title_field.set_text(select_source.getTitle()) - src_obj.author_field.set_text(select_source.getAuthor()) - src_obj.pub_field.set_text(select_source.getPubInfo()) - src_obj.callno_field.set_text(select_source.getCallNumber()) + if src_entry.active_source == None: + src_entry.author_field.set_text("") + src_entry.pub_field.set_text("") else: - src_obj.title_field.set_text("") - src_obj.author_field.set_text("") - src_obj.pub_field.set_text("") - src_obj.callno_field.set_text("") + src_entry.author_field.set_text(src_entry.active_source.getAuthor()) + src_entry.pub_field.set_text(src_entry.active_source.getPubInfo()) -#------------------------------------------------------------------------- -# -# -# -#------------------------------------------------------------------------- -def on_sourceapply_clicked(obj): - - row = obj.get_data(INDEX) - src_obj = obj.get_data(ACTIVESRC) - - src_obj.active_source = obj.get_row_data(row) - if row == -1: - src_obj.active_source = None - elif not src_obj.active_source: - src_obj.active_source = Source() - - if not src_obj.source_info.source: - src_obj.source_info.source = Source() - src_obj.source_info.source.setBase(src_obj.active_source) - src_obj.source_info.draw() - - utils.destroy_passed_object(src_obj.selSrc.get_widget("sourceEditor")) diff --git a/src/WriteXML.py b/src/WriteXML.py index 85ab1ff09..3487d94bb 100644 --- a/src/WriteXML.py +++ b/src/WriteXML.py @@ -97,24 +97,34 @@ def dump_my_event(g,name,event): write_line(g,"date",date) write_line(g,"place",place) write_line(g,"description",description) - source = event.getSource() - if source: - sourceRef = source.getBase() - if sourceRef: - p = source.getPage() - c = source.getComments() - t = source.getText() - d = source.getDate().getSaveDate() + if event.getNote() != "": + writeNote(g,"note",event.getNote()) + + dump_source_ref(g,event.getSourceRef()) + g.write("\n") + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def dump_source_ref(g,source_ref): + if source_ref: + source = source_ref.getBase() + if source: + p = source_ref.getPage() + c = source_ref.getComments() + t = source_ref.getText() + d = source_ref.getDate().getSaveDate() if p == "" and c == "" and t == "" and d == "": - g.write("\n" % sourceRef.getId()) + g.write("\n" % source.getId()) else: - g.write("\n" % sourceRef.getId()) + g.write("\n" % source.getId()) write_line(g,"spage",p) writeNote(g,"scomments",c) writeNote(g,"stext",t) write_line(g,"sdate",c) g.write("\n") - g.write("\n") #------------------------------------------------------------------------- # @@ -263,15 +273,26 @@ def exportData(database, filename, callback): write_line(g,"state",address.getState()) write_line(g,"country",address.getCountry()) write_line(g,"postal",address.getPostal()) + if address.getNote() != "": + writeNote(g,"note",address.getNote()) + dump_source_ref(g,address.getSourceRef()) g.write('\n') g.write('\n') if len(person.getAttributeList()) > 0: g.write("\n") for attr in person.getAttributeList(): - g.write('' % attr.getType()) - g.write(fix(attr.getValue())) - g.write('\n') + if attr.getSourceRef() or attr.getNote(): + g.write('') + write_line(g,"attr_type",attr.getType()) + write_line(g,"attr_value",attr.getValue()) + dump_source_ref(g,attr.getSourceRef()) + writeNote(g,"note",attr.getNote()) + g.write('\n') + else: + g.write('' % attr.getType()) + g.write(fix(attr.getValue())) + g.write('\n') g.write('\n') if len(person.getUrlList()) > 0: @@ -335,12 +356,14 @@ def exportData(database, filename, callback): write_line(g,"sauthor",source.getAuthor()) write_line(g,"spubinfo",source.getPubInfo()) write_line(g,"scallno",source.getCallNumber()) + if source.getNote() != "": + writeNote(g,"note",source.getNote()) g.write("\n") g.write("\n") - if len(db.bookmarks) > 0: + if len(db.getBookmarks()) > 0: g.write("\n") - for person in db.bookmarks: + for person in db.getBookmarks(): g.write("\n") g.write("\n") diff --git a/src/config.glade b/src/config.glade index adfd0364c..ed61208ef 100644 --- a/src/config.glade +++ b/src/config.glade @@ -250,7 +250,7 @@ GtkLabel label199 - + GTK_JUSTIFY_CENTER False 1 @@ -276,7 +276,7 @@ GtkLabel label200 - + GTK_JUSTIFY_CENTER False 1 @@ -303,7 +303,8 @@ GtkOptionMenu date_format True - + + 0 1 @@ -325,7 +326,8 @@ GtkOptionMenu name_format True - + + 0 1 @@ -369,7 +371,7 @@ GtkLabel label201 - + GTK_JUSTIFY_CENTER False 1 @@ -396,7 +398,8 @@ GtkOptionMenu date_entry_format True - + + 0 1 @@ -433,41 +436,12 @@ GtkTable table21 - 2 - 1 + 1 + 2 False 0 0 - - GtkCheckButton - enableColors - True - - toggled - on_color_toggled - propertybox - Sat, 17 Feb 2001 14:19:39 GMT - - - False - True - - 0 - 1 - 0 - 1 - 5 - 10 - False - False - False - False - True - False - - - GtkFrame frame4 @@ -477,8 +451,8 @@ 0 1 - 1 - 2 + 0 + 1 5 5 False @@ -492,7 +466,7 @@ GtkTable table22 - 4 + 5 2 False 0 @@ -514,8 +488,8 @@ 1 2 - 0 - 1 + 1 + 2 5 5 False @@ -543,8 +517,8 @@ 1 2 - 1 - 2 + 2 + 3 5 5 False @@ -572,8 +546,8 @@ 1 2 - 2 - 3 + 3 + 4 5 5 False @@ -601,8 +575,8 @@ 1 2 - 3 - 4 + 4 + 5 5 5 False @@ -617,33 +591,7 @@ GtkLabel label195 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 0 - 1 - 5 - 0 - False - False - False - False - False - False - - - - - GtkLabel - label196 - + GTK_JUSTIFY_CENTER False 1 @@ -661,15 +609,15 @@ False False False - False + True False GtkLabel - label197 - + label196 + GTK_JUSTIFY_CENTER False 1 @@ -687,15 +635,15 @@ False False False - False + True False GtkLabel - label198 - + label197 + GTK_JUSTIFY_CENTER False 1 @@ -713,10 +661,157 @@ False False False - False + True False + + + GtkLabel + label198 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 0 + + 0 + 1 + 4 + 5 + 5 + 0 + False + False + False + False + True + False + + + + + GtkCheckButton + enableColors + True + + toggled + on_color_toggled + propertybox + Sat, 17 Feb 2001 14:19:39 GMT + + + False + True + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + + + + + + + GtkFrame + frame7 + + 0 + GTK_SHADOW_ETCHED_IN + + 1 + 2 + 0 + 1 + 5 + 5 + True + True + False + False + True + True + + + + GtkVBox + vbox25 + False + 0 + + + GtkRadioButton + stat1 + True + + toggled + on_object_toggled + propertybox + Wed, 30 May 2001 02:18:01 GMT + + + True + True + status + + 0 + False + False + + + + + GtkRadioButton + stat2 + True + + toggled + on_object_toggled + propertybox + Wed, 30 May 2001 02:18:16 GMT + + + False + True + status + + 0 + False + False + + + + + GtkRadioButton + stat3 + True + + toggled + on_object_toggled + propertybox + Wed, 30 May 2001 02:18:29 GMT + + + False + True + status + + 0 + False + False + + @@ -938,7 +1033,7 @@ GtkLabel label143 - + GTK_JUSTIFY_CENTER False 1 @@ -950,7 +1045,7 @@ 1 0 1 - 0 + 5 0 False False @@ -964,7 +1059,7 @@ GtkLabel label144 - + GTK_JUSTIFY_CENTER False 1 @@ -976,7 +1071,7 @@ 1 1 2 - 0 + 5 0 False False @@ -990,7 +1085,7 @@ GtkLabel label145 - + GTK_JUSTIFY_CENTER False 1 @@ -1002,7 +1097,7 @@ 1 2 3 - 0 + 5 0 False False @@ -1016,7 +1111,7 @@ GtkLabel label146 - + GTK_JUSTIFY_CENTER False 1 @@ -1028,7 +1123,7 @@ 1 3 4 - 0 + 5 0 False False @@ -1042,7 +1137,7 @@ GtkLabel label147 - + GTK_JUSTIFY_CENTER False 1 @@ -1054,7 +1149,7 @@ 1 4 5 - 0 + 5 0 False False @@ -1068,7 +1163,7 @@ GtkLabel label148 - + GTK_JUSTIFY_CENTER False 1 @@ -1080,7 +1175,7 @@ 1 5 6 - 0 + 5 0 False False @@ -1094,7 +1189,7 @@ GtkLabel label149 - + GTK_JUSTIFY_CENTER False 1 @@ -1106,7 +1201,7 @@ 1 6 7 - 0 + 5 0 False False @@ -1120,7 +1215,7 @@ GtkLabel label150 - + GTK_JUSTIFY_CENTER False 1 @@ -1132,7 +1227,7 @@ 1 7 8 - 0 + 5 0 False False @@ -1156,6 +1251,131 @@ 0 0 + + + GtkTable + table25 + 3 + 2 + False + 0 + 0 + + + GtkLabel + label203 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 0 + + 0 + 1 + 0 + 1 + 5 + 5 + False + False + False + False + True + False + + + + + GtkLabel + label204 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 0 + + 0 + 1 + 1 + 2 + 5 + 5 + False + False + False + False + True + False + + + + + GtkOptionMenu + paper_size + True + Letter +A4 + + 0 + + 1 + 2 + 1 + 2 + 5 + 5 + True + False + False + False + True + False + + + + + GtkOptionMenu + output_format + True + OpenOffice +HTML +PDF +AbiWord + + 0 + + 1 + 2 + 0 + 1 + 5 + 5 + True + False + False + False + True + False + + + + + + GtkLabel + Notebook:tab + label202 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + diff --git a/src/const.py b/src/const.py index 368c76997..8237f22f3 100644 --- a/src/const.py +++ b/src/const.py @@ -54,6 +54,7 @@ marriageFile = rootDir + os.sep + "marriage.glade" editPersonFile = rootDir + os.sep + "EditPerson.glade" bookFile = rootDir + os.sep + "bookmarks.glade" pluginsFile = rootDir + os.sep + "plugins.glade" +notesFile = rootDir + os.sep + "editnote.glade" configFile = rootDir + os.sep + "config.glade" pluginsDir = rootDir + os.sep + "plugins" @@ -67,7 +68,7 @@ gtkrcFile = rootDir + os.sep + "gtkrc" # #------------------------------------------------------------------------- progName = "gramps" -version = "0.1.5" +version = "0.2.0pre" copyright = "(C) 2001 Donald N. Allingham" authors = ["Donald N. Allingham"] comments = _("Gramps (Genealogical Research and Analysis Management ") +\ @@ -98,6 +99,9 @@ helpMenu = "contents.html" # Constants # #------------------------------------------------------------------------- + +output_formats = ["OpenOffice", "AbiWord", "PDF", "HTML" ] + childRelations = [ "Biological", "Adopted", diff --git a/src/gramps.glade b/src/gramps.glade index 2d642a66f..49e2539ed 100644 --- a/src/gramps.glade +++ b/src/gramps.glade @@ -20,7 +20,12 @@ destroy on_exit_activate - Thu, 19 Oct 2000 14:26:14 GMT + Tue, 29 May 2001 23:11:49 GMT + + + delete_event + delete_event + Tue, 29 May 2001 23:19:12 GMT Gramps GTK_WINDOW_TOPLEVEL @@ -207,6 +212,18 @@ False + + + GtkMenuItem + sources + + activate + on_sources_activate + Wed, 30 May 2001 01:59:42 GMT + + + False + @@ -446,6 +463,26 @@ pedegree.xpm + + GtkButton + Toolbar:button + button105 + + clicked + on_sources_activate + Wed, 30 May 2001 02:01:04 GMT + + + GNOME_STOCK_PIXMAP_PROPERTIES + + True + + + + + Placeholder + + GtkButton Toolbar:button @@ -2307,6 +2344,138 @@ 0 0 + + + GtkVBox + vbox33 + False + 0 + + + GtkScrolledWindow + scrolledwindow24 + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + 0 + True + True + + + + GtkCList + source_list + True + + select_row + on_source_list_select_row + Tue, 29 May 2001 21:23:02 GMT + + 2 + 300,80 + GTK_SELECTION_SINGLE + True + GTK_SHADOW_IN + + + GtkLabel + CList:title + label215 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + GtkLabel + CList:title + label216 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + + + GtkHButtonBox + hbuttonbox20 + GTK_BUTTONBOX_SPREAD + 30 + 85 + 27 + 7 + 0 + + 0 + False + True + + + + GtkButton + button102 + True + True + + clicked + on_add_source_clicked + source_list + Tue, 29 May 2001 21:16:02 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button103 + True + True + + clicked + on_edit_source_clicked + source_list + Tue, 29 May 2001 21:15:39 GMT + + + GTK_RELIEF_NORMAL + + + + GtkButton + button104 + False + True + True + + GTK_RELIEF_NORMAL + + + + + + GtkLabel + Notebook:tab + label214 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + @@ -3282,7 +3451,7 @@ Other clicked on_sourceapply_clicked - sourceList + sourceEditor Thu, 18 Jan 2001 02:53:13 GMT GNOME_STOCK_BUTTON_OK @@ -3347,13 +3516,18 @@ Other - GtkTable - table17 - 4 - 2 - False - 0 - 0 + GtkNotebook + notebook2 + 450 + 250 + True + True + True + GTK_POS_TOP + False + 2 + 2 + False 0 True @@ -3361,322 +3535,223 @@ Other - GtkLabel - label165 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 0 - 1 - 0 - 0 - False - False - False - False - True - False - - - - - GtkLabel - label166 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 1 - 2 - 0 - 0 - False - False - False - False - True - False - - - - - GtkLabel - label167 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 2 - 3 - 0 - 0 - False - False - False - False - True - False - - - - - GtkLabel - label168 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 3 - 4 - 0 - 0 - False - False - False - False - True - False - - - - - GtkEntry - source_title - True - True - True - 0 - - - 1 - 2 - 0 - 1 - 2 - 2 - True - False - False - False - True - False - - - - - GtkEntry - author - True - True - True - 0 - - - 1 - 2 - 1 - 2 - 2 - 2 - True - False - False - False - True - False - - - - - GtkEntry - pubinfo - True - True - True - 0 - - - 1 - 2 - 2 - 3 - 2 - 2 - True - False - False - False - True - False - - - - - GtkEntry - callno - True - True - True - 0 - - - 1 - 2 - 3 - 4 - 2 - 2 - True - False - False - False - True - False - - - - - - GtkScrolledWindow - scrolledwindow19 - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_UPDATE_CONTINUOUS - GTK_UPDATE_CONTINUOUS - - 0 - True - True - - - - GtkCList - sourceList - 400 - 150 - True - - select_row - on_sourceList_select_row - Thu, 18 Jan 2001 15:09:10 GMT - + GtkTable + table17 + 3 2 - 171,80 - GTK_SELECTION_SINGLE - True - GTK_SHADOW_IN + False + 0 + 0 GtkLabel - CList:title - label169 - + label165 + GTK_JUSTIFY_CENTER False - 0.5 + 1 0.5 0 0 + + 0 + 1 + 0 + 1 + 0 + 0 + False + False + False + False + True + False + GtkLabel - CList:title - label170 - + label166 + GTK_JUSTIFY_CENTER False - 0.5 + 1 0.5 0 0 + + 0 + 1 + 1 + 2 + 0 + 0 + False + False + False + False + True + False + + + + + GtkLabel + label167 + + GTK_JUSTIFY_CENTER + False + 1 + 0.5 + 0 + 0 + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + False + + + + + GtkEntry + source_title + True + True + True + 0 + + + 1 + 2 + 0 + 1 + 5 + 5 + True + False + False + False + True + False + + + + + GtkEntry + author + True + True + True + 0 + + + 1 + 2 + 1 + 2 + 5 + 5 + True + False + False + False + True + False + + + + + GtkEntry + pubinfo + True + True + True + 0 + + + 1 + 2 + 2 + 3 + 5 + 5 + True + False + False + False + True + False + - - - - GtkHButtonBox - hbuttonbox16 - GTK_BUTTONBOX_SPREAD - 30 - 85 - 27 - 7 - 0 - - 0 - True - True - - GtkButton - button91 - True - True - - clicked - on_addsource_clicked - sourceList - Thu, 18 Jan 2001 02:53:25 GMT - - - GTK_RELIEF_NORMAL + GtkLabel + Notebook:tab + label204 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 - GtkButton - button92 - True - True - - clicked - on_updatesource_clicked - sourceList - Fri, 02 Mar 2001 21:01:33 GMT - - - GTK_RELIEF_NORMAL + GtkScrolledWindow + scrolledwindow23 + GTK_POLICY_NEVER + GTK_POLICY_ALWAYS + GTK_UPDATE_CONTINUOUS + GTK_UPDATE_CONTINUOUS + + + GtkText + source_note + True + False + + - GtkButton - button93 - True - True - - clicked - on_deletesource_clicked - sourceList - Thu, 18 Jan 2001 02:53:52 GMT - - - GTK_RELIEF_NORMAL + GtkLabel + Notebook:tab + label205 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 + + + + Placeholder + + + + GtkLabel + Notebook:tab + label206 + + GTK_JUSTIFY_CENTER + False + 0.5 + 0.5 + 0 + 0 @@ -3799,7 +3874,7 @@ Other GtkTable table18 - 6 + 4 2 False 0 @@ -3810,32 +3885,6 @@ Other True - - GtkLabel - label172 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 3 - 4 - 0 - 0 - False - False - False - False - True - False - - - GtkLabel label173 @@ -3920,8 +3969,8 @@ Other 0 2 - 5 - 6 + 3 + 4 0 0 False @@ -3934,23 +3983,20 @@ Other - GtkLabel - stitle - - GTK_JUSTIFY_LEFT - False - 0 - 0.5 - 3 - 0 + GtkOptionMenu + source_title + True + + + 0 1 2 0 1 - 0 - 0 - True + 5 + 5 + False False False False @@ -3974,8 +4020,8 @@ Other 2 1 2 - 0 - 0 + 5 + 5 True False False @@ -4000,8 +4046,8 @@ Other 2 2 3 - 0 - 0 + 5 + 5 True False False @@ -4010,82 +4056,6 @@ Other False - - - GtkLabel - scallno - - GTK_JUSTIFY_LEFT - False - 0 - 0.5 - 3 - 0 - - 1 - 2 - 3 - 4 - 0 - 0 - True - False - False - False - True - False - - - - - GtkHButtonBox - hbuttonbox18 - GTK_BUTTONBOX_DEFAULT_STYLE - 30 - 85 - 27 - 7 - 0 - - 0 - 2 - 4 - 5 - 0 - 0 - False - True - False - False - True - True - - - - GtkButton - button96 - True - True - - clicked - on_selectsource_clicked - sourceDisplay - Tue, 16 Jan 2001 19:59:32 GMT - - - GTK_RELIEF_NORMAL - - - - - - GtkVSeparator - vseparator9 - - 3 - True - True - @@ -4154,58 +4124,6 @@ Other - - GtkLabel - label182 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 2 - 3 - 0 - 0 - False - False - False - False - True - False - - - - - GtkLabel - label183 - - GTK_JUSTIFY_CENTER - False - 1 - 0.5 - 0 - 0 - - 0 - 1 - 3 - 4 - 0 - 0 - False - False - False - False - True - False - - - GtkScrolledWindow scrolledwindow20 @@ -4231,6 +4149,7 @@ Other GtkText scomment + 300 True True @@ -4316,6 +4235,58 @@ Other False + + + GtkLabel + label183 + + GTK_JUSTIFY_CENTER + False + 1 + 0 + 0 + 10 + + 0 + 1 + 3 + 4 + 0 + 0 + False + False + False + False + True + True + + + + + GtkLabel + label182 + + GTK_JUSTIFY_CENTER + False + 1 + 0 + 0 + 5 + + 0 + 1 + 2 + 3 + 0 + 0 + False + False + False + False + True + True + + diff --git a/src/gramps_main.py b/src/gramps_main.py index a5724065d..5c463ac13 100755 --- a/src/gramps_main.py +++ b/src/gramps_main.py @@ -100,6 +100,7 @@ topWindow = None statusbar = None Main = None person_list = None +source_list = None database = None family_window = None queryTop = None @@ -146,6 +147,16 @@ def deathday(person): return person.getDeath().getQuoteDate() else: return "" + +def delete_event(widget, event): + widget.hide() + if utils.wasModified(): + question = _("Unsaved changes exist in the current database\n") + \ + _("Do you wish to save the changes?") + topWindow.question(question,save_query) + else: + mainquit(widget) + return TRUE #------------------------------------------------------------------------- # @@ -560,6 +571,7 @@ def new_database_response(val): change_active_person(None) person_list.clear() load_family() + load_sources() #------------------------------------------------------------------------- # @@ -594,9 +606,113 @@ def update_display(changed): goto_active_person() elif page == 1: load_family() + elif page == 3: + load_sources() else: load_tree() +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def load_sources(): + source_list.clear() + source_list.freeze() + + color_clist = ListColors.ColorList(source_list,1) + + current_row = source_list.get_data("i") + if current_row == None: + current_row = -1 + + index = 0 + for src in database.getSourceMap().values(): + source_list.append([src.getTitle(),src.getAuthor()]) + source_list.set_row_data(index,src) + index = index + 1 + + if index > 0: + if current_row == -1: + current_row = 0 + source_list.select_row(current_row,0) + source_list.moveto(current_row,0) + + source_list.set_data("i",current_row) + source_list.thaw() + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def on_source_list_button_press_event(obj,event): + if event.button == 1 and event.type == GDK._2BUTTON_PRESS: + index = obj.get_data("i") + if index == -1: + return + + source = obj.get_row_data(index) + EditSource.EditSource(source,database,update_source_after_edit) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def on_source_list_select_row(obj,a,b,c): + obj.set_data("i",a) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def on_add_source_clicked(obj): + import EditSource + + EditSource.EditSource(Source(),database,new_source_after_edit) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def on_delete_source_clicked(obj): + pass + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def on_edit_source_clicked(obj): + import EditSource + + index = obj.get_data("i") + if index == -1: + return + + source = obj.get_row_data(index) + EditSource.EditSource(source,database,update_source_after_edit) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def new_source_after_edit(source): + database.addSource(source.source) + update_display(1) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def update_source_after_edit(source): + update_display(1) + #------------------------------------------------------------------------- # # @@ -1153,7 +1269,18 @@ def change_active_person(person): # #------------------------------------------------------------------------- def modify_statusbar(): - statusbar.set_status(Config.nameof(active_person)) + pname = Config.nameof(active_person) + if Config.status_bar == 1: + name = "[%s] %s" % (str(active_person.getId()),pname) + elif Config.status_bar == 2: + name = pname + for attr in active_person.getAttributeList(): + if attr.getType() == Config.attr_name: + name = "[%s] %s" % (attr.getValue(),pname) + break + else: + name = pname + statusbar.set_status(name) #------------------------------------------------------------------------- # @@ -1276,6 +1403,10 @@ def on_pedegree1_activate(obj): notebk = Main.get_widget(NOTEBOOK) notebk.set_page(2) +def on_sources_activate(obj): + notebk = Main.get_widget(NOTEBOOK) + notebk.set_page(3) + #------------------------------------------------------------------------- # # Load the appropriate page after a notebook switch @@ -1284,16 +1415,18 @@ def on_pedegree1_activate(obj): def on_notebook1_switch_page(obj,junk,page): if not active_person: return - if (page == 0): + if page == 0: if id2col.has_key(active_person): column = id2col[active_person] person_list.select_row(column,0) person_list.moveto(column,0) - elif (page == 1): + elif page == 1: load_family() - elif (page == 2): + elif page == 2: load_tree() - + elif page == 3: + load_sources() + #------------------------------------------------------------------------- # # @@ -1797,7 +1930,7 @@ def setup_bookmarks(): menu = Main.get_widget("jump_to") person_map = database.getPersonMap() - bookmarks = Bookmarks.Bookmarks(database.bookmarks,person_map,\ + bookmarks = Bookmarks.Bookmarks(database.getBookmarks(),person_map,\ menu,bookmark_callback) #------------------------------------------------------------------------- @@ -1989,7 +2122,7 @@ def on_preferences_activate(obj): def main(arg): global database, Main global statusbar - global person_list, pv + global person_list, source_list, pv global topWindow import ReadXML @@ -2008,6 +2141,7 @@ def main(arg): topWindow = Main.get_widget("gramps") statusbar = Main.get_widget("statusbar") person_list = Main.get_widget("person_list") + source_list = Main.get_widget("source_list") filter_list = Main.get_widget("filter_list") myMenu = GtkMenu() @@ -2035,6 +2169,7 @@ def main(arg): "on_reports_clicked" : on_reports_clicked, "on_person_list1_activate": on_person_list1_activate, "on_family1_activate" : on_family1_activate, + "on_sources_activate" : on_sources_activate, "on_pedegree1_activate" : on_pedegree1_activate, "on_notebook1_switch_page": on_notebook1_switch_page, "on_ok_button1_clicked": on_ok_button1_clicked, @@ -2077,6 +2212,12 @@ def main(arg): "on_edit_mother_clicked" : on_edit_mother_clicked, "on_exit_activate" : on_exit_activate, "on_statusbar_unmap" : on_statusbar_unmap, + "on_add_source_clicked" : on_add_source_clicked, + "on_source_list_button_press_event" : on_source_list_button_press_event, + "on_source_list_select_row": on_source_list_select_row, + "on_delete_source_clicked" : on_delete_source_clicked, + "on_edit_source_clicked" : on_edit_source_clicked, + "delete_event" : delete_event, "on_open_activate" : on_open_activate }) diff --git a/src/latin_utf8.py b/src/latin_utf8.py index a954d2f61..4008a71bb 100644 --- a/src/latin_utf8.py +++ b/src/latin_utf8.py @@ -1,3 +1,22 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2000 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 +# import cStringIO @@ -26,9 +45,8 @@ try: except: def utf8_to_latin(s): - return s + return s.encode('latin-1') def latin_to_utf8(s): - return s - + return s.encode('utf-8') diff --git a/src/plugins/IndivSummary.py b/src/plugins/IndivSummary.py index 17b65a933..9e7610117 100644 --- a/src/plugins/IndivSummary.py +++ b/src/plugins/IndivSummary.py @@ -293,8 +293,16 @@ class IndivSummary: family = self.person.getMainFamily() if family: - father = family.getFather().getPrimaryName().getRegularName() - mother = family.getMother().getPrimaryName().getRegularName() + father_inst = family.getFather() + if father_inst: + father = father_inst.getPrimaryName().getRegularName() + else: + father = "" + mother_inst = family.getMother() + if mother_inst: + mother = mother_inst.getPrimaryName().getRegularName() + else: + mother = "" else: father = "" mother = "" diff --git a/src/plugins/ReadGedcom.py b/src/plugins/ReadGedcom.py index 758e41f3f..8893fe130 100644 --- a/src/plugins/ReadGedcom.py +++ b/src/plugins/ReadGedcom.py @@ -37,12 +37,15 @@ from gtk import * from gnome.ui import * from libglade import * +ANSEL = 1 +UNICODE = 2 topDialog = None db = None callback = None glade_file = None clear_data = 0 +in_obje = 0 InvalidGedcom = "Invalid GEDCOM file" @@ -67,6 +70,9 @@ def find_file(fullname,altpath): else: return "" +lineRE = re.compile(r"\s*(\d+)\s+(\S+)\s*(.*)$") +nameRegexp = re.compile(r"([\S\s]*\S)?\s*/([^/]+)?/\s*,?\s*([\S]+)?") + #------------------------------------------------------------------------- # # @@ -78,547 +84,1108 @@ def importData(database, filename): global glade_file global statusWindow - headRegexp = re.compile(r"\s*0\s+HEAD") - charRegexp = re.compile(r"\s*1\s+CHAR\s+(\S+)\s*$") - sourceRegexp = re.compile(r"\s*1\s+SOUR\s+(\S?[\s\S]*\S)\s*$") - srcrefRegexp = re.compile(r"\s*2\s+SOUR\s+@(.+)@") - indiRegexp = re.compile(r"\s*0\s+@(.+)@\s+INDI") - familyRegexp = re.compile(r"\s*0\s+@(.+)@\s+FAM") - srcRegexp = re.compile(r"\s*0\s+@(.+)@\s+SOUR") - topRegexp = re.compile(r"\s*0\s+") - changeRegexp = re.compile(r"\s*1\s+CHAN") - geventRegexp = re.compile(r"\s*1\s+EVEN") - numRegexp = re.compile(r"\s*[2-9]\s") - eventRegexp = re.compile(r"\s*1\s+([\S]+)\s*(.*)?$") - titleRegexp = re.compile(r"\s*1\s+TITL\s*(.*)?$") - objeRegexp = re.compile(r"\s*1\s+OBJE") - title2Regexp = re.compile(r"\s*2\s+TITL\s*(.*)?$") - fileRegexp = re.compile(r"\s*2\s+FILE\s*(.*)?$") - uidRegexp = re.compile(r"\s*1\s+_UID\s*(.*)?$") - authorRegexp = re.compile(r"\s*1\s+AUTH\s*(.*)?$") - pubRegexp = re.compile(r"\s*1\s+PUBL\s*(.*)?$") - callnoRegexp = re.compile(r"\s*1\s+CALN\s*(.*)?$") - prefixRegexp = re.compile(r"\s*2\s+NPFX\s*(.*)?$") - suffixRegexp = re.compile(r"\s*2\s+NSFX\s*(.*)?$") - birthRegexp = re.compile(r"\s*1\s+BIRT\s*(.*)?$") - noterefRegexp= re.compile(r"\s*1\s+NOTE\s+@(.+)@") - noteactRegexp= re.compile(r"\s*1\s+NOTE\s+(.+)*") - refnRegexp = re.compile(r"\s*1\s+REFN") - noteRegexp = re.compile(r"\s*0\s+@(.+)@\s+NOTE\s*(.*)?$") - concRegexp = re.compile(r"\s*\d\s+CONC\s(.*)?$") - contRegexp = re.compile(r"\s*\d\s+CONT\s(.*)?$") - deathRegexp = re.compile(r"\s*1\s+DEAT\s*(.*)?$") - divorceRegexp= re.compile(r"\s*1\s+DIV\s*(.*)?$") - marriedRegexp= re.compile(r"\s*1\s+MAR\s*(.*)?$") - genderRegexp = re.compile(r"\s*1\s+SEX\s+(\S)?") - typeRegexp = re.compile(r"\s*2\s+TYPE\s*(.*)?$") - placeRegexp = re.compile(r"\s*2\s+PLAC\s*(.*)?$") - pageRegexp = re.compile(r"\s*3\s+PAGE\s*(.*)?$") - dateRegexp = re.compile(r"\s*2\s+DATE\s*(.*)?$") - nameRegexp = re.compile(r"\s*1\s+NAME\s+([\S\s]*\S)?\s*/([^/]+)?/\s*,?\s*([\S]+)?") - famsRegexp = re.compile(r"\s*1\s+FAMS\s+@(.*)@") - famcRegexp = re.compile(r"\s*1\s+FAMC\s+@(.*)@") - fatherRegexp = re.compile(r"\s*1\s+HUSB\s+@(.*)@") - motherRegexp = re.compile(r"\s*1\s+WIFE\s+@(.*)@") - childRegexp = re.compile(r"\s*1\s+CHIL\s+@(.*)@") - - noteId = "" - inlineNote = 0 - inlocalNote = 0 - user2note = {} - person2note = {} - personActive = 0 - familyActive = 0 - sourceActive = 0 - noteActive = 0 - allLines = [] - values = {} - index = 0 - currentLine = 0 - fmap = {} - pmap = {} - smap = {} - familyTree = 0 - in_change = 0 - photo = None - encoding = 0 # add some checking here - gedcom = open(filename,"r") - if clear_data == 1: database.new() - statusTop = GladeXML(glade_file,"status") - statusWindow = statusTop.get_widget("status") - progressWindow = statusTop.get_widget("progress") - - allLines = gedcom.readlines() - gedcom.close() + g = GedcomParser(database,filename) + g.parse_gedcom_file() - # use search here instead of match, since PAF5 seems to like to - # insert garbage as the first couple of characters in the file - - regex_match = headRegexp.search(allLines[0]) - if regex_match == None: - raise InvalidGedcom - - total = len(allLines) +# statusTop = GladeXML(glade_file,"status") +# statusWindow = statusTop.get_widget("status") +# progressWindow = statusTop.get_widget("progress") - value = 0 - for index in range(1,51): - value = value + total/50 - values[index] = value + utils.modified() + callback(1) - index = 1 - value = values[1] - for line in allLines: +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +class AddrStruct: + def __init__(self): + self.label = "" + self.addr1 = "" + self.addr2 = "" + self.city = "" + self.state = "" + self.postal = "" + self.country = "" + self.phone = "" - line = string.replace(line, '\r', "") - if encoding == 1: +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +class DateStruct: + def __init__(self): + self.date = "" + self.time = "" + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +class GedcomParser: + + SyntaxError = "Syntax Error" + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def __init__(self,db, file): + self.db = db + self.person = None + self.pmap = {} + self.fmap = {} + self.smap = {} + self.nmap = {} + f = open(file,"r") + self.lines = f.readlines() + f.close() + self.index = 0 + self.code = 0 + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def get_next(self): + line = string.replace(self.lines[self.index],'\r','') + if self.code == ANSEL: line = latin_ansel.ansel_to_latin(line) - elif encoding == 2: + elif self.code == UNICODE: line = latin_utf8.utf8_to_latin(line) - - if currentLine == value and index <= 50: - index = index + 1 - if index <= 50: - value = values[index] - progressWindow.set_percentage(float(currentLine)/float(total)) - while events_pending(): - mainiteration() + match = lineRE.match(line) + if not match: + raise GedcomParser.SyntaxError, self.lines[self.index] + self.index = self.index + 1 + return match.groups() - currentLine = currentLine + 1 + def barf(self,level): + print "IGNORED (%d): %s" % (self.index, self.lines[self.index-1]) + self.ignore_sub_junk(level) - regex_match = charRegexp.match(line) - if regex_match: - id = regex_match.groups() - if id[0] == "ANSEL": - encoding = 1 - elif id[0] == "UNICODE" or id[0] == "UTF-8" or id[0] == "UTF8": - encoding = 2 - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def backup(self): + self.index = self.index - 1 - regex_match = changeRegexp.match(line) - if regex_match: - in_change = 1 - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_gedcom_file(self): + self.index = 0 + self.parse_header() + self.parse_submitter() + self.parse_record() + self.parse_trailer() - if in_change: - if numRegexp.match(line): - in_change = 0 - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_trailer(self): + matches = self.get_next() - regex_match = indiRegexp.match(line) - if regex_match: - id = regex_match.groups() - person = database.findPerson(id[0],pmap) - personActive = 1 - familyActive = 0 - sourceActive = 0 - noteActive = 0 - continue + if matches[1] != "TRLR": + self.barf(0) - regex_match = familyRegexp.match(line) - if regex_match: - id = regex_match.groups() - family = database.findFamily(id[0],fmap) - personActive = 0 - familyActive = 1 - sourceActive = 0 - noteActive = 0 - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header(self): + self.parse_header_head() + self.parse_header_source() + self.parse_header_dest() + self.parse_header_date() + self.parse_header_subm() + self.parse_header_subn() + self.parse_header_file() + self.parse_header_copr() + self.parse_header_gedc() + self.parse_header_char() + self.parse_header_lang() + self.parse_header_plac() + self.parse_header_note() - regex_match = srcRegexp.match(line) - if regex_match: - id = regex_match.groups() - source = database.findSource(id[0],smap) - personActive = 0 - familyActive = 0 - sourceActive = 1 - noteActive = 0 - continue - - regex_match = noteRegexp.match(line) - if regex_match: - matches = regex_match.groups() - noteId = matches[0] - noteActive = 1 - sourceActive = 0 - familyActive = 0 - personActive = 0 - if matches[1] == None: - user2note[noteId] = "" + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_submitter(self): + matches = self.get_next() + + if matches[2] != "SUBN": + self.backup() + return + else: + self.ignore_sub_junk(1) + + def parse_source(self,name,level): + self.source = self.db.findSource(name,self.smap) + + while 1: + matches = self.get_next() + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "DATA" or matches[1] == "TEXT": + self.ignore_sub_junk(2) + elif matches[1] == "TITL": + self.source.setTitle(matches[2] + self.parse_continue_data(2)) + elif matches[1] == "AUTH": + self.source.setAuthor(matches[2] + self.parse_continue_data(2)) + elif matches[1] == "PUBL": + self.source.setPubInfo(matches[2] + self.parse_continue_data(2)) + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[1] + self.parse_continue_data(1) + self.source.setNote(note) + self.ignore_sub_junk(2) + else: + if self.nmap.has_key(matches[2]): + self.source.setNoteObj(self.nmap[matches[2]]) + else: + noteobj = Note() + self.nmap[matches[2]] = noteobj + self.source.setNoteObj(noteobj) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_record(self): + while 1: + matches = self.get_next() + + if matches[2] == "FAM": + self.family = self.db.findFamily(matches[1],self.fmap) + self.parse_family() + elif matches[2] == "INDI": + self.person = self.db.findPerson(matches[1],self.pmap) + self.parse_individual() + elif matches[2] == "SUBM": + self.ignore_sub_junk(1) + elif matches[1] == "SUBM": + self.ignore_sub_junk(1) + elif matches[2] == "SOUR": + self.parse_source(matches[1],1) + elif matches[2] == "REPO": + print "REPO",matches[1] + self.ignore_sub_junk(1) + elif matches[2] == "NOTE": + if self.nmap.has_key(matches[1]): + noteobj = self.nmap[matches[1]] + else: + noteobj = Note() + self.nmap[matches[1]] = noteobj + noteobj.set(self.parse_continue_data(1)) + self.parse_note_data(1) + elif matches[2] == "OBJE": + print "OBJE",matches[1] + self.ignore_sub_junk(1) + elif matches[1] == "TRLR": + self.backup() + return else: - user2note[noteId] = matches[1] - continue + self.barf(1) - regex_match = sourceRegexp.match(line) - if regex_match: - matches = regex_match.groups() - if matches[0] == "FTW": - familyTree = 1 - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_note_data(self,level): + while 1: + matches = self.get_next() + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "SOUR": + self.ignore_sub_junk(level+1) + elif matches[1] == "CHAN": + self.ignore_sub_junk(level+1) + elif matches[1] == "REFN": + self.ignore_sub_junk(level+1) + elif matches[1] == "RIN": + pass + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_source_citation(self,level): + while 1: + matches = self.get_next() + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "PAGE": + pass + elif matches[1] == "EVEN": + self.ignore_sub_junk(level+1) + elif matches[1] == "DATA": + self.ignore_sub_junk(level+1) + elif matches[1] == "QUAY": + pass + elif matches[1] == "NOTE": + note = matches[1] + self.parse_continue_data(level+1) + self.ignore_change_data(level+1) + pass + else: + self.barf(level+1) - regex_match = topRegexp.match(line) - if regex_match: - personActive = 0 - familyActive = 0 - noteActive = 0 - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_family(self): + while 1: + matches = self.get_next() - if familyActive == 1: - regex_match = srcrefRegexp.match(line) - if regex_match: - matches = regex_match.groups() - source = database.findSource(matches[0],smap) - mySource = Source() - mySource.setBase(source) - event.setSource(mySource) - continue - - regex_match = pageRegexp.match(line) - if regex_match: - matches = regex_match.groups() - mySource.setPage(matches[0]) - continue - - regex_match = fatherRegexp.match(line) - if regex_match: - matches = regex_match.groups() - father = database.findPerson(matches[0],pmap) - family.setFather(father) - continue - - regex_match = motherRegexp.match(line) - if regex_match: - matches = regex_match.groups() - mother = database.findPerson(matches[0],pmap) - family.setMother(mother) - continue - - regex_match = childRegexp.match(line) - if regex_match : - matches = regex_match.groups() - child = database.findPerson(matches[0],pmap) - family.addChild(child) - continue - - regex_match = marriedRegexp.match(line) - if regex_match : - matches = regex_match.groups() + if int(matches[0]) == 0: + self.backup() + return + elif matches[1] == "HUSB": + self.family.setFather(self.db.findPerson(matches[2],self.pmap)) + self.ignore_sub_junk(2) + elif matches[1] == "WIFE": + self.family.setMother(self.db.findPerson(matches[2],self.pmap)) + self.ignore_sub_junk(2) + elif matches[1] == "CHIL": + self.family.addChild(self.db.findPerson(matches[2],self.pmap)) + elif matches[1] == "NCHI" or matches[1] == "RIN" or matches[1] == "SUBM": + pass + elif matches[1] == "REFN" or matches[1] == "CHAN": + self.ignore_sub_junk(2) + elif matches[1] == "MARR": event = Event() event.setName("Marriage") - family.setMarriage(event) - continue - - regex_match = divorceRegexp.match(line) - if regex_match : - matches = regex_match.groups() + self.family.setMarriage(event) + self.parse_family_event(event,2) + elif matches[1] == "DIV": event = Event() event.setName("Divorce") - family.setDivorce(event) - continue - - regex_match = placeRegexp.match(line) - if regex_match : - matches = regex_match.groups() - event.setPlace(matches[0]) - continue - - regex_match = geventRegexp.match(line) - if regex_match : - matches = regex_match.groups() + self.family.setDivorce(event) + self.parse_family_event(event,2) + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[1] + self.parse_continue_data(1) + self.family.setNote(note) + self.ignore_sub_junk(2) + else: + if self.nmap.has_key(matches[2]): + self.family.setNoteObj(self.nmap[matches[2]]) + else: + noteobj = Note() + self.nmap[matches[2]] = noteobj + self.family.setNoteObj(noteobj) + else: event = Event() - family.addEvent(event) - continue - - regex_match = dateRegexp.match(line) - if regex_match : - matches = regex_match.groups() try: - event.setDate(matches[0]) + event.setName(ged2fam[matches[2]]) except: - pass - continue - - regex_match = typeRegexp.match(line) - if regex_match : - matches = regex_match.groups() - event.setName(matches[0]) - continue + event.setName(matches[2]) + self.family.addEvent(event) + self.parse_family_event(event,2) - elif personActive == 1: + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_individual(self): + while 1: + matches = self.get_next() - regex_match = nameRegexp.match(line) - if regex_match : - matches = regex_match.groups() + if int(matches[0]) == 0: + self.backup() + return + elif matches[1] == "NAME": name = Name() - if matches[0] : - name.setFirstName(matches[0]) - if matches[1] : - name.setSurname(matches[1]) - if matches[2] : - name.setSuffix(matches[2]) - - person.setPrimaryName(name) - continue - - regex_match = titleRegexp.match(line) - if regex_match: - continue - - regex_match = prefixRegexp.match(line) - if regex_match: - matches = regex_match.groups() - name.setTitle(matches[0]) - continue - - regex_match = uidRegexp.match(line) - if regex_match: - matches = regex_match.groups() - person.setPafUid(matches[0]) - continue - - regex_match = suffixRegexp.match(line) - if regex_match: - matches = regex_match.groups() - name.setSuffix(matches[0]) - continue - - if inlocalNote == 1: - - regex_match = concRegexp.match(line) - if regex_match : - matches = regex_match.groups() - user2note[noteId] = user2note[noteId] + matches[0] - continue - - regex_match = contRegexp.match(line) - if regex_match : - matches = regex_match.groups() - user2note[noteId] = user2note[noteId] + "\n" + matches[0] - continue - - inlocalNote = 0 - person.setNote(user2note[noteId]) - - regex_match = noterefRegexp.match(line) - if regex_match : - matches = regex_match.groups() - person2note[person] = matches[0] - continue - - regex_match = noteactRegexp.match(line) - if regex_match : - inlocalNote = 1 - matches = regex_match.groups() - noteId = "local%d" % inlineNote - inlineNote = inlineNote + 1 - if matches[0] == None: - user2note[noteId] = "" + names = nameRegexp.match(matches[2]).groups() + if names[0]: + name.setFirstName(names[0]) + if names[1]: + name.setSurname(names[1]) + if names[2]: + name.setSuffix(names[2]) + self.person.setPrimaryName(name) + self.parse_name(name,2) + elif matches[1] == "RIN": + pass + elif matches[1] == "RFN": + pass + elif matches[1] == "AFN": + pass + elif matches[1] == "CHAN": + self.ignore_sub_junk(1) + elif matches[1] == "ALIA": + pass + elif matches[1] == "ANCI" or matches[1] == "DESI": + pass + elif matches[1] == "REFN": + self.ignore_sub_junk(1) + elif matches[1] == "SOUR": + self.ignore_sub_junk(1) + elif matches[1] == "OBJE": + if matches[2] and matches[2][0] == '@': + self.ignore_sub_junk(2) else: - user2note[noteId] = matches[0] - continue - - regex_match = srcrefRegexp.match(line) - if regex_match: - matches = regex_match.groups() - source = database.findSource(matches[0],smap) - mySource = Source() - mySource.setBase(source) - event.setSource(mySource) - continue - - regex_match = pageRegexp.match(line) - if regex_match: - matches = regex_match.groups() - mySource.setPage(matches[0]) - continue - - regex_match = genderRegexp.match(line) - if regex_match : - matches = regex_match.groups() - if matches[0] == "M": - person.setGender(Person.male) + self.parse_person_object(2) + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[1] + self.parse_continue_data(1) + self.person.setNote(note) + self.ignore_sub_junk(2) else: - person.setGender(Person.female) - continue - - regex_match = famcRegexp.match(line) - if regex_match : - matches = regex_match.groups() - new_family = database.findFamily(matches[0],fmap) - person.setMainFamily(new_family) - continue - - regex_match = famsRegexp.match(line) - if regex_match : - matches = regex_match.groups() - new_family = database.findFamily(matches[0],fmap) - person.addFamily(new_family) - continue - - regex_match = birthRegexp.match(line) - if regex_match : - matches = regex_match.groups() + if self.nmap.has_key(matches[2]): + self.person.setNoteObj(self.nmap[matches[2]]) + else: + noteobj = Note() + self.nmap[matches[2]] = noteobj + self.person.setNoteObj(noteobj) + elif matches[1] == "SEX": + if matches[2][0] == "M": + self.person.setGender(Person.male) + else: + self.person.setGender(Person.female) + elif matches[1] == "EVEN": + pass + elif matches[1] == "FAMS": + self.person.addFamily(self.db.findFamily(matches[2],self.fmap)) + note = self.parse_optional_note(2) + elif matches[1] == "FAMC": + type,note = self.parse_famc_type(2) + family = self.db.findFamily(matches[2],self.fmap) + if type == "" or type == "Birth": + self.person.setMainFamily(family) + else: + self.person.addAltFamily(family,type) + elif matches[1] == "RESI": + addr = Address() + self.person.addAddress(addr) + self.parse_residence(addr,2) + elif matches[1] == "BIRT": event = Event() - - # check to see if the person already had a birthdate set. - # if he/she does, then add the birthdate as an alternate. - # this assumes that the first birthdate in the GEDCOM file - # is the one that should be considered the primary - - lbirth = person.getBirth() - if lbirth.getDate() != "" or lbirth.getPlace() != "": - person.addEvent(event) + if self.person.getBirth().getDate() != "" or \ + self.person.getBirth().getPlace() != "": event.setName("Alternate Birth") + self.person.addEvent(event) else: - person.setBirth(event) - continue - - regex_match = deathRegexp.match(line) - if regex_match : - matches = regex_match.groups() + event.setName("Birth") + self.person.setBirth(event) + self.parse_person_event(event,2) + elif matches[1] == "ADOP": event = Event() - - # check to see if the person already had a birthdate set. - # if he/she does, then add the birthdate as an alternate. - # this assumes that the first birthdate in the GEDCOM file - # is the one that should be considered the primary - - ldeath = person.getDeath() - if ldeath.getDate() != "" or ldeath.getPlace() != "": - person.addEvent(event) + event.setName("Adopted") + self.person.addEvent(event) + self.parse_person_event(event,2) + elif matches[1] == "DEAT": + event = Event() + if self.person.getDeath().getDate() != "" or \ + self.person.getDeath().getPlace() != "": event.setName("Alternate Death") + self.person.addEvent(event) else: - person.setDeath(event) - continue - - regex_match = refnRegexp.match(line) - if regex_match : - continue - - regex_match = geventRegexp.match(line) - if regex_match : - matches = regex_match.groups() + event.setName("Death") + self.person.setDeath(event) + self.parse_person_event(event,2) + elif matches[1] == "EVEN": event = Event() - person.addEvent(event) - continue - - regex_match = eventRegexp.match(line) - if regex_match : - matches = regex_match.groups() + self.person.addEvent(event) + self.parse_person_event(event,2) + else: event = Event() - if ged2rel.has_key(matches[0]): - type = ged2rel[matches[0]] - elif ged2fam.has_key(matches[0]): - type = ged2fam[matches[0]] - else: - type = matches[0] - event.setName(type) - if matches[1] : - event.setDescription(matches[1]) - person.addEvent(event) - continue - - regex_match = typeRegexp.match(line) - if regex_match : - matches = regex_match.groups() - event.setName(matches[0]) - continue - - regex_match = placeRegexp.match(line) - if regex_match : - matches = regex_match.groups() - event.setPlace(matches[0]) - continue - - regex_match = dateRegexp.match(line) - if regex_match : - matches = regex_match.groups() try: - event.setDate(matches[0]) + event.setName(ged2rel[matches[1]]) except: - pass - continue + event.setName(matches[1]) + self.person.addEvent(event) + self.parse_person_event(event,2) - regex_match = fileRegexp.match(line) - if regex_match : - matches = regex_match.groups() - imagepath = find_file(matches[0],os.path.dirname(filename)) - savepath = database.getSavePath() - if imagepath != "" and savepath != "": - id = person.getId() - for index in range(0,100): - base = "i%s_%d.jpg" % (id,index) - name = savepath + os.sep + base - if os.path.exists(name) == 0: - break - shutil.copy(imagepath,name) + def parse_optional_note(self,level): + note = "" + while 1: + matches = self.get_next() - photo = Photo() - continue + if int(matches[0]) < level: + self.backup() + return note + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[2] + self.parse_continue_data(level+1) + self.parse_note_data(level+1) + else: + self.ignore_sub_junk(level+1) + else: + self.barf(level+1) - regex_match = title2Regexp.match(line) - if regex_match and photo != None: - matches = regex_match.groups() - photo.setDescripton(matches[0]) - continue + def parse_famc_type(self,level): + type = "" + note = "" + while 1: + matches = self.get_next() - if objeRegexp.match(line): - photo = None - continue - - elif noteActive == 1: + if int(matches[0]) < level: + self.backup() + return (string.capitalize(type),note) + elif matches[1] == "PEDI": + type = matches[2] + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[2] + self.parse_continue_data(level+1) + self.parse_note_data(level+1) + else: + self.ignore_sub_junk(level+1) + else: + self.barf(level+1) - regex_match = concRegexp.match(line) - if regex_match : - matches = regex_match.groups() - user2note[noteId] = user2note[noteId] + matches[0] - continue + def parse_person_object(self,level): + form = "" + file = "" + title = "" + note = "" + while 1: + matches = self.get_next() + if matches[1] == "FORM": + form = matches[2] + elif matches[1] == "TITL": + title = matches[2] + elif matches[1] == "FILE": + file = matches[2] + elif matches[1] == "NOTE": + note = matches[2] + self.parse_continue_data(level+1) + elif int(matches[0]) < level: + self.backup() + break + else: + self.barf(level+1) - regex_match = contRegexp.match(line) - if regex_match : - matches = regex_match.groups() - user2note[noteId] = user2note[noteId] + "\n" + matches[0] - continue + if form == "URL": + url = Url(file,title) + self.person.addUrl(url) + else: + print "*",form,title - elif sourceActive == 1: + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_residence(self,address,level): + while 1: + matches = self.get_next() + if int(matches[0]) < level: + self.backup() + break + elif matches[1] == "DATE": + address.setDate(matches[2]) + elif matches[1] == "AGE" or matches[1] == "AGNC": + self.ignore_sub_junk(level+1) + elif matches[1] == "CAUS" or matches[1] == "ADDR": + self.ignore_sub_junk(level+1) + elif matches[1] == "STAT" or matches[1] == "TEMP": + self.ignore_sub_junk(level+1) + elif matches[1] == "OBJE" or matches[1] == "TYPE": + self.ignore_sub_junk(level+1) + elif matches[1] == "SOUR": + source_ref = SourceRef() + source_ref.setBase(self.db.findSource(matches[2],self.smap)) + address.setSourceRef(source_ref) + self.parse_source_reference(source_ref,level+1) + elif matches[1] == "PLAC": + address.setStreet(matches[2]) + self.parse_address(address,level+1) + elif matches[1] == "PHON": + pass + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[1] + self.parse_continue_data(1) + self.address.setNote(note) + self.ignore_sub_junk(2) + else: + if self.nmap.has_key(matches[2]): + self.address.setNoteObj(self.nmap[matches[2]]) + else: + noteobj = Note() + self.nmap[matches[2]] = noteobj + self.address.setNoteObj(noteobj) + else: + self.barf(level+1) - regex_match = titleRegexp.match(line) - if regex_match: - matches = regex_match.groups() - source.setTitle(matches[0]) - continue + def parse_address(self,address,level): + first = 0 + while 1: + matches = self.get_next() - regex_match = authorRegexp.match(line) - if regex_match: - matches = regex_match.groups() - source.setAuthor(matches[0]) - continue + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "ADDR" or matches[1] == "ADR1" or matches[1] == "ADR2": + val = address.getStreet() + if first == 0: + val = "%s %s" % (matches[2], self.parse_continue_data(level+1)) + first = 1 + else: + val = "%s,%s %s" % (val,matches[2],self.parse_continue_data(level+1)) + address.setStreet(val) + elif matches[1] == "CITY": + address.setCity(matches[2]) + elif matches[1] == "STAE": + address.setState(matches[2]) + elif matches[1] == "POST": + address.setPostal(matches[2]) + elif matches[1] == "CTRY": + address.setCountry(matches[2]) + else: + self.barf(level+1) - regex_match = pubRegexp.match(line) - if regex_match: - matches = regex_match.groups() - source.setPubInfo(matches[0]) - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_person_event(self,event,level): + while 1: + matches = self.get_next() + if int(matches[0]) < level: + self.backup() + break + elif matches[1] == "TYPE": + if event.getName() != "": + try: + event.setName(ged2rel[matches[2]]) + except: + event.setName(matches[2]) + elif matches[1] == "DATE": + event.setDate(matches[2]) + elif matches[1] == "AGE" or matches[1] == "AGNC": + self.ignore_sub_junk(level+1) + elif matches[1] == "CAUS" or matches[1] == "ADDR": + self.ignore_sub_junk(level+1) + elif matches[1] == "STAT" or matches[1] == "TEMP": + self.ignore_sub_junk(level+1) + elif matches[1] == "OBJE": + self.ignore_sub_junk(level+1) + elif matches[1] == "SOUR": + source_ref = SourceRef() + source_ref.setBase(self.db.findSource(matches[2],self.smap)) + event.setSourceRef(source_ref) + self.parse_source_reference(source,level+1) + elif matches[1] == "FAMC": + family = self.db.findFamily(matches[2],self.fmap) + if event.getName() == "Birth": + self.person.setMainFamily(family) + else: + self.person.addAltFamily(family,event.getName()) + self.ignore_sub_junk(level+1) + elif matches[1] == "PLAC": + event.setPlace(matches[2]) + self.ignore_sub_junk(level+1) + elif matches[1] == "NOTE": + note = matches[2] + self.parse_continue_data(level+1) + else: + self.barf(level+1) - regex_match = callnoRegexp.match(line) - if regex_match: - matches = regex_match.groups() - source.setCallNumber(matches[0]) - continue + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_family_event(self,event,level): + while 1: + matches = self.get_next() + if int(matches[0]) < level: + self.backup() + break + elif matches[1] == "TYPE": + if event.getName() != "": + try: + event.setName(ged2fam[matches[2]]) + except: + event.setName(matches[2]) + elif matches[1] == "DATE": + event.setDate(matches[2]) + elif matches[1] == "AGE" or matches[1] == "AGNC": + self.ignore_sub_junk(level+1) + elif matches[1] == "CAUS" or matches[1] == "ADDR": + self.ignore_sub_junk(level+1) + elif matches[1] == "STAT" or matches[1] == "TEMP": + self.ignore_sub_junk(level+1) + elif matches[1] == "OBJE": + self.ignore_sub_junk(level+1) + elif matches[1] == "SOUR": + source_ref = SourceRef() + source_ref.setBase(self.db.findSource(matches[2],self.smap)) + event.setSourceRef(source_ref) + self.parse_source_reference(source_ref,level+1) + elif matches[1] == "PLAC": + event.setPlace(matches[2]) + self.ignore_sub_junk(level+1) + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[1] + self.parse_continue_data(1) + event.setNote(note) + self.ignore_sub_junk(2) + else: + if self.nmap.has_key(matches[2]): + event.setNoteObj(self.nmap[matches[2]]) + else: + noteobj = Note() + self.nmap[matches[2]] = noteobj + event.setNoteObj(noteobj) + else: + self.barf(level+1) - for person in person2note.keys(): - name = person.getPrimaryName() - noteId = person2note[person] - person.setNote(user2note[noteId]) + def parse_source_reference(self,source,level): + while 1: + matches = self.get_next() - statusWindow.destroy() + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "PAGE": + source.setPage(matches[2]) + elif matches[1] == "DATA": + date,text = self.parse_source_data(level+1) + d = Date() + d.set(date) + source.setDate(d) + source.setText(text) + elif matches[1] == "QUAY": + pass + elif matches[1] == "NOTE": + if matches[2] and matches[2][0] != "@": + note = matches[1] + self.parse_continue_data(1) + source.setComments(note) + self.ignore_sub_junk(2) + else: + if self.nmap.has_key(matches[2]): + source.setNoteObj(self.nmap[matches[2]]) + else: + noteobj = Note() + self.nmap[matches[2]] = noteobj + source.setNoteObj(noteobj) + else: + self.barf(level+1) + + def parse_source_data(self,level): + date = "" + note = "" + while 1: + matches = self.get_next() - callback(1) + if int(matches[0]) < level: + self.backup() + return (date,note) + elif matches[1] == "DATE": + date = matches[2] + + elif matches[1] == "TEXT": + note = matches[2] + self.parse_continue_data(level+1) + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_name(self,name,level): + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "NPFX": + name.setTitle(matches[1]) + elif matches[1] == "GIVN": + name.setFirstName(matches[1]) + elif matches[1] == "SPFX": + pass + elif matches[1] == "SURN": + name.setSurname(matches[1]) + elif matches[1] == "NSFX": + name.setSuffix(matches[1]) + elif matches[1] == "NICK": + self.person.setNickName(matches[1]) + elif matches[1] == "SOUR": + self.ignore_sub_junk(level+1) + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_head(self): + matches = self.get_next() + + if matches[1] != "HEAD": + self.barf(0) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_source(self): + while 1: + matches = self.get_next() + + print matches[0],matches[1],matches[2] + if int(matches[0]) == 0: + self.backup() + return + elif matches[1] == "SOUR": + print "Source is",matches[2] + elif matches[1] == "NAME": + print "Name is",matches[2] + elif matches[1] == "VERS": + print "Version is",matches[2] + elif matches[1] == "CORP": + self.ignore_sub_junk(2) + elif matches[1] == "DATA": + print "Data is",matches[2] + self.parse_sub_data(3) + elif matches[1] == "SUBM": + pass + elif matches[1] == "SUBN": + pass + elif matches[1] == "DEST": + pass + elif matches[1] == "FILE": + self.ignore_sub_junk(1) + elif matches[1] == "COPR": + pass + elif matches[1] == "CHAR": + if matches[2] == "UNICODE" or matches[2] == "UTF-8" or \ + matches[2] == "UTF8": + self.code = UNICODE + elif matches[2] == "ANSEL": + self.code = ANSEL + self.parse_sub_char(2) + elif matches[1] == "GEDC": + self.parse_gedc(2) + elif matches[1] == "LANG": + print "Language is",matches[2] + elif matches[1] == "PLAC": + self.parse_place_form(2) + elif matches[1] == "DATE": + date = self.parse_date(2) + date.date = matches[2] + elif matches[1] == "NOTE": + note = matches[2] + self.parse_continue_data(2) + print note + elif matches[1][0] == "_": + self.ignore_sub_junk(2) + else: + self.barf(2) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def ignore_sub_junk(self,level): + + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def ignore_change_data(self,level): + + matches = self.get_next() + if matches[1] == "CHAN": + while 1: + matches = self.get_next() + + if int(matches[0]) < level+1: + self.backup() + return + else: + self.backup() + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_sub_char(self,level): + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "VERS": + print "CHAR version is",matches[2] + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_place_form(self,level): + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "FORM": + print "FORM",matches[2] + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_continue_data(self,level): + data = "" + while 1: + matches = self.get_next() + + if matches[1] == "CONC": + data = "%s%s" % (data,matches[2]) + elif matches[1] == "CONT": + data = "%s\n%s" % (data,matches[2]) + else: + self.backup() + return data + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_gedc(self,level): + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "VERS": + print "Gedcom version is",matches[2] + elif matches[1] == "FORM": + print "Gedcom form is",matches[2] + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_date(self,level): + date = DateStruct() + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return date + elif matches[1] == "TIME": + date.time = matches[2] + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_addr_struct(self,level): + addr = AddrStruct() + + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "ADDR": + addr.label = matches[2] + self.parse_sub_addr(level+1, addr) + elif matches[1] == "PHON": + addr.phone = matches[2] + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_sub_addr(self,level,addr): + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "CONT": + addr.label = "%s\n%s" %(addr.label,matches[2]) + elif matches[1] == "ADR1": + addr.addr1 = matches[2] + elif matches[1] == "ADR2": + addr.addr2 = matches[2] + elif matches[1] == "CITY": + addr.city = matches[2] + elif matches[1] == "STAE": + addr.state = matches[2] + elif matches[1] == "POST": + addr.postal = matches[2] + elif matches[1] == "CTRY": + addr.country = matches[2] + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_sub_data(self,level): + while 1: + matches = self.get_next() + + if int(matches[0]) < level: + self.backup() + return + elif matches[1] == "DATE": + pass + elif matches[1] == "COPR": + pass + else: + self.barf(level+1) + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_dest(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_date(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_subm(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_subn(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_file(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_copr(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_gedc(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_char(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_lang(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_plac(self): + pass + + #--------------------------------------------------------------------- + # + # + # + #--------------------------------------------------------------------- + def parse_header_note(self): + pass #------------------------------------------------------------------------- # @@ -640,16 +1207,7 @@ def on_ok_clicked(obj): clear_data = 0 utils.destroy_passed_object(obj) - try: - importData(db,name) - except InvalidGedcom: - GnomeErrorDialog(_("%s is not a valid GEDCOM file") % name) - statusWindow.destroy() - except IOError, val: - GnomeErrorDialog(_("Could not load %s") % name + "\n" + val[1]) - except: - GnomeErrorDialog(_("Could not load %s") % name) - statusWindow.destroy() + importData(db,name) #------------------------------------------------------------------------- # @@ -684,3 +1242,14 @@ def readData(database,active_person,cb): #------------------------------------------------------------------------- def get_name(): return _("Import from GEDCOM") + +if __name__ == "__main__": + + import sys + + db = RelDataBase() + if len(sys.argv) == 1: + g = GedcomParser(db,"test.ged") + else: + g = GedcomParser(db,sys.argv[1]) + g.parse_gedcom_file() diff --git a/src/plugins/WriteGedcom.py b/src/plugins/WriteGedcom.py index 6e68c38f5..8e9c29834 100644 --- a/src/plugins/WriteGedcom.py +++ b/src/plugins/WriteGedcom.py @@ -26,6 +26,8 @@ import string import time import const import utils +import intl +_ = intl.gettext from gtk import * from gnome.ui import * @@ -192,9 +194,9 @@ def add_persons_sources(person): if person.getDeath(): elist.append(person.getDeath()) for event in elist: - source = event.getSource() - if source != None: - source_list.append(source) + source_ref = event.getSourceRef() + if source_ref != None: + source_list.append(source_ref) #------------------------------------------------------------------------- # @@ -208,9 +210,9 @@ def add_familys_sources(family): if family.getDivorce(): elist.append(family.getDivorce()) for event in elist: - source = event.getSource() - if source != None: - source_list.append(source) + source_ref = event.getSourceRef() + if source_ref != None: + source_list.append(source_ref) #------------------------------------------------------------------------- # diff --git a/src/plugins/familygroup.glade b/src/plugins/familygroup.glade index 6ad12fb8a..448b332f7 100644 --- a/src/plugins/familygroup.glade +++ b/src/plugins/familygroup.glade @@ -233,6 +233,26 @@ + + GtkRadioButton + abiword + True + + toggled + on_html_toggled + Tue, 20 Mar 2001 17:02:37 GMT + + + False + True + format + + 0 + False + False + + + GtkRadioButton pdf