GEDCOM improvements, Find improvements

svn: r621
This commit is contained in:
Don Allingham 2001-12-16 00:16:43 +00:00
parent a2faca3f16
commit fc8c83168d
22 changed files with 1467 additions and 1232 deletions

View File

@ -17,7 +17,15 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Provides a TextDoc based interface to the AbiWord document format.
"""
#-------------------------------------------------------------------------
#
# Imported Modules
#
#-------------------------------------------------------------------------
import os
import base64
@ -25,26 +33,40 @@ from TextDoc import *
from latin_utf8 import latin_to_utf8
import const
import string
import utils
cnv = utils.fl2txt
from utils import fl2txt
#-------------------------------------------------------------------------
#
# Attemp to import the Python Imaging Library
#
#-------------------------------------------------------------------------
try:
import PIL.Image
no_pil = 0
except:
no_pil = 1
#-------------------------------------------------------------------------
#
# Class Definitions
#
#-------------------------------------------------------------------------
class AbiWordDoc(TextDoc):
"""AbiWord document generator. Inherits from the TextDoc generic
document interface class."""
def __init__(self,styles,type,orientation):
"""Initializes the AbiWordDoc class, calling the __init__ routine
of the parent TextDoc class"""
TextDoc.__init__(self,styles,type,orientation)
self.f = None
self.level = 0
self.new_page = 0
def open(self,filename):
"""Opens the document, writing the necessary header information.
AbiWord uses an XML format, so the document format is pretty easy
to understand"""
if filename[-4:] != ".abw":
self.filename = "%s.abw" % filename
else:
@ -59,19 +81,20 @@ class AbiWordDoc(TextDoc):
self.f.write('orientation="portrait" ')
else:
self.f.write('orientation="landscape" ')
self.f.write('width="%s" ' % cnv("%.4f",self.width/2.54))
self.f.write('height="%s" ' % cnv("%.4f",self.height/2.54))
self.f.write('width="%s" ' % fl2txt("%.4f",self.width/2.54))
self.f.write('height="%s" ' % fl2txt("%.4f",self.height/2.54))
self.f.write('units="inch" page-scale="1.000000"/>\n')
self.f.write('<section ')
rmargin = float(self.rmargin)/2.54
lmargin = float(self.lmargin)/2.54
self.f.write('props="page-margin-right:%sin; ' % \
cnv("%.4f",rmargin))
fl2txt("%.4f",rmargin))
self.f.write('page-margin-left:%sin"' % \
cnv("%.4f",lmargin))
fl2txt("%.4f",lmargin))
self.f.write('>\n')
def close(self):
"""Write the trailing information and closes the file"""
self.f.write('</section>\n')
if len(self.photo_list) > 0:
self.f.write('<data>\n')
@ -119,8 +142,8 @@ class AbiWordDoc(TextDoc):
self.f.write('<image dataid="')
self.f.write(tag)
width = cnv("%.3f",act_width)
height = cnv("%.3f",act_height)
width = fl2txt("%.3f",act_width)
height = fl2txt("%.3f",act_height)
self.f.write('" props="width:%sin; ' % width)
self.f.write('height:%sin"/>' % height)
@ -136,9 +159,9 @@ class AbiWordDoc(TextDoc):
self.f.write('text-align:center;')
else:
self.f.write('text-align:justify;')
rmargin = cnv("%.4f",float(style.get_right_margin())/2.54)
lmargin = cnv("%.4f",float(style.get_left_margin())/2.54)
indent = cnv("%.4f",float(style.get_first_indent())/2.54)
rmargin = fl2txt("%.4f",float(style.get_right_margin())/2.54)
lmargin = fl2txt("%.4f",float(style.get_left_margin())/2.54)
indent = fl2txt("%.4f",float(style.get_first_indent())/2.54)
self.f.write(' margin-right:%sin;' % rmargin)
self.f.write(' margin-left:%sin;' % lmargin)
self.f.write(' tabstops:%sin/L;' % lmargin)
@ -193,7 +216,7 @@ class AbiWordDoc(TextDoc):
self.f.write('; font-style:italic')
color = font.get_color()
if color != (0,0,0):
self.f.write('; color:%2x%2x%2x' % color)
self.f.write('; color:%02x%02x%02x' % color)
if font.get_underline():
self.f.write('; text-decoration:underline')
self.f.write('">')
@ -212,7 +235,7 @@ class AbiWordDoc(TextDoc):
self.f.write('; font-style:italic')
color = font.get_color()
if color != (0,0,0):
self.f.write('; color:%2x%2x%2x' % color)
self.f.write('; color:%02x%02x%02x' % color)
if font.get_underline():
self.f.write('; text-decoration:underline')
self.f.write('">')

View File

@ -18,6 +18,10 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Provides the interface to allow a person to add a media object to the database.
"""
#-------------------------------------------------------------------------
#
# Standard python modules
@ -124,7 +128,6 @@ class AddMediaObject:
see if the file exists. If it does, the imgae is loaded into
the preview window.
"""
filename = self.file_text.get_text()
basename = os.path.basename(filename)
(root,ext) = os.path.splitext(basename)

View File

@ -17,6 +17,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
The AddSpouse module provides the AddSpouse class that allows the user to
add a new spouse to the active person.
"""
#-------------------------------------------------------------------------
#

View File

@ -17,6 +17,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
The AddrEdit module provides the AddressEditor class. This provides a
mechanism for the user to edit address information.
"""
#-------------------------------------------------------------------------
#
@ -33,6 +37,7 @@ import libglade
import const
import utils
import Date
import RelLib
from intl import gettext
_ = gettext
@ -44,7 +49,7 @@ _ = gettext
#-------------------------------------------------------------------------
class AddressEditor:
"""
Displays a dialog that allows the user to edit a address.
Displays a dialog that allows the user to edit an address.
"""
def __init__(self,parent,addr):
"""
@ -110,7 +115,7 @@ class AddressEditor:
def ok_clicked(self,obj):
"""
Called when the OK button is pressed. Gets data from the
form and updates the Address data structure
form and updates the Address data structure.
"""
date = self.addr_start.get_text()
street = self.street.get_text()
@ -122,7 +127,7 @@ class AddressEditor:
priv = self.priv.get_active()
if self.addr == None:
self.addr = Address()
self.addr = RelLib.Address()
self.addr.setSourceRefList(self.srcreflist)
self.parent.plist.append(self.addr)
@ -154,27 +159,7 @@ class AddressEditor:
self.check(self.addr.getNote,self.addr.setNote,note)
self.check(self.addr.getPrivacy,self.addr.setPrivacy,priv)
# if self.addr.getState() != state:
# self.addr.setState(state)
# self.parent.lists_changed = 1
# if self.addr.getStreet() != street:
# self.addr.setStreet(street)
# self.parent.lists_changed = 1
# if self.addr.getCountry() != country:
# self.addr.setCountry(country)
# self.parent.lists_changed = 1
# if self.addr.getCity() != city:
# self.addr.setCity(city)
# self.parent.lists_changed = 1
# if self.addr.getPostal() != postal:
# self.addr.setPostal(postal)
# self.parent.lists_changed = 1
# if self.addr.getNote() != note:
# self.addr.setNote(note)
# self.parent.lists_changed = 1
# if self.addr.getPrivacy() != priv:
# self.addr.setPrivacy(priv)
# self.parent.lists_changed = 1
def src_changed(parent):
"""Sets the lists_changed flag of the parent object. Used as a callback
to the source editor, so the source editor can indicate a change."""
parent.lists_changed = 1

View File

@ -17,6 +17,10 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
The AttrEdit module provides the AddressEditor class. This provides a
mechanism for the user to edit address information.
"""
#-------------------------------------------------------------------------
#
@ -44,8 +48,18 @@ _ = gettext
#
#-------------------------------------------------------------------------
class AttributeEditor:
"""
Displays a dialog that allows the user to edit an attribute.
"""
def __init__(self,parent,attrib,title,list):
"""
Displays the dialog box.
parent - The class that called the Address editor.
attrib - The attribute that is to be edited
title - The title of the dialog box
list - list of options for the pop down menu
"""
self.parent = parent
self.attrib = attrib
self.top = libglade.GladeXML(const.dialogFile, "attr_edit")
@ -84,16 +98,20 @@ class AttributeEditor:
self.window.set_data("o",self)
self.top.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_attr_edit_ok_clicked" : self.on_attrib_edit_ok_clicked,
"on_attr_edit_ok_clicked" : self.on_ok_clicked,
"on_combo_insert_text" : utils.combo_insert_text,
"on_source_clicked" : self.on_attrib_source_clicked
"on_source_clicked" : self.on_source_clicked
})
def on_attrib_source_clicked(self,obj):
def on_source_clicked(self,obj):
"""Displays the SourceSelector, allowing sources to be edited"""
Sources.SourceSelector(self.srcreflist,self.parent,src_changed)
def on_attrib_edit_ok_clicked(self,obj):
def on_ok_clicked(self,obj):
"""
Called when the OK button is pressed. Gets data from the
form and updates the Attribute data structure.
"""
type = self.type_field.get_text()
value = self.value_field.get_text()
note = self.note_field.get_chars(0,-1)
@ -104,28 +122,27 @@ class AttributeEditor:
self.attrib.setSourceRefList(self.srcreflist)
self.parent.alist.append(self.attrib)
self.update_attrib(type,value,note,priv)
self.update(type,value,note,priv)
self.parent.redraw_attr_list()
utils.destroy_passed_object(obj)
def update_attrib(self,type,value,note,priv):
if self.attrib.getType() != const.save_pattr(type):
self.attrib.setType(const.save_pattr(type))
self.parent.lists_changed = 1
if self.attrib.getValue() != value:
self.attrib.setValue(value)
self.parent.lists_changed = 1
if self.attrib.getNote() != note:
self.attrib.setNote(note)
self.parent.lists_changed = 1
if self.attrib.getPrivacy() != priv:
self.attrib.setPrivacy(priv)
def check(self,get,set,data):
"""Compares a data item, updates if necessary, and sets the
parents lists_changed flag"""
if get() != data:
set(data)
self.parent.lists_changed = 1
def update(self,type,value,note,priv):
"""Compares the data items, and updates if necessary"""
ntype = const.save_pattr(type)
self.check(self.attrib.getType,self.attrib.setType,ntype)
self.check(self.attrib.getValue,self.attrib.setValue,value)
self.check(self.attrib.getNote,self.attrib.setNote,note)
self.check(self.attrib.getPrivacy,self.attrib.setPrivacy,priv)
def src_changed(parent):
"""Sets the lists_changed flag of the parent object. Used as a callback
to the source editor, so the source editor can indicate a change."""
parent.lists_changed = 1

View File

@ -61,7 +61,7 @@ _AM9_32_43 = ((15 * _HALAKIM_PER_HOUR) + 589)
#-------------------------------------------------------------------------
#
#
# Conversion tables
#
#-------------------------------------------------------------------------
monthsPerYear = [
@ -76,7 +76,7 @@ yearOffset = [
#-------------------------------------------------------------------------
#
#
# Tasks
#
#-------------------------------------------------------------------------
@ -99,6 +99,7 @@ def sdn_to_french(sdn):
def sdn_to_gregorian(sdn):
"""Converts an SDN number to a gregorial date"""
if sdn <= 0:
return (0,0,0)
@ -133,7 +134,7 @@ def sdn_to_gregorian(sdn):
return (year,month,day)
def gregorian_to_sdn(iyear,imonth,iday):
"""Converts a gregorian date to an SDN number"""
# check for invalid dates
if iyear==0 or iyear<-4714 or imonth<=0 or imonth>12 or iday<=0 or iday>31:
return 0
@ -164,6 +165,7 @@ def gregorian_to_sdn(iyear,imonth,iday):
def sdn_to_julian(sdn):
"""Converts an SDN number to a Julian date"""
if sdn <= 0 :
return (0,0,0)
@ -193,6 +195,7 @@ def sdn_to_julian(sdn):
return (year,month,day)
def julian_to_sdn(iyear,imonth,iday):
"""Converts a Julian calendar date to an SDN number"""
# check for invalid dates
if iyear==0 or iyear<-4713 or imonth<=0 or imonth>12 or iday<=0 or iday>31:
@ -329,6 +332,7 @@ def FindStartOfYear(year):
return (pMetonicCycle, pMetonicYear, pMoladDay, pMoladHalakim, pTishri1)
def sdn_to_jewish(sdn):
"""Converts an SDN number to a Julian calendar date"""
if sdn <= _H_SDN_OFFSET :
return (0,0,0)
@ -439,6 +443,7 @@ def sdn_to_jewish(sdn):
def jewish_to_sdn(year, month, day):
"""Converts a Jewish calendar date to an SDN number"""
if year <= 0 or day <= 0 or day > 30 :
return 0

View File

@ -461,12 +461,18 @@ class SingleDate:
retval = str(self.year)
elif self.year == UNDEF:
retval = _mname[self.month]
else:
retval = "%s %d" % (_mname[self.month],self.year)
else:
try:
retval = "%s %d" % (_mname[self.month],self.year)
except:
retval = "**** %d %d %d ****" % (self.year,self.month,self.day)
elif self.month == UNDEF:
retval = str(self.year)
else:
month = _mname[self.month]
try:
month = _mname[self.month]
except:
month = "<ILLEGAL MONTH>"
if self.year == UNDEF:
retval = "%s %d, ????" % (month,self.day)
else:
@ -830,6 +836,8 @@ class SingleDate:
else:
self.setMonthVal(matches[1])
self.setYearVal(matches[2])
if self.getMonth() > 13:
raise Date.Error
return 1
match = SingleDate.fmt3.match(text)

View File

@ -1222,7 +1222,7 @@ def birth_dates_in_order(list):
for i in range(len(list)):
child = list[i]
bday = child.getBirth().getDateObj()
child_date = sort.build_sort_event(bday)
child_date = sort.build_sort_date(bday)
if (child_date == "99999999"):
continue
if (prev_date <= child_date): # <= allows for twins
@ -1246,13 +1246,13 @@ def reorder_child_list(person, list):
return(list)
# Build the person's date string once
person_bday = sort.build_sort_event(person.getBirth().getDateObj())
person_bday = sort.build_sort_date(person.getBirth().getDateObj())
# First, see if the person needs to be moved forward in the list
index = list.index(person)
target = index
for i in range(index-1, -1, -1):
other_bday = sort.build_sort_event(list[i].getBirth().getDateObj())
other_bday = sort.build_sort_date(list[i].getBirth().getDateObj())
if (other_bday == "99999999"):
continue;
if (person_bday < other_bday):
@ -1261,7 +1261,7 @@ def reorder_child_list(person, list):
# Now try moving to a later position in the list
if (target == index):
for i in range(index, len(list)):
other_bday = sort.build_sort_event(list[i].getBirth().getDateObj())
other_bday = sort.build_sort_date(list[i].getBirth().getDateObj())
if (other_bday == "99999999"):
continue;
if (person_bday > other_bday):

View File

@ -50,17 +50,17 @@ class Find:
})
self.top = self.xml.get_widget("find")
self.entry = self.xml.get_widget("entry1")
self.combo = self.xml.get_widget("combo")
self.entry = self.xml.get_widget("entry")
if Config.autocomp:
self.entry.connect_object("insert-text",utils.combo_insert_text,self.combo)
self.combo.disable_activate()
self.nlist = [("","")]
for n in plist:
n1 = n.getPrimaryName().getName()
n2 = string.lower(n1)
self.nlist.append((n2,n1))
self.nlist.sort()
self.entry.connect("insert-text",self.insert_text)
self.next = self.xml.get_widget("next")
nlist = [""]
for n in plist:
nlist.append(n.getPrimaryName().getName())
nlist.sort()
self.combo.set_popdown_strings(nlist)
self.top.editable_enters(self.entry)
def find_next(self):
@ -133,3 +133,84 @@ class Find:
def on_prev_clicked(self,obj):
"""Callback for dialog box that causes the previous person to be found"""
self.find_prev()
#-------------------------------------------------------------------------
#
# Sets up a delayed (0.005 sec) handler for text completion. Text
# completion cannot be handled directly in this routine because, for
# some reason, the select_region() function doesn't work when called
# from signal handlers. Go figure.
#
# Thanks to iain@nodata.demon.co.uk (in mail from 1999) for the idea
# to use a timer to get away from the problems with signal handlers
# and the select_region function.
#
#-------------------------------------------------------------------------
def insert_text(self,entry,new_text,new_text_len,i_dont_care):
# One time setup to clear selected region when user moves on
if (not entry.get_data("signal_set")):
entry.set_data("signal_set",1)
entry.signal_connect("focus_out_event", self.lost_focus, entry)
# Nuke the current timer if the user types fast enough
timer = entry.get_data("timer");
if (timer):
gtk.timeout_remove(timer)
# Setup a callback timer so we can operate outside of a signal handler
timer = gtk.timeout_add(5, self.timer_callback, entry)
entry.set_data("timer", timer);
#-------------------------------------------------------------------------
#
# The entry box entry field lost focus. Go clear any selection. Why
# this form of a select_region() call works in a signal handler and
# the other form doesn't is a mystery.
#
#-------------------------------------------------------------------------
def lost_focus(self,entry,a,b):
entry.select_region(0, 0)
#-------------------------------------------------------------------------
#
# The workhorse routine of file completion. This routine grabs the
# current text of the entry box, and grubs through the list item
# looking for any case insensitive matches. This routine relies on
# public knowledge of the GtkEntry data structure, not on any private
# data.
#
# These three completion routines have only one gramps specific hook,
# and can be easily ported to any program.
#
#-------------------------------------------------------------------------
def timer_callback(self,entry):
# Clear any timer
timer = entry.get_data("timer");
if (timer):
gtk.timeout_remove(timer)
# Get the user's text
typed = entry.get_text()
if (not typed):
return
typed_lc = string.lower(typed)
# Walk the GtkList in the entry box
for nl,n in self.nlist:
if (not nl):
continue
# If equal, no need to add any text
if (typed_lc == nl):
return
# If typed text is a substring of the label text, then fill in
# the entry field with the full text (and correcting
# capitalization), and then select all the characters that
# don't match. With the user's enxt keystroke these will be
# replaced if they are incorrect.
if (string.find(nl,typed_lc) == 0):
entry.set_text(n)
entry.set_position(len(typed))
entry.select_region(len(typed), -1)
return

View File

@ -328,7 +328,8 @@ class MediaView:
oref.setReference(photo)
try:
id = photo.getId()
name = RelImage.import_media_object(tfile,self.path,id)
path = self.db.getSavePath()
name = RelImage.import_media_object(tfile,path,id)
if name != None and name != "":
photo.setPath(name)
except:

View File

@ -149,7 +149,6 @@ class PlaceView:
for a in self.sort_arrow:
a.hide()
arrow = self.sort_arrow[column]
if self.sort_col == column:
if self.sort_direct == GTK.SORT_DESCENDING:
self.sort_direct = GTK.SORT_ASCENDING

View File

@ -2656,7 +2656,7 @@ information.</text>
<title_color>125,104,74</title_color>
<text_color>0,0,0</text_color>
<background_color>225,219,197</background_color>
<logo_background_color>191,191,191</logo_background_color>
<logo_background_color>225,220,197</logo_background_color>
<textbox_color>255,255,255</textbox_color>
<logo_image>gramps.png</logo_image>
<watermark_image>splash.jpg</watermark_image>
@ -2674,7 +2674,7 @@ information.</text>
<title>Researcher Information</title>
<title_color>125,104,74</title_color>
<background_color>225,220,197</background_color>
<logo_background_color>191,191,191</logo_background_color>
<logo_background_color>225,220,197</logo_background_color>
<logo_image>gramps.png</logo_image>
<widget>
@ -3200,7 +3200,7 @@ contribute.
Please enjoy using GRAMPS.</text>
<background_color>225,220,197</background_color>
<logo_background_color>191,191,191</logo_background_color>
<logo_background_color>225,220,197</logo_background_color>
<textbox_color>255,255,255</textbox_color>
<text_color>0,0,0</text_color>
<title_color>125,104,74</title_color>

View File

@ -152,45 +152,19 @@
</child>
<widget>
<class>Placeholder</class>
</widget>
<widget>
<class>GtkCombo</class>
<name>combo</name>
<value_in_list>False</value_in_list>
<ok_if_empty>True</ok_if_empty>
<case_sensitive>False</case_sensitive>
<use_arrows>True</use_arrows>
<use_arrows_always>False</use_arrows_always>
<items></items>
<class>GtkEntry</class>
<name>entry</name>
<can_focus>True</can_focus>
<has_focus>True</has_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>10</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkEntry</class>
<child_name>GtkCombo:entry</child_name>
<name>entry1</name>
<can_focus>True</can_focus>
<has_focus>True</has_focus>
<signal>
<name>insert_text</name>
<handler>on_combo_insert_text</handler>
<object>combo</object>
<last_modification_time>Wed, 12 Dec 2001 01:27:32 GMT</last_modification_time>
</signal>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
</widget>
</widget>
<widget>
<class>Placeholder</class>
</widget>
</widget>
</widget>

View File

@ -1,5 +1,5 @@
[Desktop Entry]
Name=Gramps
Name=Genealogy (Gramps)
Name[sv]=Gramps
Comment=Genealogy Program
Comment[sv]=Ett släktforskningsprogram

Binary file not shown.

View File

@ -1289,8 +1289,8 @@ def redisplay_person_list(person):
gender,bday.getQuoteDate(),
dday.getQuoteDate(),
sort.build_sort_name(name),
sort.build_sort_event(bday),
sort.build_sort_event(dday)])
sort.build_sort_date(bday),
sort.build_sort_date(dday)])
person_list.set_row_data(0,pos)
@ -1302,8 +1302,8 @@ def redisplay_person_list(person):
gender,bday.getQuoteDate(),
dday.getQuoteDate(),
sort.build_sort_name(name),
sort.build_sort_event(bday),
sort.build_sort_event(dday)])
sort.build_sort_date(bday),
sort.build_sort_date(dday)])
person_list.set_row_data(0,pos2)
@ -1720,8 +1720,8 @@ def apply_filter():
bday = person.getBirth().getDateObj()
dday = person.getDeath().getDateObj()
sort_bday = sort.build_sort_event(bday)
sort_dday = sort.build_sort_event(dday)
sort_bday = sort.build_sort_date(bday)
sort_dday = sort.build_sort_date(dday)
qbday = bday.getQuoteDate()
qdday = dday.getQuoteDate()
pid = person.getId()

View File

@ -48,6 +48,7 @@ active_person = None
db = None
styles = StyleSheet()
style_sheet_list = None
topDialog = None
#------------------------------------------------------------------------
#

View File

@ -48,6 +48,7 @@ active_person = None
db = None
styles = StyleSheet()
style_sheet_list = None
topDialog = None
#------------------------------------------------------------------------
#
@ -277,7 +278,6 @@ def report(database,person):
global active_person
global topDialog
global glade_file
global db
global style_sheet_list

View File

@ -45,6 +45,7 @@ active_person = None
db = None
styles = StyleSheet()
style_sheet_list = None
topDialog = None
#------------------------------------------------------------------------
#

View File

@ -78,29 +78,6 @@ fromtoRegexp = re.compile(r"\s*FROM\s+@#D([^@]+)@\s*(.*)\s+TO\s+@#D([^@]+)@\s*(.
#
#
#-------------------------------------------------------------------------
def find_file(fullname,altpath):
if os.path.isfile(fullname):
type = utils.get_mime_type(fullname)
if type[0:6] != "image/":
return ""
else:
return fullname
other = altpath + os.sep + os.path.basename(fullname)
if os.path.isfile(other):
type = utils.get_mime_type(other)
if type[0:6] != "image/":
return ""
else:
return other
else:
return ""
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def importData(database, filename):
global callback
@ -199,6 +176,41 @@ class GedcomParser:
self.update(self.file_obj,file)
self.code = 0
self.search_paths = []
try:
f = open("/etc/fstab","r")
for line in f.readlines():
paths = string.split(line)
if len(paths) < 3:
continue
first = string.strip(paths[0])
if first[0] == '#':
continue
if string.upper(paths[2]) in ["VFAT","FAT","NTFS"]:
self.search_paths.append(paths[1])
f.close()
except:
pass
def find_file(self,fullname,altpath):
fullname = string.replace(fullname,'\\','/')
if os.path.isfile(fullname):
return fullname
other = os.path.join(altpath,os.path.basename(fullname))
if os.path.isfile(other):
return other
if len(fullname) > 3:
if fullname[1] == ':':
fullname = fullname[2:]
for path in self.search_paths:
other = os.path.join(path,os.path.basename(fullname))
if os.path.isfile(other):
return other
return ""
else:
return ""
def update(self,field,text):
field.set_text(text)
@ -311,7 +323,6 @@ class GedcomParser:
def parse_record(self):
while 1:
matches = self.get_next()
if matches[2] == "FAM":
if self.fam_count % 10 == 0:
self.update(self.families_obj,str(self.fam_count))
@ -333,9 +344,9 @@ class GedcomParser:
self.indi_count = self.indi_count + 1
self.person = self.db.findPerson(matches[1],self.pmap)
self.parse_individual()
elif matches[2] == "SUBM":
elif matches[2] in ["SUBM","SUBN"]:
self.ignore_sub_junk(1)
elif matches[1] == "SUBM":
elif matches[1] in ["SUBM","SUBN"]:
self.ignore_sub_junk(1)
elif matches[2] == "SOUR":
self.parse_source(matches[1],1)
@ -354,13 +365,36 @@ class GedcomParser:
noteobj.set(text + self.parse_continue_data())
self.parse_note_data(1)
elif matches[2] == "OBJE":
self.ignore_sub_junk(2)
self.ignore_sub_junk(1)
elif matches[1] == "TRLR":
self.backup()
return
else:
self.barf(1)
def parse_cause(self,event,level):
while 1:
matches = self.get_next()
if int(matches[0]) < level:
self.backup()
return
elif matches[1] == "SOUR":
source_ref = SourceRef()
if matches[2] and matches[2][0] != "@":
self.localref = self.localref + 1
ref = "gsr%d" % self.localref
s = self.db.findSource(ref,self.smap)
source_ref.setBase(s)
s.setTitle('Imported Source #%d' % self.localref)
s.setNote(matches[2] + self.parse_continue_data())
self.ignore_sub_junk(2)
else:
source_ref.setBase(self.db.findSource(matches[2],self.smap))
self.parse_source_reference(source_ref,level+1)
event.addSourceRef(source_ref)
else:
self.barf(1)
def parse_note_data(self,level):
while 1:
matches = self.get_next()
@ -507,13 +541,17 @@ class GedcomParser:
self.person.setPafUid(matches[2])
elif matches[1] == "ALIA":
aka = Name()
names = nameRegexp.match(matches[2]).groups()
if names[0]:
aka.setFirstName(names[0])
if names[1]:
aka.setSurname(names[1])
if names[2]:
aka.setSuffix(names[2])
match = nameRegexp.match(matches[2])
if match:
names = match.groups()
if names[0]:
aka.setFirstName(names[0])
if names[1]:
aka.setSurname(names[1])
if names[2]:
aka.setSuffix(names[2])
else:
aka.setFirstName(matches[2])
self.person.addAlternateName(aka)
elif matches[1] == "OBJE":
if matches[2] and matches[2][0] == '@':
@ -621,7 +659,7 @@ class GedcomParser:
self.person.addAttribute(attr)
else:
self.person.addEvent(event)
elif matches[1] in ["AFN","CHAN","REFN","SOUR"]:
elif matches[1] in ["AFN","CHAN","REFN","SOUR","ASSO"]:
self.ignore_sub_junk(2)
elif matches[1] in ["ANCI","DESI","RIN","RFN"]:
pass
@ -716,11 +754,10 @@ class GedcomParser:
url.set_path(file)
url.set_description(title)
self.person.addUrl(url)
elif form in photo_types:
path = find_file(file,self.dir_path)
else:
path = self.find_file(file,self.dir_path)
if path == "":
self.warn(_("Could not import %s: either the file could not be found, or it was not a valid image")\
% file + "\n")
self.warn(_("Could not import %s") % file + "\n")
else:
photo = Photo()
photo.setPath(path)
@ -730,9 +767,6 @@ class GedcomParser:
oref = ObjectRef()
oref.setReference(photo)
self.person.addPhoto(oref)
else:
self.warn(_("Could not import %s: currently an unknown file type") % \
file + "\n")
def parse_source_object(self,source,level):
form = ""
@ -755,11 +789,10 @@ class GedcomParser:
else:
self.barf(level+1)
if form in photo_types:
path = find_file(file,self.dir_path)
if form:
path = self.find_file(file,self.dir_path)
if path == "":
self.warn(_("Could not import %s: either the file could not be found, or it was not a valid image")\
% file + "\n")
self.warn(_("Could not import %s") % file + "\n")
else:
photo = Photo()
photo.setPath(path)
@ -769,9 +802,6 @@ class GedcomParser:
oref = ObjectRef()
oref.setReference(photo)
source.addPhoto(oref)
else:
self.warn(_("Could not import %s: currently an unknown file type") % \
file + "\n")
def parse_family_object(self,level):
form = ""
@ -794,10 +824,10 @@ class GedcomParser:
else:
self.barf(level+1)
if form in photo_types:
path = find_file(file,self.dir_path)
if form:
path = self.find_file(file,self.dir_path)
if path == "":
self.warn("Could not import %s: the file could not be found\n" % file)
self.warn(_("Could not import %s") % file)
else:
photo = Photo()
photo.setPath(path)
@ -807,8 +837,6 @@ class GedcomParser:
oref = ObjectRef()
oref.setReference(photo)
self.family.addPhoto(photo)
else:
self.warn("Could not import %s: current an unknown file type\n" % file)
def parse_residence(self,address,level):
while 1:
@ -888,7 +916,7 @@ class GedcomParser:
ord.setDateObj(self.extract_date(matches[2]))
elif matches[1] == "FAMC":
ord.setFamily(self.db.findFamily(matches[2],self.fmap))
elif matches[1] == ["PLAC", "STAT", "SOUR", "NOTE" ]:
elif matches[1] in ["PLAC", "STAT", "SOUR", "NOTE" ]:
self.ignore_sub_junk(level+1)
else:
self.barf(level+1)
@ -914,9 +942,8 @@ class GedcomParser:
name = matches[2]
event.setName(name)
elif matches[1] == "DATE":
foo = self.extract_date(matches[2])
event.setDateObj(foo)
elif matches[1] == ["TIME","ADDR","AGE","AGNC","STAT","TEMP","OBJE"]:
event.setDateObj(self.extract_date(matches[2]))
elif matches[1] in ["TIME","ADDR","AGE","AGNC","STAT","TEMP","OBJE"]:
self.ignore_sub_junk(level+1)
elif matches[1] == "SOUR":
source_ref = SourceRef()
@ -951,6 +978,7 @@ class GedcomParser:
elif matches[1] == "CAUS":
info = matches[2] + self.parse_continue_data()
event.setCause(info)
self.parse_cause(event,level+1)
elif matches[1] == "NOTE":
info = matches[2] + self.parse_continue_data()
if note == "":
@ -979,7 +1007,7 @@ class GedcomParser:
break
elif matches[1] == "DATE":
event.setDateObj(self.extract_date(matches[2]))
elif matches[1] == ["TIME","ADDR","AGE","AGNC","STAT","TEMP","OBJE"]:
elif matches[1] in ["TIME","ADDR","AGE","AGNC","STAT","TEMP","OBJE"]:
self.ignore_sub_junk(level+1)
elif matches[1] == "SOUR":
source_ref = SourceRef()
@ -1017,9 +1045,13 @@ class GedcomParser:
self.placemap[val] = place
event.setPlace(place)
self.ignore_sub_junk(level+1)
elif matches[1] == "TYPE":
# eventually do something intelligent here
pass
elif matches[1] == "CAUS":
info = matches[2] + self.parse_continue_data()
event.setCause(info)
self.parse_cause(event,level+1)
elif matches[1] == "NOTE":
info = matches[2] + self.parse_continue_data()
if note == "":
@ -1072,7 +1104,7 @@ class GedcomParser:
else:
name = matches[2]
attr.setName(name)
elif matches[1] == ["CAUS", "DATE","TIME","ADDR","AGE","AGNC","STAT","TEMP","OBJE"]:
elif matches[1] in ["CAUS", "DATE","TIME","ADDR","AGE","AGNC","STAT","TEMP","OBJE"]:
self.ignore_sub_junk(level+1)
elif matches[1] == "SOUR":
source_ref = SourceRef()
@ -1127,7 +1159,11 @@ class GedcomParser:
event.setName(matches[2])
elif matches[1] == "DATE":
event.setDateObj(self.extract_date(matches[2]))
elif matches[1] == ["TIME","AGE","AGNC","CAUS","ADDR","STAT","TEMP","HUSB","WIFE","OBJE"]:
elif matches[1] == "CAUS":
info = matches[2] + self.parse_continue_data()
event.setCause(info)
self.parse_cause(event,level+1)
elif matches[1] in ["TIME","AGE","AGNC","ADDR","STAT","TEMP","HUSB","WIFE","OBJE"]:
self.ignore_sub_junk(level+1)
elif matches[1] == "SOUR":
source_ref = SourceRef()
@ -1318,22 +1354,12 @@ class GedcomParser:
self.update(self.created_obj,matches[2])
elif matches[1] == "VERS":
self.update(self.version_obj,matches[2])
elif matches[1] == "CORP":
elif matches[1] in ["CORP","DATA","SUBM","SUBN","COPR","FILE","LANG"]:
self.ignore_sub_junk(2)
elif matches[1] == "DATA":
self.ignore_sub_junk(2)
elif matches[1] == "SUBM":
pass
elif matches[1] == "SUBN":
pass
elif matches[1] == "DEST":
if genby == "GRAMPS":
self.gedsource = self.gedmap.get_from_source_tag(matches[2])
self.broken_conc = self.gedsource.get_conc()
elif matches[1] == "FILE":
self.ignore_sub_junk(2)
elif matches[1] == "COPR":
pass
elif matches[1] == "CHAR":
if matches[2] == "UNICODE" or matches[2] == "UTF-8" or \
matches[2] == "UTF8":
@ -1348,8 +1374,6 @@ class GedcomParser:
self.ignore_sub_junk(2)
elif matches[1] == "_SCHEMA":
self.parse_ftw_schema(2)
elif matches[1] == "LANG":
pass
elif matches[1] == "PLAC":
self.parse_place_form(2)
elif matches[1] == "DATE":
@ -1496,6 +1520,7 @@ class GedcomParser:
dateobj.set(data)
else:
dateobj.set(text)
return dateobj
#-------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -17,25 +17,39 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
Provides sorting routines for use in GRAMPS. Since these functions are
intended to provide fast sorting, they tend to bypass access methods,
and directly use class members. For this reason, care needs to be taken
to make sure these remain in sync with the rest of the design.
"""
#-------------------------------------------------------------------------
#
# Imported Modules
#
#-------------------------------------------------------------------------
import string
from Date import compare_dates, UNDEF
import Date
#-------------------------------------------------------------------------
#
#
# Functions
#
#-------------------------------------------------------------------------
def build_sort_name(n):
"""Builds a name from a RelLib.Name instance that is suitable for
use as a sort key in a GtkCList. The name is converted to upper case
to provide for case-insenstive sorting"""
return "%-25s%-30s%s" % \
(string.upper(n.Surname),string.upper(n.FirstName),string.upper(n.Suffix))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def build_sort_event(n):
def build_sort_date(n):
"""Builds a date from a Date.Date instance that is suitable for
use as a sort key in a GtkCList. The resultant string is in the format
of YYYYMMDD. Unknown values are given as all nines, so that the
appear at the end"""
y = n.start.year
if y < 0:
y = 9999
@ -47,110 +61,32 @@ def build_sort_event(n):
d = 99
return "%04d%02d%02d" % (y,m,d)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def fast_name_sort(list):
nlist = map(build_sort_name,list)
nlist.sort()
return map(lambda(key,x): x, nlist)
def by_last_name(first, second):
"""Sort routine for comparing two last names. If last names are equal,
uses the given name and suffix"""
u = string.upper
name1 = first.PrimaryName
name2 = second.PrimaryName
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def reverse_name_sort(list):
nlist = map(build_sort_name,list)
nlist.sort()
nlist.reverse()
return map(lambda(key,x): x, nlist)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def fast_birth_sort(list):
nlist = map(build_sort_event,list)
nlist.sort()
return map(lambda(key,x): x, nlist)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def reverse_birth_sort(list):
nlist = map(build_sort_event,list)
nlist.sort()
nlist.reverse()
return map(lambda(key,x): x, nlist)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def fast_death_sort(list):
nlist = map(build_sort_event,list)
nlist.sort()
return map(lambda(key,x): x, nlist)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def reverse_death_sort(list):
nlist = map(build_sort_event,list)
nlist.sort()
nlist.reverse()
return map(lambda(key,x): x, nlist)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def by_last_name(first, second) :
name1 = first.getPrimaryName()
name2 = second.getPrimaryName()
fsn = string.upper(name1.getSurname())
ssn = string.upper(name2.getSurname())
fsn = u(name1.Surname)
ssn = u(name2.Surname)
if fsn == ssn :
ffn = string.upper(name1.getFirstName())
sfn = string.upper(name2.getFirstName())
ffn = u(name1.FirstName)
sfn = u(name2.FirstName)
if ffn == sfn :
return cmp(string.upper(name1.getSuffix()), string.upper(name2.getSuffix()))
return cmp(u(name1.Suffix), u(name2.Suffix))
else :
return cmp(ffn, sfn)
else :
return cmp(fsn, ssn)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def by_last_name_backwards(first, second) :
return by_last_name(second,first)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def by_birthdate(first, second) :
"""Sort routine for comparing two people by birth dates. If the birth dates
are equal, sorts by name"""
date1 = first.getBirth().getDateObj()
date2 = second.getBirth().getDateObj()
val = compare_dates(date1,date2)
val = Date.compare_dates(date1,date2)
if val == 0:
return by_last_name(first,second)
return val