updated support for readonly files

svn: r948
This commit is contained in:
Don Allingham 2002-05-01 22:37:18 +00:00
parent 72ac1d8853
commit 9de33f73cd
9 changed files with 305 additions and 286 deletions

View File

@ -65,13 +65,8 @@ _ = gettext
#-------------------------------------------------------------------------
class ImageSelect:
#---------------------------------------------------------------------
#
# __init__ - Creates an edit window. Associates a person with the
# window.
#
#---------------------------------------------------------------------
def __init__(self, path, db):
"""Creates an edit window. Associates a person with the window."""
self.path = path;
self.db = db
self.dataobj = None
@ -85,13 +80,13 @@ class ImageSelect:
"should be overrridden"
pass
#-------------------------------------------------------------------------
#
# create_add_dialog - Create the gnome dialog for selecting a new
# photo and entering its description.
#
#-------------------------------------------------------------------------
def create_add_dialog(self):
"""Create the gnome dialog for selecting a new photo and entering
its description."""
if self.path == '':
return
self.glade = libglade.GladeXML(const.imageselFile,"imageSelect")
window = self.glade.get_widget("imageSelect")
self.fname = self.glade.get_widget("fname")
@ -109,13 +104,8 @@ class ImageSelect:
window.editable_enters(self.description)
window.show()
#-------------------------------------------------------------------------
#
# on_name_changed - The filename has changed. Verify it and load
# the picture.
#
#-------------------------------------------------------------------------
def on_name_changed(self, obj):
"""The filename has changed. Verify it and load the picture."""
filename = self.fname.get_text()
basename = os.path.basename(filename)
@ -134,12 +124,8 @@ class ImageSelect:
else:
self.image.load_file(Utils.find_icon(type))
#-------------------------------------------------------------------------
#
# savephoto - Save the photo in the dataobj object. (Required function)
#
#-------------------------------------------------------------------------
def on_savephoto_clicked(self, obj):
"""Save the photo in the dataobj object. (Required function)"""
filename = self.glade.get_widget("photosel").get_full_path(0)
description = self.description.get_text()
@ -169,13 +155,15 @@ class ImageSelect:
if type[0:5] == "image":
if self.external.get_active() == 0:
name = RelImage.import_media_object(filename,self.path,mobj.getId())
name = RelImage.import_media_object(filename,self.path,
mobj.getId())
mobj.setLocal(1)
else:
if self.external.get_active() == 1:
name = filename
else:
name = RelImage.import_media_object(filename,self.path,mobj.getId())
name = RelImage.import_media_object(filename,self.path,
mobj.getId())
mobj.setLocal(1)
mobj.setPath(name)
@ -204,17 +192,15 @@ class Gallery(ImageSelect):
('text/uri-list',0,2),
('application/x-rootwin-drop',0,1)]
icon_list.drag_dest_set(GTK.DEST_DEFAULT_ALL, t, GDK.ACTION_COPY | GDK.ACTION_MOVE)
icon_list.connect("drag_data_received", self.on_photolist_drag_data_received)
if path:
icon_list.drag_dest_set(GTK.DEST_DEFAULT_ALL, t,
GDK.ACTION_COPY | GDK.ACTION_MOVE)
icon_list.connect("drag_data_received",
self.on_photolist_drag_data_received)
icon_list.drag_source_set(GDK.BUTTON1_MASK|GDK.BUTTON3_MASK,t,
GDK.ACTION_COPY | GDK.ACTION_MOVE)
icon_list.connect("drag_data_get", self.on_photolist_drag_data_get)
# Be paranoid - development only error messages
assert dataobj.addPhoto, "Gallery data object must contain an addPhoto routine."
assert dataobj.getPhotoList, "Gallery data object must contain an getPhotoList routine."
icon_list.connect("drag_data_get",
self.on_photolist_drag_data_get)
# Remember arguments
self.path = path;
@ -225,31 +211,23 @@ class Gallery(ImageSelect):
self.selectedIcon = -1
self.currentImages = []
#-------------------------------------------------------------------------
#
# savephoto - Save the photo in the dataobj object. (Required function)
#
#-------------------------------------------------------------------------
def savephoto(self, photo):
"""Save the photo in the dataobj object. (Required function)"""
self.db.addObject(photo)
oref = ObjectRef()
oref.setReference(photo)
self.dataobj.addPhoto(oref)
self.add_thumbnail(oref)
#-------------------------------------------------------------------------
#
# add_thumbnail - Scale the image and add it to the IconList.
#
#-------------------------------------------------------------------------
def add_thumbnail(self, photo):
"""Scale the image and add it to the IconList."""
object = photo.getReference()
name = Utils.thumb_path(self.db.getSavePath(),object)
try:
thumb = GdkImlib.Image(name)
except IOError,msg:
gnome.ui.GnomeErrorDialog(_("Could not import %s - %s") % (name,msg))
emsg = _("Could not import %s - %s") % (name,msg)
gnome.ui.GnomeErrorDialog(emsg)
return
self.icon_cache.append(thumb)
description = object.getDescription()
@ -257,14 +235,10 @@ class Gallery(ImageSelect):
description = "%s..." % description[0:50]
self.icon_list.append_imlib(thumb,description)
#-------------------------------------------------------------------------
#
# load_images - clears the currentImages list to free up any cached
# Imlibs. Then add each photo in the place's list of photos to the
# photolist window.
#
#-------------------------------------------------------------------------
def load_images(self):
"""clears the currentImages list to free up any cached
Imlibs. Then add each photo in the place's list of photos to the
photolist window."""
self.icon_list.freeze()
self.icon_list.clear()
self.icon_cache = []
@ -272,12 +246,8 @@ class Gallery(ImageSelect):
self.add_thumbnail(photo)
self.icon_list.thaw()
#-------------------------------------------------------------------------
#
# on_photo_select_icon - User clicked on a photo. Remember which one.
#
#-------------------------------------------------------------------------
def on_photo_select_icon(self, obj,iconNumber,event):
"""User clicked on a photo. Remember which one."""
self.selectedIcon = iconNumber
def on_photolist_drag_data_received(self,w, context, x, y, data, info, time):
@ -378,23 +348,14 @@ class Gallery(ImageSelect):
id = ref.getReference().getId()
selection_data.set(selection_data.target, 8, id)
#-------------------------------------------------------------------------
#
# on_add_photo_clicked - User wants to add a new photo. Create a
# dialog to find out which photo they want.
#
#-------------------------------------------------------------------------
def on_add_photo_clicked(self, obj):
"""User wants to add a new photo. Create a dialog to find out
which photo they want."""
self.create_add_dialog()
#-------------------------------------------------------------------------
#
# on_delete_photo_clicked - User wants to delete a new photo.
# Remove it from the displayed thumbnails, and remove it from the
# dataobj photo list.
#
#-------------------------------------------------------------------------
def on_delete_photo_clicked(self, obj):
"""User wants to delete a new photo. Remove it from the displayed
thumbnails, and remove it from the dataobj photo list."""
icon = self.selectedIcon
if icon != -1:
self.icon_list.remove(icon)
@ -405,13 +366,9 @@ class Gallery(ImageSelect):
self.selectedIcon = 0
self.icon_list.select_icon(0)
#-------------------------------------------------------------------------
#
# on_button_press_event - Look for right-clicks on a
# picture and create a popup menu of the available actions.
#
#-------------------------------------------------------------------------
def on_button_press_event(self, obj, event):
"""Look for right-clicks on a picture and create a popup
menu of the available actions."""
icon = self.selectedIcon
if icon == -1:
return
@ -422,10 +379,11 @@ class Gallery(ImageSelect):
item = gtk.GtkTearoffMenuItem()
item.show()
menu.append(item)
Utils.add_menuitem(menu,_("View in the default viewer"),None,self.popup_view_photo)
Utils.add_menuitem(menu,_("View in the default viewer"),
None,self.popup_view_photo)
object = photo.getReference()
if object.getMimeType()[0:5] == "image":
Utils.add_menuitem(menu,_("Edit with the GIMP"),\
Utils.add_menuitem(menu,_("Edit with the GIMP"),
None,self.popup_edit_photo)
Utils.add_menuitem(menu,_("Edit Object Properties"),None,
self.popup_change_description)
@ -434,45 +392,31 @@ class Gallery(ImageSelect):
self.popup_convert_to_private)
menu.popup(None,None,None,0,0)
#-------------------------------------------------------------------------
#
# popup_view_photo - Open this picture in a picture viewer
#
#-------------------------------------------------------------------------
def popup_view_photo(self, obj):
"""Open this picture in a picture viewer"""
photo = self.dataobj.getPhotoList()[self.selectedIcon]
Utils.view_photo(photo.getReference())
#-------------------------------------------------------------------------
#
# popup_edit_photo - Open this picture in a picture editor
#
#-------------------------------------------------------------------------
def popup_edit_photo(self, obj):
"""Open this picture in a picture editor"""
photo = self.dataobj.getPhotoList()[self.selectedIcon]
if os.fork() == 0:
os.execvp(const.editor,[const.editor, photo.getReference().getPath()])
os.execvp(const.editor,[const.editor,
photo.getReference().getPath()])
#-------------------------------------------------------------------------
#
# popup_convert_to_private - Copy this picture into gramps private
# database instead of leaving it as an external data object.
#
#-------------------------------------------------------------------------
def popup_convert_to_private(self, obj):
"""Copy this picture into gramps private database instead of
leaving it as an external data object."""
photo = self.dataobj.getPhotoList()[self.selectedIcon]
object = photo.getReference()
name = RelImage.import_media_object(object.getPath(),self.path,object.getId())
name = RelImage.import_media_object(object.getPath(),self.path,
object.getId())
object.setPath(name)
object.setLocal(1)
#-------------------------------------------------------------------------
#
# popup_change_description - Bring up a window allowing the user
# to edit the description of a picture.
#
#-------------------------------------------------------------------------
def popup_change_description(self, obj):
"""Bring up a window allowing the user to edit the description
of a picture."""
if self.selectedIcon >=0:
photo = self.dataobj.getPhotoList()[self.selectedIcon]
LocalMediaProperties(photo,self.path)
@ -491,7 +435,8 @@ class LocalMediaProperties:
self.lists_changed = 0
fname = self.object.getPath()
self.change_dialog = libglade.GladeXML(const.imageselFile,"change_description")
self.change_dialog = libglade.GladeXML(const.imageselFile,
"change_description")
descr_window = self.change_dialog.get_widget("description")
pixmap = self.change_dialog.get_widget("pixmap")
self.attr_type = self.change_dialog.get_widget("attr_type")
@ -510,7 +455,9 @@ class LocalMediaProperties:
self.change_dialog.get_widget("path").set_text("<local>")
else:
self.change_dialog.get_widget("path").set_text(fname)
self.change_dialog.get_widget("type").set_text(Utils.get_mime_description(mtype))
mt = Utils.get_mime_description(mtype)
self.change_dialog.get_widget("type").set_text(mt)
self.change_dialog.get_widget("notes").insert_defaults(photo.getNote())
self.change_dialog.signal_autoconnect({
"on_cancel_clicked" : Utils.destroy_passed_object,

View File

@ -61,7 +61,7 @@ class ImgManip:
os.system(cmd)
def fmt_data(self,cnv):
cmd = "%s '%s' '%s:-'" % (const.convert,cnv,self.src)
cmd = "%s '%s' '%s:-'" % (const.convert,self.src,cnv)
r,w = popen2.popen2(cmd)
buf = r.read()
r.close()

View File

@ -1083,8 +1083,8 @@ class Person:
return self.AltFamilyList
def addAltFamily(self,family,mrel,frel):
"""adds a Family to the alternate family list, indicating the relationship
to the mother (mrel) and the father (frel)"""
"""adds a Family to the alternate family list, indicating the
relationship to the mother (mrel) and the father (frel)"""
self.AltFamilyList.append((family,mrel,frel))
def removeAltFamily(self,family):

View File

@ -93,7 +93,8 @@ class AbiWordDoc(TextDoc):
self.f.write('<data>\n')
for file_tuple in self.photo_list:
file = file_tuple[0]
base = "%s/%s_png" % (os.path.dirname(file),os.path.basename(file))
base = "%s/%s_png" % (os.path.dirname(file),
os.path.basename(file))
tag = string.replace(base,'.','_')
img = ImgManip.ImgManip(file)

View File

@ -90,7 +90,7 @@
<last_modification_time>Sat, 16 Dec 2000 23:53:36 GMT</last_modification_time>
</signal>
<stock_item>GNOMEUIINFO_MENU_NEW_ITEM</stock_item>
<label>_New File</label>
<label>_New Database</label>
</widget>
<widget>

View File

@ -135,6 +135,9 @@ class Gramps:
self.database.set_pprefix(GrampsCfg.pprefix)
if arg != None:
if string.upper(arg[-3:]) == "GED":
self.read_gedcom(arg)
else:
self.read_file(arg)
elif GrampsCfg.lastfile and GrampsCfg.autoload:
self.auto_save_load(GrampsCfg.lastfile)
@ -143,7 +146,8 @@ class Gramps:
DbPrompter.DbPrompter(self,0)
if GrampsCfg.autosave_int != 0:
Utils.enable_autosave(self.autosave_database,GrampsCfg.autosave_int)
Utils.enable_autosave(self.autosave_database,
GrampsCfg.autosave_int)
self.database.setResearcher(GrampsCfg.get_researcher())
@ -716,6 +720,13 @@ class Gramps:
def loadsaved_file(self):
self.read_file(self.nname)
def read_gedcom(self,filename):
import ReadGedcom
self.topWindow.set_title("%s - GRAMPS" % filename)
ReadGedcom.importData(self.database,filename)
self.full_update()
def read_file(self,filename):
base = os.path.basename(filename)
if base == const.indexFile:
@ -804,6 +815,9 @@ class Gramps:
def autosave_database(self):
path = self.database.getSavePath()
if not path:
return
filename = os.path.normpath(path)
Utils.clear_timer()
@ -1201,6 +1215,7 @@ class Gramps:
fileSelector.show()
def on_revert_activate(self,obj):
if self.database.getSavePath() != "":
msg = _("Do you wish to abandon your changes and "
"revert to the last saved database?")

View File

@ -1,4 +1,3 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
@ -23,6 +22,7 @@ import cStringIO
ANSEL_ERROR = "ANSEL Error"
_s1 = {
0xC3 : { 0xB8 : 0xF8 , 0x98 : 0xD8},
0xEA : { ord('A') : 0xC5, ord('a') : 0xE5 },
0xE8 : { ord('A') : 0xC4, ord('E') : 0xCB, ord('I') : 0xCF, ord('O') : 0xD6,
ord('U') : 0xDC, ord('a') : 0xE4, ord('e') : 0xEB, ord('i') : 0xEF,
@ -59,7 +59,9 @@ _t1 = {
0xF2 : (chr(0xE1), 'o'), 0xF3 : (chr(0xE2), 'o'), 0xF4 : (chr(0xE3), 'o'),
0xF5 : (chr(0xE4), 'o'), 0xF6 : (chr(0xE8), 'o'), 0xF9 : (chr(0xE1), 'u'),
0xFA : (chr(0xE2), 'u'), 0xFB : (chr(0xE3), 'u'), 0xFC : (chr(0xE8), 'u'),
0xFD : (chr(0xE2), 'y'), 0xFF : (chr(0xE8), 'y')
0xFD : (chr(0xE2), 'y'), 0xFF : (chr(0xE8), 'y'),
0xF8 : (chr(0xC3), chr(0xB8)),
0xD8 : (chr(0xC3), chr(0x98)),
}
_s0 = {
@ -67,16 +69,18 @@ _s0 = {
0xB3 : 0xF8, 0xA5 : 0xC6, 0xB5 : 0xE6, 0xBA : 0xF0 }
_t0 = {
0xDF : chr(0xCF), 0xDE : chr(0xA4), 0xFE : chr(0xB4), 0xD8 : chr(0xA2),
0xF8 : chr(0xB3), 0xC6 : chr(0xA5), 0xE6 : chr(0xB5), 0xBA : chr(0xF0),
0xDF : chr(0xCF), 0xDE : chr(0xA4), 0xFE : chr(0xB4),
0xC6 : chr(0xA5), 0xE6 : chr(0xB5), 0xBA : chr(0xF0),
0xB0 : chr(0xC0) }
#-------------------------------------------------------------------------
#
#
# Tasks
#
#-------------------------------------------------------------------------
def ansel_to_latin(s):
"""Converts an ANSEL encoded string to ISO-8859-1"""
buff = cStringIO.StringIO()
while s:
c0 = ord(s[0])
@ -85,7 +89,7 @@ def ansel_to_latin(s):
s = s[1:]
elif c0 > 127:
try:
if c0 >= 0xE0:
if c0 >= 0xC0:
c1 = ord(s[1])
head = chr(_s1[c0][c1])
s = s[2:]
@ -103,12 +107,8 @@ def ansel_to_latin(s):
buff.close()
return ans
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def latin_to_ansel(s):
"""converts a iso-8859-1 string to ansel encoding"""
buff = cStringIO.StringIO()
orig = s
while s:

View File

@ -20,26 +20,42 @@
"Import from GEDCOM"
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
import os
import re
import string
import const
import time
#-------------------------------------------------------------------------
#
# GTK/GNOME Modules
#
#-------------------------------------------------------------------------
import gtk
import gnome.ui
import libglade
import gnome.mime
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from RelLib import *
import Date
import latin_ansel
import latin_utf8
import intl
import Utils
from GedcomInfo import *
_ = intl.gettext
import os
import re
import string
import const
import Utils
import gtk
import gnome.ui
import libglade
import gnome.mime
ANSEL = 1
UNICODE = 2
@ -52,6 +68,11 @@ def nocnv(s):
photo_types = [ "jpeg", "bmp", "pict", "pntg", "tpic", "png", "gif",
"jpg", "tiff", "pcx" ]
#-------------------------------------------------------------------------
#
# GEDCOM events to GRAMPS events conversion
#
#-------------------------------------------------------------------------
ged2gramps = {}
for _val in const.personalConstantEvents.keys():
_key = const.personalConstantEvents[_val]
@ -64,6 +85,11 @@ for _val in const.familyConstantEvents.keys():
if _key != "":
ged2fam[_key] = _val
#-------------------------------------------------------------------------
#
# regular expressions
#
#-------------------------------------------------------------------------
intRE = re.compile(r"\s*(\d+)\s*$")
lineRE = re.compile(r"\s*(\d+)\s+(\S+)\s*(.*)$")
headRE = re.compile(r"\s*(\d+)\s+HEAD")
@ -166,7 +192,9 @@ class GedcomParser:
self.families_obj = window.get_widget("families")
self.people_obj = window.get_widget("people")
self.errors_obj = window.get_widget("errors")
self.close_done = window.get_widget('close_done')
self.error_text_obj = window.get_widget("error_text")
self.window = window
self.error_count = 0
self.error_text_obj.set_point(0)
self.error_text_obj.set_word_wrap(0)
@ -262,6 +290,7 @@ class GedcomParser:
self.backoff = 1
def parse_gedcom_file(self):
t = time.time()
self.index = 0
self.fam_count = 0
self.indi_count = 0
@ -272,6 +301,10 @@ class GedcomParser:
self.update(self.families_obj,str(self.fam_count))
self.update(self.people_obj,str(self.indi_count))
self.break_note_links()
t = time.time() - t
self.error_text_obj.insert_defaults(_('Import Complete: %d seconds') % t)
if self.close_done.get_active():
self.window.destroy()
def break_note_links(self):
for o in self.share_note:

View File

@ -41,7 +41,7 @@
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>10</padding>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
@ -51,7 +51,7 @@
<class>GtkHSeparator</class>
<name>hseparator4</name>
<child>
<padding>0</padding>
<padding>2</padding>
<expand>False</expand>
<fill>True</fill>
</child>
@ -60,7 +60,7 @@
<widget>
<class>GtkTable</class>
<name>table1</name>
<rows>7</rows>
<rows>8</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>0</row_spacing>
@ -201,126 +201,6 @@
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>file</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>created</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>version</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>families</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>4</top_attach>
<bottom_attach>5</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>people</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>5</top_attach>
<bottom_attach>6</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label11</name>
@ -347,30 +227,6 @@
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>errors</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>6</top_attach>
<bottom_attach>7</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label12</name>
@ -397,6 +253,78 @@
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>file</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>created</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>version</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>encoding</name>
@ -411,7 +339,7 @@
<top_attach>3</top_attach>
<bottom_attach>4</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
@ -420,6 +348,101 @@
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>families</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>4</top_attach>
<bottom_attach>5</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>people</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>5</top_attach>
<bottom_attach>6</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>errors</name>
<can_focus>True</can_focus>
<editable>False</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>6</top_attach>
<bottom_attach>7</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>close_done</name>
<can_focus>True</can_focus>
<label>Close window when complete</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>7</top_attach>
<bottom_attach>8</bottom_attach>
<xpad>5</xpad>
<ypad>2</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
</widget>
<widget>