Merge from 2.0.1
svn: r4666
This commit is contained in:
parent
62c65fb454
commit
d7ce524379
285
ChangeLog
285
ChangeLog
@ -1,6 +1,288 @@
|
||||
2005-05-23 Alex Roitman <shura@gramps-project.org>
|
||||
* various: merge changes made in gramps20 branch with main trunk.
|
||||
|
||||
2005-05-23 Don Allingham <don@gramps-project.org>
|
||||
* src/MergePeople.py: clean up and refactoring of code.
|
||||
* Release: Version 2.0.1 "None shall pass" released.
|
||||
|
||||
2005-05-23 Alex Roitman <shura@gramps-project.org>
|
||||
* src/po/ru.po: More tranlsated tips.
|
||||
|
||||
2005-05-23 Eero Tamminen <eerot@sf>
|
||||
* src/po/fi.po: Translate all fuzzy strings. Tips are still to be
|
||||
translated
|
||||
* src/plugins/StatisticsChart.py: Fix a typo in one string
|
||||
(I actually changed the string, but now it should actually be
|
||||
understandable i.e. something people can localize)
|
||||
* src/dates/Makefile.am, src/dates/Date_fi.py: Remove Finnish date
|
||||
parser. Unfortunately I don't have time either to fix DateParser.py
|
||||
regexps matches to be position independent or write the required
|
||||
(almost) duplicate code to Date_fi.py directly
|
||||
|
||||
2005-05-23 Jens Arvidsson <jya@sverige.nu>
|
||||
* src/po/sv.po: Translation update for version 2.0.1.
|
||||
|
||||
2005-05-22 Don Allingham <don@gramps-project.org>
|
||||
* src/MergePeople.py: merge improvements, merge data not merged before.
|
||||
|
||||
2005-05-22 Alex Roitman <shura@gramps-project.org>
|
||||
* src/ImageSelect.py (item_event): Do nothing if nothing is selected.
|
||||
* src/EditSource.py (button_press): Return if no data.
|
||||
* src/Sources.py (drag_data_get): Return if no data.
|
||||
* src/EditPerson.py (ev_drag_data_get,name_drag_data_get):
|
||||
Return if no data.
|
||||
* src/EditPlace.py (url_source_drag_data_get): Properly obtain data;
|
||||
return if no data.
|
||||
|
||||
2005-05-22 Julio Sanchez <jsanchez@users.sourceforge.net>
|
||||
* src/po/es.po: Updated translation for filters, tips still pending
|
||||
|
||||
2005-05-21 Don Allingham <don@gramps-project.org>
|
||||
* src/ChooseParents.py: handle the addition of a person correctly.
|
||||
Warn if the person just added is suppressed by the filter.
|
||||
* src/MergePeople.py: use __debug__ for print statements
|
||||
|
||||
2005-05-20 Don Allingham <don@gramps-project.org>
|
||||
* src/MergePeople.py: fixed name merging, incorporate Martin's
|
||||
patches.
|
||||
|
||||
2005-05-20 Eero Tamminen <eerot@sf>
|
||||
* src/po/fi.po: Merge PO file and (finally) translate the welcome
|
||||
message. Otherwise translation is not yet updated
|
||||
* src/data/gramps.desktop: Add Finnish translations
|
||||
|
||||
2005-05-20 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/WriteXML.py: Remove unnecessary database reads, so it does no
|
||||
longer crash when exporting a corrupt database.
|
||||
* src/WriteGedcom.py: Some hardening against corrupt database.
|
||||
|
||||
2005-05-20 Alex Roitman <shura@gramps-project.org>
|
||||
* src/SelectObject.py (on_select_row): Properly get mime type.
|
||||
* src/GrampsBSDDB.py (remove_object): Use correct key for transaction.
|
||||
* src/ImageSelect.py (add_thumbnail, on_delete_media_clicked):
|
||||
Identify canvas items by MediaRef instance, not by the handle of the
|
||||
referred MediaObject.
|
||||
* src/gramps_main.py (read_file): Remove set_resizable() calls.
|
||||
* src/MediaView.py (on_drag_drop): Remove drag_get_data() call
|
||||
as it was calling extraneous 'drag-data-received' signal.
|
||||
* src/ReadGedcom.py (parse_person_object,parse_family_object):
|
||||
Always add media references/objects, even if the files are not found
|
||||
(keep the warnings); set the note for the media references.
|
||||
* example/gedcom/sample.ged: Correct object format tags.
|
||||
|
||||
* src/ChooseParents.py (close_child_windows): Pass no arguments
|
||||
to child_window.close().
|
||||
|
||||
2005-05-19 Don Allingham <don@gramps-project.org>
|
||||
* src/DisplayModels.py: remove place column
|
||||
* src/MediaView.py: delete Place option
|
||||
* src/GrampsDbBase.py: new default for media columns
|
||||
* src/GrampsBSDDB.py: upgrade database version for media columns
|
||||
* src/MediaView.py: enable sorting by columns
|
||||
* src/DisplayModels.py: enable sorting by columns for MediaModel
|
||||
|
||||
2005-05-19 Alex Roitman <shura@gramps-project.org>
|
||||
* src/MergePeople.py (merge_family_pair): Properly use handles.
|
||||
* src/RelLib.py (SourceNote.replace_source_references): Properly
|
||||
replace references; (MediaBase.replace_media_references): Properly
|
||||
replace references.
|
||||
* src/MergeData.py: Correct comments.
|
||||
* src/mergedata.glade: Make information panes non-editable.
|
||||
* src/gramps.glade: Enclose date and place groups into tables,
|
||||
to allow proper widget order when using tab key.
|
||||
* src/EditSource.py (button_press): Properly test event names.
|
||||
* src/po/ru.po: Partial update for 2.0.1.
|
||||
|
||||
2005-05-19 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/GenericFilter.py: Catch invalid input in some filters;
|
||||
(old_names_2_class): Add one name for full 1.0.11 compatibility;
|
||||
(FilterParser): Properly catch invalid rule names and invalid
|
||||
module/class names.
|
||||
|
||||
2005-05-18 Don Allingham <don@gramps-project.org>
|
||||
* src/dates/Date_de.py: handle dates in the form of dd. mon year
|
||||
|
||||
2005-05-18 Richard Bos <radoeka@xs4all.nl>
|
||||
* src/data/gramps.desktop: Add Dutch strings.
|
||||
|
||||
2005-05-18 James Treacy <treacy@debian.org>
|
||||
* src/data/tips.xml: Update and rework.
|
||||
|
||||
2005-05-18 Alex Roitman <shura@gramps-project.org>
|
||||
* src/GenericFilter.py: Use class names for internal work; Rework
|
||||
ID-based filters to use gramps-id instead of a handle.
|
||||
* src/plugins/FilterEditor.py: Use class names for internal work.
|
||||
* src/po/template.po: Update for 2.0.1.
|
||||
* src/gramps_main.py (open_example): Add example database funciton.
|
||||
* NEWS: Update.
|
||||
* src/po/ru.po: Partial update for 2.0.1.
|
||||
|
||||
2005-05-18 Don Allingham <don@gramps-project.org>
|
||||
* src/ReadGedcom.py: grab description for birth and death events
|
||||
* src/WriteGedcom.py: export description for birth and death events
|
||||
* example/gedcom/sample.ged: add test case
|
||||
|
||||
2005-05-18 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/GrampsInMemDB.py: Emit the *-delete signals correctly.
|
||||
* src/GrampsDbBase.py: Emission of the *-update/*-add signals should not depend
|
||||
on the existance of a transaction.
|
||||
|
||||
2005-05-18 Don Allingham <don@gramps-project.org>
|
||||
* src/plugins/FilterEditor.py: sort entries in Add Rule dialog
|
||||
|
||||
2005-05-18 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/GrampsBSDDB.py, src/GrampsDbBase.py, src/GrampsInMemDB.py,
|
||||
src/RelLib.py: Catch invalid arguments instead of crashing.
|
||||
TODO: raise TypeError or HandleError instead of simply returning?
|
||||
|
||||
* src/plugins/TestcaseGenerator.py: Added debbuging helpers for signal emissions
|
||||
|
||||
2005-05-17 Don Allingham <don@gramps-project.org>
|
||||
* configure.in: bump up verison number to 2.1.0
|
||||
|
||||
2005-05-17 Alex Roitman <shura@gramps-project.org>
|
||||
* src/GenericFilter.py: Change filter rule names to make them consistent.
|
||||
* src/gramps_main.py: Change filter names to make them consistent.
|
||||
|
||||
* src/Date.py: Import gettext.
|
||||
* src/DateDisplay.py: Import gettext.
|
||||
* src/GenericFilter.py: Support existing custom_filters.xml files
|
||||
by adding an old2new mapping for names.
|
||||
|
||||
* src/AddSpouse.py (select_spouse_clicked): Display warning and
|
||||
provide a way to override when trying to add child/parent as a spouse.
|
||||
|
||||
2005-05-17 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/plugins/ImportGeneWeb.py (decode): Decode characters and named
|
||||
entities. Because gramps is not web browser based we can simply use
|
||||
unicode.
|
||||
|
||||
2005-05-16 Don Allingham <don@gramps-project.org>
|
||||
* src/PlaceView.py: select correct column for sorting
|
||||
* src/SourceView.py: select correct column for sorting
|
||||
* src/WriteGedcom.py: used 'replace' mode on iso-8859-1 string
|
||||
encoding conversion
|
||||
|
||||
2005-05-16 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/ReadGedcom.py (parse_trailer): Catch EOF to warn about premature
|
||||
EOF only once; Always close file; (parse_record): Properly catch
|
||||
premature EOF instead of unknown level 0 records; Support single line
|
||||
SOUR records; (parse_address): Support PHON and NOTE, ignore _NAME.
|
||||
|
||||
2005-05-16 Alex Roitman <shura@gramps-project.org>
|
||||
* src/ansel_utf8.py: Convert to Unix end-of-line.
|
||||
|
||||
* src/plugins/StatisticsChart.py: Minor stylistic corrections.
|
||||
* src/GenericFilter.py: Minor stylistic corrections.
|
||||
|
||||
* src/TarFile.py: Indent with spaces, remove string module.
|
||||
* src/RelImage.py: Remove unused string module.
|
||||
* src/SubstKeywords.py: Remove string module.
|
||||
|
||||
2005-05-16 Don Allingham <don@gramps-project.org>
|
||||
* src/FamilyView.py: fix reordering of children in family view
|
||||
|
||||
2005-05-15 Don Allingham <don@gramps-project.org>
|
||||
* src/ChooseParents.py: redraw window properly after person add
|
||||
* src/DisplayModels.py: provide sorting support
|
||||
* src/PlaceView.py: add sorting by columns
|
||||
* src/SourceView.py: add sorting by columns
|
||||
|
||||
2005-05-14 Don Allingham <don@gramps-project.org>
|
||||
* src/ReadGedcom.py: add a few more items to parse from Legacy
|
||||
generated GEDCOM files
|
||||
|
||||
2005-05-14 Alex Roitman <shura@gramps-project.org>
|
||||
* src/data/Makefile.am: Always install gramps.schemas and gramps.xml,
|
||||
with or without packager mode.
|
||||
|
||||
2005-05-14 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/GenericFilter.py (IsSiblingOfFilterMatch): Match only sibling,
|
||||
not the filterMatch; (HasEvent,HasFamilyEvent): Dont crash in filter
|
||||
editor.
|
||||
|
||||
* src/GenericFilter.py (HasTextMatchingSubstringOf, HasTextMatchingRegexpOf):
|
||||
Search media objects in full text search.
|
||||
* src/RelLib.py: Add GRAMPS ID to get_text_data_list so this field is
|
||||
usable in full text search; Dont crash if get_text_data_list contains
|
||||
None values instead of empty strings.
|
||||
|
||||
* src/EditPerson.py, src/AddMedia.py, src/ImageSelect.py, src/ReportUtils.py,
|
||||
src/SelectObject.py, src/plugins/Ancestors.py, src/plugins/IndivComplete.py,
|
||||
src/plugins/IndivSummary.py, src/plugins/WebPage.py, src/plugins/WriteCD.py:
|
||||
Dont crash with "note only" media object.
|
||||
|
||||
2005-05-13 Don Allingham <don@gramps-project.org>
|
||||
* src/plugins/ScratchPad.py: fix GdkAtom index problem with pygtk2.4
|
||||
|
||||
2005-05-13 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/GenericFilter.py (HasEvent,HasFamilyEvent): Correct filter rules
|
||||
|
||||
2005-05-13 Alex Roitman <shura@gramps-project.org>
|
||||
* src/DateDisplay.py (DateDisplayEn): Localize format names.
|
||||
|
||||
* src/get_strings: Support extracting strings from tips.xml file.
|
||||
* src/build_po: Process tips.xml file.
|
||||
* src/TipOfDay.py (TipOfDay.__init__): Use translated tips.
|
||||
* src/po/template.po: new translatable strings.
|
||||
|
||||
* src/DateEdit.py (parse_and_check): Display date as parsed on
|
||||
focus-out from the entry fields.
|
||||
|
||||
2005-05-13 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/SelectChild.py (on_save_child_clicked) Commit new parent family
|
||||
of child properly; correct handle/object mismatch; exec parent callback
|
||||
to do a proper redraw (closes #1201151)
|
||||
|
||||
* src/dates/Date_de.py: Register for all variants of german; Add other
|
||||
variants of month names for parser
|
||||
|
||||
* src/Date.py: Raise Exception.DateError on invalid arguments
|
||||
* src/DateParser.py: Catch DateError and use text only date as fallback
|
||||
* src/plugins/TestcaseGenerator.py: Handle DateError exception
|
||||
|
||||
* src/plugins/ImportGeneWeb.py: Distinguish unknown people
|
||||
|
||||
* src/DateDisplay.py: Allow B.C.E. in years to be localized
|
||||
* src/dates/Date_de.py: Some more translations including B.C.E.
|
||||
|
||||
2005-05-12 Don Allingham <don@gramps-project.org>
|
||||
* src/GrampsBSDDB.py: force database sync on transaction commit
|
||||
|
||||
2005-05-12 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/GenericFilter.py (ParamFilter.apply): Set parameter list before
|
||||
prepare (solves crash in full text search)
|
||||
* src/gramps_main.py: Enable full text search filters again
|
||||
|
||||
2005-05-12 Alex Roitman <shura@gramps-project.org>
|
||||
* src/plugins/Check.py (cleanup_missing_photos): Typo.
|
||||
* configure.in: Bump up the version number.
|
||||
* NEWS: Update.
|
||||
* src/ReportUtils.py (insert_images): Pass sizes to add_media_object;
|
||||
(married_str): Quit if no spouse.
|
||||
|
||||
* src/data/gramps.xml: Include different cases for file extensions.
|
||||
|
||||
* src/po/ru.po: Typo.
|
||||
|
||||
2005-05-12 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/plugins/TestcaseGenerator.py: Added generation of multiple date
|
||||
formats including invalid dates. This is displaying and reparsing every
|
||||
date to compare the result.
|
||||
* src/plugins/NavWebPage.py (HomePage): Dont crash on note only object
|
||||
* src/dates/Date_de.py: Updated translation
|
||||
|
||||
2005-05-11 Don Allingham <don@gramps-project.org>
|
||||
* src/ReadGedcom.py: coerce the name into a unicode value - if the wrong character
|
||||
encoding is indicated in the file, the screen display can get corrupted due to keys
|
||||
that aren't unicode values
|
||||
* src/dates/Date_de.py: first pass at a German date handler
|
||||
|
||||
2005-05-11 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||
* src/DateHandler.py: Fallback to "C" locale instead of the ISO
|
||||
format. This currently basically falls back to en, but this could
|
||||
be enhanced by a translated fallback parser later.
|
||||
|
||||
2005-05-11 Julio Sanchez <jsanchez@users.sourceforge.net>
|
||||
* src/po/es.po: remerge from 2.0.0
|
||||
|
||||
@ -34,6 +316,9 @@
|
||||
src/po/ru.po, src/po/sv.po, src/po/template.po:
|
||||
Merge changes made in gramps20 into HEAD.
|
||||
|
||||
2005-05-10 Don Allingham <don@gramps-project.org>
|
||||
* Release: Version 2.0.0 "The Bright Side of Life"" released.
|
||||
|
||||
2005-05-10 Don Allingham <don@gramps-project.org>
|
||||
* src/DbPrompter.py: add callback for progressbar
|
||||
* src/GrampsXMLDB.py: pass callback task
|
||||
|
11
NEWS
11
NEWS
@ -1,3 +1,14 @@
|
||||
Version 2.0.1 -- the "None shall pass" release
|
||||
* Example database function is back.
|
||||
* Entering incestuous relations is possible (with the warning).
|
||||
* Sorting in list views is back.
|
||||
* Better support for non-standard GEDCOM tags produced by Legacy.
|
||||
* ScratchPad works with pygtk2.4.
|
||||
* Full text search filters are back.
|
||||
* Date formats for non-localized dates.
|
||||
* Date localization for German.
|
||||
* TONS of bug fixes.
|
||||
|
||||
Version 2.0.0 -- the "The Bright Side of Life" release
|
||||
* Bug fixes
|
||||
* Translation updates.
|
||||
|
@ -7,8 +7,8 @@ AC_PREREQ(2.57)
|
||||
AC_INIT(gramps, 2.1.0, gramps-bugs@lists.sourceforge.net)
|
||||
AC_CONFIG_SRCDIR(src/gramps.py)
|
||||
AM_INIT_AUTOMAKE(1.6.3)
|
||||
dnl RELEASE=0.CVS$(head -c 10 ${srcdir}/ChangeLog | tr -d '-')
|
||||
RELEASE=1
|
||||
RELEASE=0.CVS$(head -c 10 ${srcdir}/ChangeLog | tr -d '-')
|
||||
dnl RELEASE=1
|
||||
|
||||
VERSIONSTRING=$VERSION
|
||||
if test x"$RELEASE" != "x"
|
||||
|
@ -60,9 +60,9 @@
|
||||
1 SEX M
|
||||
1 TITL Grand Poobah
|
||||
1 OBJE
|
||||
2 FROM jpeg
|
||||
2 FORM jpeg
|
||||
2 FILE foo/O0.jpg
|
||||
1 BIRT
|
||||
1 BIRT Edwin Michael Smith's Birth event
|
||||
2 DATE 24 MAY 1961
|
||||
2 PLAC San Jose, Santa Clara Co., CA
|
||||
1 OCCU
|
||||
@ -88,7 +88,7 @@
|
||||
2 SOUR @S1601@
|
||||
1 SEX F
|
||||
1 OBJE
|
||||
2 FROM jpeg
|
||||
2 FORM jpeg
|
||||
2 FILE foo/O0.jpg
|
||||
1 BIRT
|
||||
2 DATE 22 NOV 1933
|
||||
|
@ -159,8 +159,7 @@ class AddMediaObject:
|
||||
|
||||
if os.path.isfile(filename):
|
||||
mtype = GrampsMime.get_type(filename)
|
||||
|
||||
if mtype[0:5] == "image":
|
||||
if mtype and mtype.startswith("image"):
|
||||
image = RelImage.scale_image(filename,const.thumbScale)
|
||||
else:
|
||||
image = Utils.find_mime_type_pixbuf(mtype)
|
||||
|
@ -57,7 +57,7 @@ import DateHandler
|
||||
import Marriage
|
||||
import NameDisplay
|
||||
import GenericFilter
|
||||
from QuestionDialog import ErrorDialog
|
||||
from QuestionDialog import ErrorDialog, QuestionDialog2
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -114,7 +114,8 @@ class AddSpouse:
|
||||
name = NameDisplay.displayer.display(person)
|
||||
title = _("Choose Spouse/Partner of %s") % name
|
||||
|
||||
Utils.set_titles(self.glade.get_widget('spouseDialog'),
|
||||
self.window = self.glade.get_widget('spouseDialog')
|
||||
Utils.set_titles(self.window,
|
||||
self.glade.get_widget('title'),title,
|
||||
_('Choose Spouse/Partner'))
|
||||
|
||||
@ -254,14 +255,20 @@ class AddSpouse:
|
||||
_("A person cannot be linked as his/her spouse"))
|
||||
return
|
||||
|
||||
# don't do anything if adding a parent
|
||||
# display warning if adding a parent
|
||||
for (family_handle,frel,mrel) in self.person.get_parent_family_handle_list():
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
if spouse_id in [family.get_mother_handle(),family.get_father_handle()]:
|
||||
ErrorDialog(_("Error adding a spouse"),
|
||||
_("A person cannot be linked as his/her "
|
||||
"child's spouse"))
|
||||
return
|
||||
dialog = QuestionDialog2(
|
||||
_("Spouse is a parent"),
|
||||
_("The person selected as a spouse is a parent of the "
|
||||
"active person. Usually, this is a mistake. You may "
|
||||
"choose either to proceed with adding a spouse, or to "
|
||||
"return to the Choose Spouse dialog to fix the problem."),
|
||||
_("Proceed with adding"), _("Return to dialog"),
|
||||
self.window)
|
||||
if not dialog.run():
|
||||
return
|
||||
|
||||
# don't do anything if the marriage already exists
|
||||
for f in self.person.get_family_handle_list():
|
||||
@ -273,10 +280,16 @@ class AddSpouse:
|
||||
_("The spouse is already present in this family"))
|
||||
return
|
||||
if spouse_id in fam.get_child_handle_list():
|
||||
ErrorDialog(_("Error adding a spouse"),
|
||||
_("A person cannot be linked as his/her "
|
||||
"parent's spouse"))
|
||||
return
|
||||
dialog = QuestionDialog2(
|
||||
_("Spouse is a child"),
|
||||
_("The person selected as a spouse is a child of the "
|
||||
"active person. Usually, this is a mistake. You may "
|
||||
"choose either to proceed with adding a spouse, or to "
|
||||
"return to the Choose Spouse dialog to fix the problem."),
|
||||
_("Proceed with adding"), _("Return to dialog"),
|
||||
self.window)
|
||||
if not dialog.run():
|
||||
return
|
||||
|
||||
trans = self.db.transaction_begin()
|
||||
|
||||
|
@ -57,7 +57,7 @@ import Date
|
||||
import NameDisplay
|
||||
import DateHandler
|
||||
import GenericFilter
|
||||
from QuestionDialog import ErrorDialog
|
||||
from QuestionDialog import ErrorDialog, WarningDialog
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -90,6 +90,11 @@ class ChooseParents:
|
||||
self.parent_selected = 0
|
||||
self.renderer = gtk.CellRendererText()
|
||||
|
||||
db.connect('person-add', self.redraw)
|
||||
db.connect('person-update', self.redraw)
|
||||
db.connect('person-delete', self.redraw)
|
||||
db.connect('person-rebuild', self.redraw2)
|
||||
|
||||
# set default filters
|
||||
self.all_males_filter = GenericFilter.GenericFilter()
|
||||
self.all_males_filter.add_rule(GenericFilter.IsMale([]))
|
||||
@ -250,7 +255,7 @@ class ChooseParents:
|
||||
|
||||
def close_child_windows(self):
|
||||
for child_window in self.child_windows.values():
|
||||
child_window.close(None)
|
||||
child_window.close()
|
||||
self.child_windows = {}
|
||||
|
||||
def add_itself_to_menu(self):
|
||||
@ -278,6 +283,18 @@ class ChooseParents:
|
||||
"""Display the relevant portion of GRAMPS manual"""
|
||||
gnome.help_display('gramps-manual','gramps-edit-quick')
|
||||
|
||||
def redraw(self,handle_list):
|
||||
self.redrawf()
|
||||
self.redrawm()
|
||||
# self.father_model.rebuild_data()
|
||||
# self.mother_model.rebuild_data()
|
||||
|
||||
def redraw2(self):
|
||||
self.redrawf()
|
||||
self.redrawm()
|
||||
# self.father_model.rebuild_data()
|
||||
# self.mother_model.rebuild_data()
|
||||
|
||||
def redrawf(self):
|
||||
"""Redraws the potential father list"""
|
||||
self.father_model = PeopleModel.PeopleModel(self.db,self.father_filter)
|
||||
@ -505,19 +522,31 @@ class ChooseParents:
|
||||
if self.type == RelLib.Family.CIVIL_UNION:
|
||||
self.parent_relation_changed(self.prel)
|
||||
elif person.get_gender() == RelLib.Person.MALE:
|
||||
self.redrawf()
|
||||
path = self.father_model.on_get_path(handle)
|
||||
top_path = self.father_model.on_get_path(name)
|
||||
self.father_list.expand_row(top_path,0)
|
||||
self.father_selection.select_path(path)
|
||||
self.father_list.scroll_to_cell(path,None,1,0.5,0)
|
||||
try:
|
||||
path = self.father_model.on_get_path(handle)
|
||||
top_path = self.father_model.on_get_path(name)
|
||||
self.father_list.expand_row(top_path,0)
|
||||
self.father_selection.select_path(path)
|
||||
self.father_list.scroll_to_cell(path,None,1,0.5,0)
|
||||
except KeyError:
|
||||
WarningDialog(_("Added person is not visible"),
|
||||
_("The person you added is currently "
|
||||
"not visible due to the chosen filter. "
|
||||
"This may occur if you did not specify "
|
||||
"a birth date."))
|
||||
else:
|
||||
self.redrawm()
|
||||
path = self.mother_model.on_get_path(handle)
|
||||
top_path = self.mother_model.on_get_path(name)
|
||||
self.mother_list.expand_row(top_path,0)
|
||||
self.mother_selection.select_path(path)
|
||||
self.mother_list.scroll_to_cell(path,None,1,0.5,0)
|
||||
try:
|
||||
path = self.mother_model.on_get_path(handle)
|
||||
top_path = self.mother_model.on_get_path(name)
|
||||
self.mother_list.expand_row(top_path,0)
|
||||
self.mother_selection.select_path(path)
|
||||
self.mother_list.scroll_to_cell(path,None,1,0.5,0)
|
||||
except:
|
||||
WarningDialog(_("Added person is not visible"),
|
||||
_("The person you added is currently "
|
||||
"not visible due to the chosen filter. "
|
||||
"This may occur if you did not specify "
|
||||
"a birth date."))
|
||||
|
||||
def add_parent_clicked(self,obj):
|
||||
"""Called with the Add New Person button is pressed. Calls the QuickAdd
|
||||
|
26
src/Date.py
26
src/Date.py
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2004 Donald N. Allingham
|
||||
# Copyright (C) 2000-2005 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
|
||||
@ -25,6 +25,8 @@
|
||||
__author__ = "Donald N. Allingham"
|
||||
__version__ = "$Revision$"
|
||||
|
||||
from gettext import gettext as _
|
||||
from Errors import DateError
|
||||
from CalSdn import *
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -143,9 +145,9 @@ class Date:
|
||||
Comparison function. Allows the usage of equality tests.
|
||||
This allows you do run statements like 'date1 <= date2'
|
||||
"""
|
||||
if isinstance(other,Date):
|
||||
if isinstance(other,Date):
|
||||
return cmp(self.sortval,other.sortval)
|
||||
else:
|
||||
else:
|
||||
return -1
|
||||
|
||||
def is_equal(self,other):
|
||||
@ -233,6 +235,8 @@ class Date:
|
||||
"""
|
||||
Sets the modifier for the date.
|
||||
"""
|
||||
if val not in (MOD_NONE,MOD_BEFORE,MOD_AFTER,MOD_ABOUT,MOD_RANGE,MOD_SPAN,MOD_TEXTONLY):
|
||||
raise DateError("Invalid modifier")
|
||||
self.modifier = val
|
||||
|
||||
def get_quality(self):
|
||||
@ -250,6 +254,8 @@ class Date:
|
||||
"""
|
||||
Sets the quality selected for the date.
|
||||
"""
|
||||
if val not in (QUAL_NONE,QUAL_ESTIMATED,QUAL_CALCULATED):
|
||||
raise DateError("Invalid quality")
|
||||
self.quality = val
|
||||
|
||||
def get_calendar(self):
|
||||
@ -270,6 +276,8 @@ class Date:
|
||||
"""
|
||||
Sets the calendar selected for the date.
|
||||
"""
|
||||
if val not in (CAL_GREGORIAN,CAL_JULIAN,CAL_HEBREW,CAL_FRENCH,CAL_PERSIAN,CAL_ISLAMIC):
|
||||
raise DateError("Invalid calendar")
|
||||
self.calendar = val
|
||||
|
||||
def get_start_date(self):
|
||||
@ -427,6 +435,18 @@ class Date:
|
||||
|
||||
The sort value is recalculated.
|
||||
"""
|
||||
|
||||
if modifier in (MOD_NONE,MOD_BEFORE,MOD_AFTER,MOD_ABOUT) and len(value) < 4:
|
||||
raise DateError("Invalid value. Should be: (DD,MM,YY,slash)")
|
||||
if modifier in (MOD_RANGE,MOD_SPAN) and len(value) < 8:
|
||||
raise DateError("Invalid value. Should be: (DD,MM,YY,slash1,DD,MM,YY,slash2)")
|
||||
if modifier not in (MOD_NONE,MOD_BEFORE,MOD_AFTER,MOD_ABOUT,MOD_RANGE,MOD_SPAN,MOD_TEXTONLY):
|
||||
raise DateError("Invalid modifier")
|
||||
if quality not in (QUAL_NONE,QUAL_ESTIMATED,QUAL_CALCULATED):
|
||||
raise DateError("Invalid quality")
|
||||
if calendar not in (CAL_GREGORIAN,CAL_JULIAN,CAL_HEBREW,CAL_FRENCH,CAL_PERSIAN,CAL_ISLAMIC):
|
||||
raise DateError("Invalid calendar")
|
||||
|
||||
self.quality = quality
|
||||
self.modifier = modifier
|
||||
self.calendar = calendar
|
||||
|
@ -30,6 +30,7 @@ __version__ = "$Revision$"
|
||||
|
||||
import Date
|
||||
import locale
|
||||
from gettext import gettext as _
|
||||
|
||||
|
||||
class DateDisplay:
|
||||
@ -111,6 +112,8 @@ class DateDisplay:
|
||||
_mod_str = ("","before ","after ","about ","","","")
|
||||
|
||||
_qual_str = ("","estimated ","calculated ")
|
||||
|
||||
_bce_str = "%s B.C.E."
|
||||
|
||||
def __init__(self,format=None):
|
||||
self.display_cal = [
|
||||
@ -172,15 +175,19 @@ class DateDisplay:
|
||||
return "%s%s%s%s" % (qual_str,self._mod_str[mod],text,self.calendar[cal])
|
||||
|
||||
def _slash_year(self,val,slash):
|
||||
bc = ""
|
||||
if val < 0:
|
||||
val = - val
|
||||
bc = " B.C.E"
|
||||
# self._bce_str is a localizes string that prints B.C.E. at the apropriate place
|
||||
format_string = self._bce_str
|
||||
else:
|
||||
format_string = "%s"
|
||||
|
||||
if slash:
|
||||
return "%d/%d%s" % (val,(val%10)+1,bc)
|
||||
year = "%d/%d" % (val,(val%10)+1)
|
||||
else:
|
||||
return "%d%s" % (val,bc)
|
||||
year = "%d" % (val)
|
||||
|
||||
return format_string % year
|
||||
|
||||
def display_iso(self,date_val):
|
||||
# YYYY-MM-DD (ISO)
|
||||
@ -286,8 +293,8 @@ class DateDisplayEn(DateDisplay):
|
||||
"""
|
||||
|
||||
formats = (
|
||||
"YYYY-MM-DD (ISO)", "Numerical", "Month Day, Year",
|
||||
"MON DAY, YEAR", "Day Month Year", "DAY MON YEAR"
|
||||
_("YYYY-MM-DD (ISO)"), _("Numerical"), _("Month Day, Year"),
|
||||
_("MON DAY, YEAR"), _("Day Month Year"), _("DAY MON YEAR")
|
||||
)
|
||||
|
||||
def __init__(self,format=None):
|
||||
|
@ -146,6 +146,7 @@ class DateEdit:
|
||||
if text != self.text:
|
||||
self.text = text
|
||||
self.date_obj.copy(DateHandler.parser.parse(text))
|
||||
self.text_obj.set_text(DateHandler.displayer.display(self.date_obj))
|
||||
self.check()
|
||||
|
||||
def invoke_date_editor(self,obj):
|
||||
|
@ -80,7 +80,7 @@ def get_date_formats():
|
||||
try:
|
||||
return _lang_to_display[_lang].formats
|
||||
except:
|
||||
return DateDisplay.DateDisplay.formats
|
||||
return _lang_to_display["C"].formats
|
||||
|
||||
def set_format(value):
|
||||
try:
|
||||
@ -126,17 +126,19 @@ try:
|
||||
parser = _lang_to_parser[_lang]()
|
||||
except:
|
||||
print "Date parser for",_lang,"not available, using default"
|
||||
parser = DateParser.DateParser()
|
||||
parser = _lang_to_parser["C"]()
|
||||
|
||||
try:
|
||||
import GrampsKeys
|
||||
val = GrampsKeys.get_date_format(_lang_to_display[_lang].formats)
|
||||
except:
|
||||
val = 0
|
||||
try:
|
||||
val = GrampsKeys.get_date_format(_lang_to_display["C"].formats)
|
||||
except:
|
||||
val = 0
|
||||
|
||||
try:
|
||||
displayer = _lang_to_display[_lang](val)
|
||||
except:
|
||||
print "Date displayer for",_lang,"not available, using default"
|
||||
displayer = DateDisplay.DateDisplay(val)
|
||||
|
||||
displayer = _lang_to_display["C"](val)
|
||||
|
@ -44,7 +44,7 @@ import calendar
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import Date
|
||||
|
||||
from Errors import DateError
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Top-level module functions
|
||||
@ -587,5 +587,8 @@ class DateParser:
|
||||
Parses the text, returning a Date object.
|
||||
"""
|
||||
new_date = Date.Date()
|
||||
self.set_date(new_date,text)
|
||||
try:
|
||||
self.set_date(new_date,text)
|
||||
except DateError:
|
||||
new_date.set_as_text(text)
|
||||
return new_date
|
||||
|
@ -61,14 +61,30 @@ _codeset = locale.nl_langinfo(locale.CODESET)
|
||||
#-------------------------------------------------------------------------
|
||||
class BaseModel(gtk.GenericTreeModel):
|
||||
|
||||
def __init__(self,db):
|
||||
def __init__(self,db,scol=0,order=gtk.SORT_ASCENDING):
|
||||
gtk.GenericTreeModel.__init__(self)
|
||||
self.set_property("leak_references",False)
|
||||
self.db = db
|
||||
self.sort_func = self.smap[scol]
|
||||
self.sort_col = scol
|
||||
self.reverse = (order == gtk.SORT_DESCENDING)
|
||||
self.rebuild_data()
|
||||
|
||||
def set_sort_column(self,col):
|
||||
self.sort_func = self.smap[col]
|
||||
|
||||
def sort_keys(self):
|
||||
return []
|
||||
cursor = self.gen_cursor()
|
||||
sarray = []
|
||||
data = cursor.next()
|
||||
while data:
|
||||
sarray.append((self.sort_func(data[1]),data[0]))
|
||||
data = cursor.next()
|
||||
cursor.close()
|
||||
sarray.sort()
|
||||
if self.reverse:
|
||||
sarray.reverse()
|
||||
return map(lambda x: x[1], sarray)
|
||||
|
||||
def rebuild_data(self):
|
||||
if self.db.is_open():
|
||||
@ -255,9 +271,9 @@ class ChildModel(gtk.ListStore):
|
||||
#-------------------------------------------------------------------------
|
||||
class SourceModel(BaseModel):
|
||||
|
||||
def __init__(self,db):
|
||||
self.sort_keys = db.get_source_handles
|
||||
def __init__(self,db,scol=0,order=gtk.SORT_ASCENDING):
|
||||
self.map = db.source_map
|
||||
self.gen_cursor = db.get_source_cursor
|
||||
self.fmap = [
|
||||
self.column_title,
|
||||
self.column_id,
|
||||
@ -267,7 +283,15 @@ class SourceModel(BaseModel):
|
||||
self.column_change,
|
||||
self.column_handle,
|
||||
]
|
||||
BaseModel.__init__(self,db)
|
||||
self.smap = [
|
||||
self.column_title,
|
||||
self.column_id,
|
||||
self.column_author,
|
||||
self.column_abbrev,
|
||||
self.column_pubinfo,
|
||||
self.sort_change,
|
||||
]
|
||||
BaseModel.__init__(self,db,scol,order)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
@ -293,6 +317,8 @@ class SourceModel(BaseModel):
|
||||
def column_change(self,data):
|
||||
return unicode(time.strftime(_date_format,time.localtime(data[8])),
|
||||
_codeset)
|
||||
def sort_change(self,data):
|
||||
return time.localtime(data[8])
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -301,8 +327,8 @@ class SourceModel(BaseModel):
|
||||
#-------------------------------------------------------------------------
|
||||
class PlaceModel(BaseModel):
|
||||
|
||||
def __init__(self,db):
|
||||
self.sort_keys = db.get_place_handles
|
||||
def __init__(self,db,scol=0,order=gtk.SORT_ASCENDING):
|
||||
self.gen_cursor = db.get_place_cursor
|
||||
self.map = db.place_map
|
||||
self.fmap = [
|
||||
self.column_name,
|
||||
@ -318,7 +344,21 @@ class PlaceModel(BaseModel):
|
||||
self.column_change,
|
||||
self.column_handle,
|
||||
]
|
||||
BaseModel.__init__(self,db)
|
||||
self.smap = [
|
||||
self.column_name,
|
||||
self.column_id,
|
||||
self.column_parish,
|
||||
self.column_postal_code,
|
||||
self.column_city,
|
||||
self.column_county,
|
||||
self.column_state,
|
||||
self.column_country,
|
||||
self.column_longitude,
|
||||
self.column_latitude,
|
||||
self.column_change,
|
||||
self.column_handle,
|
||||
]
|
||||
BaseModel.__init__(self,db,scol,order)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
@ -374,6 +414,9 @@ class PlaceModel(BaseModel):
|
||||
except:
|
||||
return u''
|
||||
|
||||
def sort_change(self,data):
|
||||
return time.localtime(data[11])
|
||||
|
||||
def column_change(self,data):
|
||||
return unicode(time.strftime(_date_format,time.localtime(data[11])),
|
||||
_codeset)
|
||||
@ -385,8 +428,8 @@ class PlaceModel(BaseModel):
|
||||
#-------------------------------------------------------------------------
|
||||
class MediaModel(BaseModel):
|
||||
|
||||
def __init__(self,db):
|
||||
self.sort_keys = db.get_media_object_handles
|
||||
def __init__(self,db,scol=0,order=gtk.SORT_ASCENDING):
|
||||
self.gen_cursor = db.get_media_cursor
|
||||
self.map = db.media_map
|
||||
|
||||
self.fmap = [
|
||||
@ -396,10 +439,18 @@ class MediaModel(BaseModel):
|
||||
self.column_path,
|
||||
self.column_change,
|
||||
self.column_date,
|
||||
self.column_place,
|
||||
self.column_handle,
|
||||
]
|
||||
BaseModel.__init__(self,db)
|
||||
self.smap = [
|
||||
self.column_description,
|
||||
self.column_id,
|
||||
self.column_mime,
|
||||
self.column_path,
|
||||
self.sort_change,
|
||||
self.column_date,
|
||||
self.column_handle,
|
||||
]
|
||||
BaseModel.__init__(self,db,scol,order)
|
||||
|
||||
def on_get_n_columns(self):
|
||||
return len(self.fmap)+1
|
||||
@ -424,16 +475,12 @@ class MediaModel(BaseModel):
|
||||
return unicode(DateHandler.displayer.display(data[9]))
|
||||
return u''
|
||||
|
||||
def column_place(self,data):
|
||||
if data[10]:
|
||||
place = self.db.get_place_from_handle(data[10])
|
||||
if place:
|
||||
return place.get_title()
|
||||
return u''
|
||||
|
||||
def column_handle(self,data):
|
||||
return unicode(data[0])
|
||||
|
||||
def sort_change(self,data):
|
||||
return time.localtime(data[8])
|
||||
|
||||
def column_change(self,data):
|
||||
return unicode(time.strftime(_date_format,time.localtime(data[8])),
|
||||
_codeset)
|
||||
|
@ -225,6 +225,7 @@ class EditPerson:
|
||||
|
||||
# event display
|
||||
|
||||
<<<<<<< EditPerson.py
|
||||
self.event_box = ListBox.EventListBox(
|
||||
self, self.person, self.event_list, events_label,
|
||||
[event_add_btn,event_edit_btn,event_delete_btn])
|
||||
@ -244,6 +245,53 @@ class EditPerson:
|
||||
self.url_box = ListBox.UrlListBox(
|
||||
self, self.person, self.web_list, web_label,
|
||||
[web_add_btn, web_edit_btn, web_delete_btn])
|
||||
=======
|
||||
event_default = [ 'Event', 'Description', 'Date', 'Place' ]
|
||||
self.event_trans = TransTable.TransTable(event_default)
|
||||
evalues = {
|
||||
'Event' : (_('Event'),-1,150),
|
||||
'Description' : (_('Description'),-1,150),
|
||||
'Date' : (_('Date'),-1,100),
|
||||
'Place' : (_('Place'),-1,100)
|
||||
}
|
||||
|
||||
#if not self.db.readonly:
|
||||
# values = self.db.metadata.get('event_order',event_default)
|
||||
#else:
|
||||
values = event_default
|
||||
|
||||
etitles = []
|
||||
for val in values:
|
||||
etitles.append(evalues[val])
|
||||
|
||||
self.etree = ListModel.ListModel(self.event_list,etitles,
|
||||
self.on_event_select_row,
|
||||
self.on_event_update_clicked)
|
||||
|
||||
# attribute display
|
||||
atitles = [(_('Attribute'),-1,150),(_('Value'),-1,150)]
|
||||
self.atree = ListModel.ListModel(self.attr_list,atitles,
|
||||
self.on_attr_select_row,
|
||||
self.on_update_attr_clicked)
|
||||
|
||||
# address display
|
||||
ptitles = [(_('Date'),-1,150),(_('Address'),-1,150)]
|
||||
self.ptree = ListModel.ListModel(self.addr_list, ptitles,
|
||||
self.on_addr_select_row,
|
||||
self.on_update_addr_clicked)
|
||||
|
||||
# name display
|
||||
ntitles = [(_('Name'),-1,250),(_('Type'),-1,100)]
|
||||
self.ntree = ListModel.ListModel(self.name_list,ntitles,
|
||||
self.on_name_select_row)
|
||||
self.ntree.tree.connect('event',self.aka_double_click)
|
||||
|
||||
# web display
|
||||
wtitles = [(_('Path'),-1,250),(_('Description'),-1,100)]
|
||||
self.wtree = ListModel.ListModel(self.web_list,wtitles,
|
||||
self.on_web_select_row,
|
||||
self.on_update_url_clicked)
|
||||
>>>>>>> 1.194.2.7
|
||||
|
||||
self.place_list = self.pdmap.keys()
|
||||
self.place_list.sort()
|
||||
@ -400,7 +448,7 @@ class EditPerson:
|
||||
if progname and len(progname) > 1:
|
||||
Utils.add_menuitem(menu,_("Open in %s") % progname[1],
|
||||
photo,self.popup_view_photo)
|
||||
if mtype[0:5] == "image":
|
||||
if mtype and mtype.startswith("image"):
|
||||
Utils.add_menuitem(menu,_("Edit with the GIMP"),
|
||||
photo,self.popup_edit_photo)
|
||||
Utils.add_menuitem(menu,_("Edit Object Properties"),photo,
|
||||
@ -632,6 +680,75 @@ class EditPerson:
|
||||
def set_lds_seal(self,obj):
|
||||
self.lds_sealing.set_status(obj.get_active())
|
||||
|
||||
<<<<<<< EditPerson.py
|
||||
=======
|
||||
def name_drag_data_get(self,widget, context, sel_data, info, time):
|
||||
name = self.ntree.get_selected_objects()
|
||||
if not name:
|
||||
return
|
||||
bits_per = 8; # we're going to pass a string
|
||||
pickled = pickle.dumps(name[0]);
|
||||
data = str((DdTargets.NAME.drag_type,self.person.get_handle(),pickled));
|
||||
sel_data.set(sel_data.target, bits_per, data)
|
||||
|
||||
def name_drag_begin(self, context, a):
|
||||
return
|
||||
icon = self.ntree.get_icon()
|
||||
t = self.ntree.tree
|
||||
(x,y) = icon.get_size()
|
||||
mask = gtk.gdk.Pixmap(self.window.window,x,y,1)
|
||||
mask.draw_rectangle(t.get_style().white_gc, True, 0,0,x,y)
|
||||
t.drag_source_set_icon(t.get_colormap(),icon,mask)
|
||||
|
||||
def name_drag_data_received(self,widget,context,x,y,sel_data,info,time):
|
||||
row = self.ntree.get_row_at(x,y)
|
||||
|
||||
if sel_data and sel_data.data:
|
||||
exec 'data = %s' % sel_data.data
|
||||
exec 'mytype = "%s"' % data[0]
|
||||
exec 'person = "%s"' % data[1]
|
||||
if mytype != DdTargets.NAME.drag_type:
|
||||
return
|
||||
elif person == self.person.get_handle():
|
||||
self.move_element(self.nlist,self.ntree.get_selected_row(),row)
|
||||
else:
|
||||
foo = pickle.loads(data[2]);
|
||||
for src in foo.get_source_references():
|
||||
base_handle = src.get_base_handle()
|
||||
newbase = self.db.get_source_from_handle(base_handle)
|
||||
src.set_base_handle(newbase.get_handle())
|
||||
|
||||
self.nlist.insert(row,foo)
|
||||
|
||||
self.lists_changed = True
|
||||
self.redraw_name_list()
|
||||
|
||||
def ev_drag_data_received(self,widget,context,x,y,sel_data,info,time):
|
||||
row = self.etree.get_row_at(x,y)
|
||||
|
||||
if sel_data and sel_data.data:
|
||||
exec 'data = %s' % sel_data.data
|
||||
exec 'mytype = "%s"' % data[0]
|
||||
exec 'person = "%s"' % data[1]
|
||||
if mytype != DdTargets.EVENT.drag_type:
|
||||
return
|
||||
elif person == self.person.get_handle():
|
||||
self.move_element(self.elist,self.etree.get_selected_row(),row)
|
||||
else:
|
||||
foo = pickle.loads(data[2]);
|
||||
for src in foo.get_source_references():
|
||||
base_handle = src.get_base_handle()
|
||||
newbase = self.db.get_source_from_handle(base_handle)
|
||||
src.set_base_handle(newbase.get_handle())
|
||||
place = foo.get_place_handle()
|
||||
if place:
|
||||
foo.set_place_handle(place.get_handle())
|
||||
self.elist.insert(row,foo.get_handle())
|
||||
|
||||
self.lists_changed = True
|
||||
self.redraw_event_list()
|
||||
|
||||
>>>>>>> 1.194.2.7
|
||||
def move_element(self,list,src,dest):
|
||||
if src == -1:
|
||||
return
|
||||
@ -639,6 +756,125 @@ class EditPerson:
|
||||
list.remove(obj)
|
||||
list.insert(dest,obj)
|
||||
|
||||
<<<<<<< EditPerson.py
|
||||
=======
|
||||
def ev_drag_data_get(self,widget, context, sel_data, info, time):
|
||||
ev = self.etree.get_selected_objects()
|
||||
if not ev:
|
||||
return
|
||||
bits_per = 8; # we're going to pass a string
|
||||
pickled = pickle.dumps(ev[0]);
|
||||
data = str((DdTargets.EVENT.drag_type,self.person.get_handle(),pickled));
|
||||
sel_data.set(sel_data.target, bits_per, data)
|
||||
|
||||
def ev_drag_begin(self, context, a):
|
||||
return
|
||||
icon = self.etree.get_icon()
|
||||
t = self.etree.tree
|
||||
(x,y) = icon.get_size()
|
||||
mask = gtk.gdk.Pixmap(self.window.window,x,y,1)
|
||||
mask.draw_rectangle(t.get_style().white_gc, True, 0,0,x,y)
|
||||
t.drag_source_set_icon(t.get_colormap(),icon,mask)
|
||||
|
||||
def url_drag_data_received(self,widget,context,x,y,sel_data,info,time):
|
||||
row = self.wtree.get_row_at(x,y)
|
||||
|
||||
if sel_data and sel_data.data:
|
||||
exec 'data = %s' % sel_data.data
|
||||
exec 'mytype = "%s"' % data[0]
|
||||
exec 'person = "%s"' % data[1]
|
||||
if mytype != DdTargets.URL.drag_type:
|
||||
return
|
||||
elif person == self.person.get_handle():
|
||||
self.move_element(self.ulist,self.wtree.get_selected_row(),row)
|
||||
else:
|
||||
foo = pickle.loads(data[2]);
|
||||
self.ulist.append(foo)
|
||||
self.lists_changed = True
|
||||
self.redraw_url_list()
|
||||
|
||||
def url_drag_begin(self, context, a):
|
||||
return
|
||||
|
||||
def url_drag_data_get(self,widget, context, sel_data, info, time):
|
||||
ev = self.wtree.get_selected_objects()
|
||||
|
||||
if len(ev):
|
||||
bits_per = 8; # we're going to pass a string
|
||||
pickled = pickle.dumps(ev[0]);
|
||||
data = str((DdTargets.URL.drag_type,self.person.get_handle(),pickled));
|
||||
sel_data.set(sel_data.target, bits_per, data)
|
||||
|
||||
def at_drag_data_received(self,widget,context,x,y,sel_data,info,time):
|
||||
row = self.atree.get_row_at(x,y)
|
||||
|
||||
if sel_data and sel_data.data:
|
||||
exec 'data = %s' % sel_data.data
|
||||
exec 'mytype = "%s"' % data[0]
|
||||
exec 'person = "%s"' % data[1]
|
||||
if mytype != DdTargets.ATTRIBUTE.drag_type:
|
||||
return
|
||||
elif person == self.person.get_handle():
|
||||
self.move_element(self.alist,self.atree.get_selected_row(),row)
|
||||
else:
|
||||
foo = pickle.loads(data[2]);
|
||||
for src in foo.get_source_references():
|
||||
base_handle = src.get_base_handle()
|
||||
newbase = self.db.get_source_from_handle(base_handle)
|
||||
src.set_base_handle(newbase.get_handle())
|
||||
self.alist.append(foo)
|
||||
self.lists_changed = True
|
||||
self.redraw_attr_list()
|
||||
|
||||
def at_drag_begin(self, context, a):
|
||||
return
|
||||
|
||||
def at_drag_data_get(self,widget, context, sel_data, info, time):
|
||||
ev = self.atree.get_selected_objects()
|
||||
|
||||
if len(ev):
|
||||
bits_per = 8; # we're going to pass a string
|
||||
pickled = pickle.dumps(ev[0]);
|
||||
data = str((DdTargets.ATTRIBUTE.drag_type,
|
||||
self.person.get_handle(),pickled));
|
||||
sel_data.set(sel_data.target, bits_per, data)
|
||||
|
||||
def ad_drag_data_received(self,widget,context,x,y,sel_data,info,time):
|
||||
row = self.ptree.get_row_at(x,y)
|
||||
|
||||
if sel_data and sel_data.data:
|
||||
exec 'data = %s' % sel_data.data
|
||||
exec 'mytype = "%s"' % data[0]
|
||||
exec 'person = "%s"' % data[1]
|
||||
if mytype != DdTargets.ADDRESS.drag_type:
|
||||
return
|
||||
elif person == self.person.get_handle():
|
||||
self.move_element(self.plist,self.ptree.get_selected_row(),row)
|
||||
else:
|
||||
foo = pickle.loads(data[2]);
|
||||
for src in foo.get_source_references():
|
||||
base_handle = src.get_base_handle()
|
||||
newbase = self.db.get_source_from_handle(base_handle)
|
||||
src.set_base_handle(newbase.get_handle())
|
||||
self.plist.insert(row,foo)
|
||||
|
||||
self.lists_changed = True
|
||||
self.redraw_addr_list()
|
||||
|
||||
def ad_drag_data_get(self,widget, context, sel_data, info, time):
|
||||
ev = self.ptree.get_selected_objects()
|
||||
|
||||
if len(ev):
|
||||
bits_per = 8; # we're going to pass a string
|
||||
pickled = pickle.dumps(ev[0]);
|
||||
data = str((DdTargets.ADDRESS.drag_type,
|
||||
self.person.get_handle(),pickled));
|
||||
sel_data.set(sel_data.target, bits_per, data)
|
||||
|
||||
def ad_drag_begin(self, context, a):
|
||||
return
|
||||
|
||||
>>>>>>> 1.194.2.7
|
||||
def menu_changed(self,obj):
|
||||
self.ldsfam = self.lds_fam_list[obj.get_active()]
|
||||
|
||||
@ -1127,7 +1363,8 @@ class EditPerson:
|
||||
object_handle = ph.get_reference_handle()
|
||||
obj = self.db.get_object_from_handle(object_handle)
|
||||
if self.load_obj != obj.get_path():
|
||||
if obj.get_mime_type()[0:5] == "image":
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
self.load_photo(obj.get_path())
|
||||
else:
|
||||
self.load_photo(None)
|
||||
|
@ -314,11 +314,14 @@ class EditPlace:
|
||||
self.redraw_url_list()
|
||||
|
||||
def url_source_drag_data_get(self,widget, context, sel_data, info, time):
|
||||
|
||||
ev = self.web_model.get_selected_objects()[0]
|
||||
store,node = self.web_list.get_selection().get_selected()
|
||||
if not node:
|
||||
return
|
||||
row = store.get_path(node)
|
||||
url = self.ulist[row[0]]
|
||||
bits_per = 8; # we're going to pass a string
|
||||
pickled = pickle.dumps(ev);
|
||||
data = str(('url',self.place.get_handle(),pickled));
|
||||
pickled = pickle.dumps(url)
|
||||
data = str(('url',self.place.get_handle(),pickled))
|
||||
sel_data.set(sel_data.target, bits_per, data)
|
||||
|
||||
def update_lists(self):
|
||||
|
@ -255,31 +255,38 @@ class EditSource:
|
||||
|
||||
def button_press(self,obj):
|
||||
data = self.model.get_selected_objects()
|
||||
(type,handle) = data[0]
|
||||
if type == 0:
|
||||
if not data:
|
||||
return
|
||||
(data_type,handle) = data[0]
|
||||
if data_type == 0:
|
||||
import EditPerson
|
||||
person = self.db.get_person_from_handle(handle)
|
||||
EditPerson.EditPerson(self.parent,person,self.db)
|
||||
elif type == 1:
|
||||
elif data_type == 1:
|
||||
import Marriage
|
||||
family = self.db.get_family_from_handle(handle)
|
||||
Marriage.Marriage(self.parent,family,self.db)
|
||||
elif type == 2:
|
||||
elif data_type == 2:
|
||||
import EventEdit
|
||||
event = self.db.get_event_from_handle(handle)
|
||||
if event.get_name() in const.marriageEvents:
|
||||
event_name = event.get_name()
|
||||
if const.family_events.has_key(event_name):
|
||||
EventEdit.EventEditor(
|
||||
self,", ", const.marriageEvents, const.family_events,
|
||||
event, None, 0, None, None, self.db.readonly)
|
||||
elif event.get_name() in const.personalEvents + [_("Birth"),_("Death")]:
|
||||
elif const.personal_events.has_key(event_name):
|
||||
EventEdit.EventEditor(
|
||||
self,", ", const.personalEvents, const.personal_events,
|
||||
event, None, 0, None, None, self.db.readonly)
|
||||
elif type == 3:
|
||||
elif event_name in ["Birth","Death"]:
|
||||
EventEdit.EventEditor(
|
||||
self,", ", const.personalEvents, const.personal_events,
|
||||
event, None, 1, None, None, self.db.readonly)
|
||||
elif data_type == 3:
|
||||
import EditPlace
|
||||
place = self.db.get_place_from_handle(handle)
|
||||
EditPlace.EditPlace(self.parent,place)
|
||||
elif type == 5:
|
||||
elif data_type == 5:
|
||||
import ImageSelect
|
||||
media = self.db.get_object_from_handle(handle)
|
||||
ImageSelect.GlobalMediaProperties(self.db,media,self)
|
||||
|
@ -260,8 +260,7 @@ class FamilyView:
|
||||
DdTargets.PERSON_LINK.target()],
|
||||
ACTION_COPY)
|
||||
self.child_list.drag_source_set(BUTTON1_MASK,
|
||||
[DdTargets.CHILD.target(),
|
||||
DdTargets.PERSON_LINK.target()],
|
||||
[DdTargets.CHILD.target()],
|
||||
ACTION_COPY)
|
||||
self.child_list.connect('drag_data_get', self.drag_data_get)
|
||||
self.child_list.connect('drag_data_received',self.drag_data_received)
|
||||
|
1436
src/GenericFilter.py
1436
src/GenericFilter.py
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@ from bsddb import dbshelve, db
|
||||
from RelLib import *
|
||||
from GrampsDbBase import *
|
||||
|
||||
_DBVERSION = 5
|
||||
_DBVERSION = 6
|
||||
|
||||
def find_surname(key,data):
|
||||
return str(data[3].get_surname())
|
||||
@ -292,6 +292,57 @@ class GrampsBSDDB(GrampsDbBase):
|
||||
vals.sort()
|
||||
return vals
|
||||
|
||||
<<<<<<< GrampsBSDDB.py
|
||||
=======
|
||||
def remove_person(self,handle,transaction):
|
||||
if not self.readonly and handle and str(handle) in self.person_map:
|
||||
person = self.get_person_from_handle(handle)
|
||||
self.genderStats.uncount_person (person)
|
||||
if transaction != None:
|
||||
transaction.add(PERSON_KEY,handle,person.serialize())
|
||||
self.emit('person-delete',([str(handle)],))
|
||||
self.person_map.delete(str(handle))
|
||||
|
||||
def remove_source(self,handle,transaction):
|
||||
if not self.readonly and handle and str(handle) in self.source_map:
|
||||
if transaction != None:
|
||||
old_data = self.source_map.get(str(handle))
|
||||
transaction.add(SOURCE_KEY,handle,old_data)
|
||||
self.emit('source-delete',([handle],))
|
||||
self.source_map.delete(str(handle))
|
||||
|
||||
def remove_family(self,handle,transaction):
|
||||
if not self.readonly and handle and str(handle) in self.family_map:
|
||||
if transaction != None:
|
||||
old_data = self.family_map.get(str(handle))
|
||||
transaction.add(FAMILY_KEY,handle,old_data)
|
||||
self.emit('family-delete',([str(handle)],))
|
||||
self.family_map.delete(str(handle))
|
||||
|
||||
def remove_event(self,handle,transaction):
|
||||
if not self.readonly and handle and str(handle) in self.event_map:
|
||||
if transaction != None:
|
||||
old_data = self.event_map.get(str(handle))
|
||||
transaction.add(EVENT_KEY,handle,old_data)
|
||||
self.event_map.delete(str(handle))
|
||||
|
||||
def remove_place(self,handle,transaction):
|
||||
if not self.readonly and handle and str(handle) in self.place_map:
|
||||
if transaction != None:
|
||||
old_data = self.place_map.get(handle)
|
||||
transaction.add(PLACE_KEY,handle,old_data)
|
||||
self.emit('place-delete',([handle],))
|
||||
self.place_map.delete(str(handle))
|
||||
|
||||
def remove_object(self,handle,transaction):
|
||||
if not self.readonly and handle and str(handle) in self.media_map:
|
||||
if transaction != None:
|
||||
old_data = self.media_map.get(handle)
|
||||
transaction.add(MEDIA_KEY,handle,old_data)
|
||||
self.emit('media-delete',([handle],))
|
||||
self.media_map.delete(str(handle))
|
||||
|
||||
>>>>>>> 1.41.2.5
|
||||
def get_person_from_gramps_id(self,val):
|
||||
"""finds a Person in the database from the passed gramps' ID.
|
||||
If no such Person exists, a new Person is added to the database."""
|
||||
@ -352,6 +403,25 @@ class GrampsBSDDB(GrampsDbBase):
|
||||
else:
|
||||
return None
|
||||
|
||||
def transaction_commit(self,transaction,msg):
|
||||
GrampsDbBase.transaction_commit(self,transaction,msg)
|
||||
self.family_map.sync()
|
||||
self.place_map.sync()
|
||||
self.source_map.sync()
|
||||
self.media_map.sync()
|
||||
self.event_map.sync()
|
||||
self.metadata.sync()
|
||||
self.person_map.sync()
|
||||
self.surnames.sync()
|
||||
self.name_group.sync()
|
||||
self.id_trans.sync()
|
||||
self.fid_trans.sync()
|
||||
self.pid_trans.sync()
|
||||
self.sid_trans.sync()
|
||||
self.oid_trans.sync()
|
||||
self.eventnames.sync()
|
||||
self.undodb.sync()
|
||||
|
||||
def upgrade(self):
|
||||
child_rel_notrans = [
|
||||
"None", "Birth", "Adopted", "Stepchild",
|
||||
@ -366,6 +436,8 @@ class GrampsBSDDB(GrampsDbBase):
|
||||
self.upgrade_4(child_rel_notrans)
|
||||
if version < 5:
|
||||
self.upgrade_5()
|
||||
if version < 6:
|
||||
self.upgrade_6()
|
||||
self.metadata['version'] = _DBVERSION
|
||||
print 'Successfully finished all upgrades'
|
||||
|
||||
@ -674,3 +746,11 @@ class GrampsBSDDB(GrampsDbBase):
|
||||
self.commit_source(source,None)
|
||||
data = cursor.next()
|
||||
cursor.close()
|
||||
|
||||
def upgrade_6(self):
|
||||
print "Upgrading to DB version 6"
|
||||
order = []
|
||||
for val in self.get_media_column_order():
|
||||
if val[1] != 6:
|
||||
order.append(val)
|
||||
self.set_media_column_order(order)
|
||||
|
@ -270,7 +270,7 @@ class GrampsDbBase(GrampsDBCallback.GrampsDBCallback):
|
||||
Commits the specified Person to the database, storing the changes
|
||||
as part of the transaction.
|
||||
"""
|
||||
if self.readonly or not obj.handle:
|
||||
if self.readonly or not obj or not obj.handle:
|
||||
return
|
||||
if change_time:
|
||||
obj.change = int(change_time)
|
||||
@ -574,13 +574,13 @@ class GrampsDbBase(GrampsDBCallback.GrampsDBCallback):
|
||||
self.genderStats.count_person (person, self)
|
||||
return person.handle
|
||||
|
||||
def _add_object(self,object,transaction,find_next_func,commit_func):
|
||||
if not object.gramps_id:
|
||||
object.gramps_id = find_next_func()
|
||||
if not object.handle:
|
||||
object.handle = self.create_id()
|
||||
commit_func(object,transaction)
|
||||
return object.handle
|
||||
def _add_object(self,obj,transaction,find_next_func,commit_func):
|
||||
if not obj.gramps_id:
|
||||
obj.gramps_id = find_next_func()
|
||||
if not obj.handle:
|
||||
obj.handle = self.create_id()
|
||||
commit_func(obj,transaction)
|
||||
return obj.handle
|
||||
|
||||
def add_family(self,family,transaction):
|
||||
"""
|
||||
@ -1230,8 +1230,20 @@ class GrampsDbBase(GrampsDBCallback.GrampsDBCallback):
|
||||
Returns the MediaObject display common information stored in the
|
||||
database's metadata.
|
||||
"""
|
||||
<<<<<<< GrampsDbBase.py
|
||||
default = [(1,1),(0,5),(0,6),(1,2),(1,3),(0,4)]
|
||||
return self._get_column_order(MEDIA_COL_KEY,default)
|
||||
=======
|
||||
default = [(1,1),(0,5),(0,4),(1,2),(1,3)]
|
||||
if self.metadata == None:
|
||||
return default
|
||||
else:
|
||||
cols = self.metadata.get('media_columns',default)
|
||||
if len(cols) != len(default):
|
||||
return cols + default[len(cols):]
|
||||
else:
|
||||
return cols
|
||||
>>>>>>> 1.53.2.3
|
||||
|
||||
class Transaction:
|
||||
"""
|
||||
|
@ -145,59 +145,124 @@ class GrampsInMemDB(GrampsDbBase):
|
||||
vals.sort()
|
||||
return vals
|
||||
|
||||
<<<<<<< GrampsInMemDB.py
|
||||
def _del_person(self,handle):
|
||||
=======
|
||||
def remove_person(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.person_map:
|
||||
return
|
||||
person = self.get_person_from_handle(handle)
|
||||
self.genderStats.uncount_person (person)
|
||||
if transaction != None:
|
||||
old_data = self.person_map.get(handle)
|
||||
transaction.add(PERSON_KEY,handle,old_data)
|
||||
self.emit('person-delete',([handle],))
|
||||
>>>>>>> 1.23.2.2
|
||||
del self.id_trans[person.get_gramps_id()]
|
||||
del self.person_map[handle]
|
||||
|
||||
<<<<<<< GrampsInMemDB.py
|
||||
def _del_source(self,handle):
|
||||
=======
|
||||
def remove_source(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.source_map:
|
||||
return
|
||||
source = self.get_source_from_handle(handle)
|
||||
if transaction != None:
|
||||
old_data = self.source_map.get(str(handle))
|
||||
transaction.add(SOURCE_KEY,handle,old_data)
|
||||
self.emit('source-delete',([handle],))
|
||||
>>>>>>> 1.23.2.2
|
||||
del self.sid_trans[source.get_gramps_id()]
|
||||
del self.source_map[str(handle)]
|
||||
|
||||
<<<<<<< GrampsInMemDB.py
|
||||
def _del_place(self,handle):
|
||||
=======
|
||||
def remove_place(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.place_map:
|
||||
return
|
||||
place = self.get_place_from_handle(handle)
|
||||
if transaction != None:
|
||||
old_data = self.place_map.get(str(handle))
|
||||
transaction.add(PLACE_KEY,handle,old_data)
|
||||
self.emit('place-delete',([handle],))
|
||||
>>>>>>> 1.23.2.2
|
||||
del self.pid_trans[place.get_gramps_id()]
|
||||
del self.place_map[str(handle)]
|
||||
|
||||
<<<<<<< GrampsInMemDB.py
|
||||
def _del_media(self,handle):
|
||||
=======
|
||||
def remove_object(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.media_map:
|
||||
return
|
||||
obj = self.get_object_from_handle(handle)
|
||||
if transaction != None:
|
||||
old_data = self.media_map.get(str(handle))
|
||||
transaction.add(MEDIA_KEY,handle,old_data)
|
||||
self.emit('media-delete',([handle],))
|
||||
>>>>>>> 1.23.2.2
|
||||
del self.oid_trans[obj.get_gramps_id()]
|
||||
del self.media_map[str(handle)]
|
||||
|
||||
<<<<<<< GrampsInMemDB.py
|
||||
def _del_family(self,handle):
|
||||
=======
|
||||
def remove_family(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.family_map:
|
||||
return
|
||||
family = self.get_family_from_handle(handle)
|
||||
if transaction != None:
|
||||
old_data = self.family_map.get(str(handle))
|
||||
transaction.add(FAMILY_KEY,handle,old_data)
|
||||
self.emit('family-delete',([handle],))
|
||||
>>>>>>> 1.23.2.2
|
||||
del self.fid_trans[family.get_gramps_id()]
|
||||
del self.family_map[str(handle)]
|
||||
|
||||
<<<<<<< GrampsInMemDB.py
|
||||
def _del_event(self,handle):
|
||||
=======
|
||||
def remove_event(self,handle,transaction):
|
||||
if self.readonly or not handle or str(handle) not in self.event_map:
|
||||
return
|
||||
if transaction != None:
|
||||
old_data = self.event_map.get(str(handle))
|
||||
transaction.add(EVENT_KEY,handle,old_data)
|
||||
>>>>>>> 1.23.2.2
|
||||
del self.event_map[str(handle)]
|
||||
|
||||
def commit_person(self,person,transaction,change_time=None):
|
||||
if self.readonly or not person.get_handle():
|
||||
if self.readonly or not person or not person.get_handle():
|
||||
return
|
||||
gid = person.get_gramps_id()
|
||||
self.id_trans[gid] = person.get_handle()
|
||||
GrampsDbBase.commit_person(self,person,transaction,change_time)
|
||||
|
||||
def commit_place(self,place,transaction,change_time=None):
|
||||
if self.readonly or not place.get_handle():
|
||||
if self.readonly or not place or not place.get_handle():
|
||||
return
|
||||
gid = place.get_gramps_id()
|
||||
self.pid_trans[gid] = place.get_handle()
|
||||
GrampsDbBase.commit_place(self,place,transaction,change_time)
|
||||
|
||||
def commit_family(self,family,transaction,change_time=None):
|
||||
if self.readonly or not family.get_handle():
|
||||
if self.readonly or not family or not family.get_handle():
|
||||
return
|
||||
gid = family.get_gramps_id()
|
||||
self.fid_trans[gid] = family.get_handle()
|
||||
GrampsDbBase.commit_family(self,family,transaction,change_time)
|
||||
|
||||
def commit_media_object(self,obj,transaction,change_time=None):
|
||||
if self.readonly or not obj.get_handle():
|
||||
if self.readonly or not obj or not obj.get_handle():
|
||||
return
|
||||
gid = obj.get_gramps_id()
|
||||
self.oid_trans[gid] = obj.get_handle()
|
||||
GrampsDbBase.commit_media_object(self,obj,transaction,change_time)
|
||||
|
||||
def commit_source(self,source,transaction,change_time=None):
|
||||
if self.readonly or not source.get_handle():
|
||||
if self.readonly or not source or not source.get_handle():
|
||||
return
|
||||
gid = source.get_gramps_id()
|
||||
self.sid_trans[gid] = source.get_handle()
|
||||
|
@ -147,7 +147,7 @@ class ImageSelect:
|
||||
|
||||
if os.path.isfile(filename):
|
||||
mtype = GrampsMime.get_type(filename)
|
||||
if mtype[0:5] == "image":
|
||||
if mtype and mtype.startswith("image"):
|
||||
image = RelImage.scale_image(filename,const.thumbScale)
|
||||
self.image.set_from_pixbuf(image)
|
||||
else:
|
||||
@ -284,6 +284,8 @@ class Gallery(ImageSelect):
|
||||
self.drag_item = widget.get_item_at(self.remember_x,
|
||||
self.remember_y)
|
||||
icon_index = self.get_index(widget,event.x,event.y)-1
|
||||
if icon_index == -1:
|
||||
return
|
||||
self.sel_obj = self.dataobj.get_media_list()[icon_index]
|
||||
if self.drag_item:
|
||||
widget.drag_begin([DdTargets.MEDIAOBJ.target()]+_drag_targets,
|
||||
@ -361,20 +363,19 @@ class Gallery(ImageSelect):
|
||||
def add_thumbnail(self, photo):
|
||||
"""Scale the image and add it to the IconList."""
|
||||
oid = photo.get_reference_handle()
|
||||
obj = self.db.get_object_from_handle(oid)
|
||||
if self.canvas_list.has_key(oid):
|
||||
(grp,item,text,x,y) = self.canvas_list[oid]
|
||||
media_obj = self.db.get_object_from_handle(oid)
|
||||
if self.canvas_list.has_key(photo):
|
||||
(grp,item,text,x,y) = self.canvas_list[photo]
|
||||
if x != self.cx or y != self.cy:
|
||||
grp.move(self.cx-x,self.cy-y)
|
||||
else:
|
||||
description = obj.get_description()
|
||||
description = media_obj.get_description()
|
||||
if len(description) > 20:
|
||||
description = "%s..." % description[0:20]
|
||||
|
||||
try:
|
||||
media_obj = self.db.get_object_from_handle(oid)
|
||||
mtype = media_obj.get_mime_type()
|
||||
if mtype[0:5] == "image":
|
||||
if mtype and mtype.startswith("image"):
|
||||
image = ImgManip.get_thumbnail_image(media_obj.get_path())
|
||||
else:
|
||||
image = Utils.find_mime_type_pixbuf(mtype)
|
||||
@ -417,7 +418,7 @@ class Gallery(ImageSelect):
|
||||
self.p_map[i] = (item,text,box,photo,oid)
|
||||
i.show()
|
||||
|
||||
self.canvas_list[oid] = (grp,item,text,self.cx,self.cy)
|
||||
self.canvas_list[photo] = (grp,item,text,self.cx,self.cy)
|
||||
|
||||
self.cx += _PAD + _IMAGEX
|
||||
|
||||
@ -575,7 +576,7 @@ class Gallery(ImageSelect):
|
||||
|
||||
if self.sel:
|
||||
(i,t,b,photo,oid) = self.p_map[self.sel]
|
||||
val = self.canvas_list[photo.get_reference_handle()]
|
||||
val = self.canvas_list[photo]
|
||||
val[0].hide()
|
||||
val[1].hide()
|
||||
val[2].hide()
|
||||
@ -607,7 +608,7 @@ class Gallery(ImageSelect):
|
||||
if progname and len(progname) > 1:
|
||||
Utils.add_menuitem(menu,_("Open in %s") % progname[1],
|
||||
photo,self.popup_view_photo)
|
||||
if mtype[0:5] == "image":
|
||||
if mtype and mtype.startswith("image"):
|
||||
Utils.add_menuitem(menu,_("Edit with the GIMP"),
|
||||
photo,self.popup_edit_photo)
|
||||
Utils.add_menuitem(menu,_("Edit Object Properties"),photo,
|
||||
|
@ -60,7 +60,6 @@ column_names = [
|
||||
_('Path'),
|
||||
_('Last Changed'),
|
||||
_('Date'),
|
||||
_('Place'),
|
||||
]
|
||||
|
||||
_HANDLE_COL = len(column_names)
|
||||
@ -84,6 +83,7 @@ class MediaView:
|
||||
self.topWindow = glade.get_widget("gramps")
|
||||
self.renderer = gtk.CellRendererText()
|
||||
self.model = DisplayModels.MediaModel(self.db)
|
||||
self.sort_col = 0
|
||||
|
||||
self.selection = self.list.get_selection()
|
||||
self.list.set_model(self.model)
|
||||
@ -130,13 +130,51 @@ class MediaView:
|
||||
self.build_columns()
|
||||
self.build_tree()
|
||||
|
||||
def column_clicked(self,obj,data):
|
||||
if self.sort_col != data:
|
||||
order = gtk.SORT_ASCENDING
|
||||
else:
|
||||
if (self.columns[data].get_sort_order() == gtk.SORT_DESCENDING
|
||||
or self.columns[data].get_sort_indicator() == False):
|
||||
order = gtk.SORT_ASCENDING
|
||||
else:
|
||||
order = gtk.SORT_DESCENDING
|
||||
self.sort_col = data
|
||||
handle = self.first_selected()
|
||||
self.model = DisplayModels.MediaModel(self.parent.db,
|
||||
self.sort_col,order)
|
||||
self.list.set_model(self.model)
|
||||
|
||||
colmap = self.parent.db.get_place_column_order()
|
||||
|
||||
if handle:
|
||||
path = self.model.on_get_path(handle)
|
||||
self.selection.select_path(path)
|
||||
self.list.scroll_to_cell(path,None,1,0.5,0)
|
||||
for i in range(0,len(self.columns)):
|
||||
self.columns[i].set_sort_indicator(i==colmap[data][1]-1)
|
||||
self.columns[self.sort_col].set_sort_order(order)
|
||||
|
||||
def first_selected(self):
|
||||
mlist = []
|
||||
self.selection.selected_foreach(self.blist,mlist)
|
||||
if mlist:
|
||||
return mlist[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def blist(self,store,path,iter,list):
|
||||
handle = store.get_value(iter,_HANDLE_COL)
|
||||
list.append(handle)
|
||||
|
||||
def build_columns(self):
|
||||
for column in self.columns:
|
||||
self.list.remove_column(column)
|
||||
|
||||
column = gtk.TreeViewColumn(_('Title'), self.renderer,text=0)
|
||||
column.set_resizable(True)
|
||||
|
||||
column.connect('clicked',self.column_clicked,0)
|
||||
column.set_clickable(True)
|
||||
column.set_min_width(225)
|
||||
self.list.append_column(column)
|
||||
self.columns = [column]
|
||||
@ -149,6 +187,8 @@ class MediaView:
|
||||
column = gtk.TreeViewColumn(name, self.renderer, text=pair[1])
|
||||
column.set_resizable(True)
|
||||
column.set_min_width(75)
|
||||
column.set_clickable(True)
|
||||
column.connect('clicked',self.column_clicked,index)
|
||||
self.columns.append(column)
|
||||
self.list.append_column(column)
|
||||
index += 1
|
||||
@ -326,7 +366,6 @@ class MediaView:
|
||||
|
||||
def on_drag_drop(self, tree, context, x, y, time):
|
||||
self.list.emit_stop_by_name('drag-drop')
|
||||
self.list.drag_get_data(context,context.targets[-1],time)
|
||||
return 1
|
||||
|
||||
def on_drag_begin(self,obj,context):
|
||||
|
@ -168,8 +168,8 @@ class MergePlaces:
|
||||
#-------------------------------------------------------------------------
|
||||
class MergeSources:
|
||||
"""
|
||||
Merges to places into a single place. Displays a dialog box that
|
||||
allows the places to be combined into one.
|
||||
Merges to sources into a single source. Displays a dialog box that
|
||||
allows the sources to be combined into one.
|
||||
"""
|
||||
def __init__(self,database,new_handle,old_handle,update):
|
||||
self.db = database
|
||||
@ -291,7 +291,7 @@ class MergeSources:
|
||||
event = self.db.get_event_from_handle(handle)
|
||||
if event.has_source_reference(self.old_handle):
|
||||
event.replace_source_references(self.old_handle,self.new_handle)
|
||||
self.db.commit_event(event,self.trans)
|
||||
self.db.commit_event(event,self.trans)
|
||||
|
||||
# sources
|
||||
for handle in self.db.get_source_handles():
|
||||
|
@ -281,26 +281,78 @@ class MergePeople:
|
||||
else:
|
||||
one.add_source_reference(xsrc)
|
||||
|
||||
def debug_person(self,person, msg=""):
|
||||
if __debug__:
|
||||
print "## %s person handle %s" % (msg,person.get_handle())
|
||||
for h in person.get_family_handle_list():
|
||||
fam = self.db.get_family_from_handle(h)
|
||||
print " - family %s has father: %s, mother: %s" % \
|
||||
(h,fam.get_father_handle(),fam.get_mother_handle())
|
||||
for h,m1,m2 in person.get_parent_family_handle_list():
|
||||
print " - parent family %s" % h
|
||||
|
||||
def merge(self):
|
||||
"""
|
||||
Perform the actual merge. A new person is created to store the
|
||||
merged data. First, the person information is merged. This is a
|
||||
very straight forward process. Second, the families associated
|
||||
with the merged people must be modified to handle the family
|
||||
information. This process can be tricky.
|
||||
|
||||
Finally, the merged person is delete from the database and the
|
||||
entire transaction is committed.
|
||||
"""
|
||||
self.debug_person(self.p1, "P1")
|
||||
self.debug_person(self.p2, "P2")
|
||||
|
||||
new = RelLib.Person()
|
||||
trans = self.db.transaction_begin()
|
||||
|
||||
self.merge_person_information(new,trans)
|
||||
self.merge_family_information(new,trans)
|
||||
self.db.commit_person(new,trans)
|
||||
self.debug_person(new, "NEW")
|
||||
self.db.remove_person(self.old_handle,trans)
|
||||
self.db.transaction_commit(trans,"Merge Person")
|
||||
|
||||
def merge_person_information(self,new,trans):
|
||||
"""
|
||||
Merging the person's individual information is pretty simple. The
|
||||
person 'new' is a new, empty person. The data is loaded in this
|
||||
new person. The idea is that all information that can possibly be
|
||||
preserved is preserved.
|
||||
"""
|
||||
self.old_handle = self.p2.get_handle()
|
||||
self.new_handle = self.p1.get_handle()
|
||||
|
||||
|
||||
# Choose the handle from the target person. Since this is internal
|
||||
# only information, no user visible information is lost.
|
||||
new.set_handle(self.new_handle)
|
||||
|
||||
# The gender is chosen from the primary person. This is one case
|
||||
# where data may be lost if you merge the data from two people of
|
||||
# opposite genders.
|
||||
new.set_gender(self.p1.get_gender())
|
||||
|
||||
# copy the GRAMPS Ids
|
||||
self.merge_gramps_ids(new)
|
||||
|
||||
# copy names
|
||||
self.merge_names(new)
|
||||
|
||||
# copy the birth event
|
||||
self.merge_birth(new,trans)
|
||||
|
||||
# copy the death event
|
||||
self.merge_death(new,trans)
|
||||
|
||||
# merge the event lists
|
||||
self.merge_event_lists(new)
|
||||
|
||||
# copy attributes
|
||||
new.set_attribute_list(self.p1.get_attribute_list() +
|
||||
self.p2.get_attribute_list())
|
||||
|
||||
# copy names
|
||||
|
||||
new.set_alternate_names(self.p1.get_alternate_names() +
|
||||
self.p2.get_alternate_names())
|
||||
|
||||
# copy addresses
|
||||
new.set_address_list(self.p1.get_address_list() + self.p2.get_address_list())
|
||||
|
||||
@ -320,68 +372,346 @@ class MergePeople:
|
||||
for photo in self.p2.get_media_list():
|
||||
new.add_media_reference(photo)
|
||||
|
||||
|
||||
# note
|
||||
note1 = self.p1.get_note_object()
|
||||
note2 = self.p2.get_note_object()
|
||||
new.set_note_object(self.merge_notes(note1,note2))
|
||||
|
||||
def merge(self):
|
||||
def merge_gramps_ids(self,new):
|
||||
"""
|
||||
Merges the GRAMPS IDs. The new GRAMPS ID is taken from
|
||||
destination person. The GRAMPS ID of the other person is added
|
||||
to the merged person as an attribute.
|
||||
"""
|
||||
# copy of GRAMPS ID as an attribute
|
||||
attr = RelLib.Attribute()
|
||||
attr.set_type('Merged GRAMPS ID')
|
||||
attr.set_value(self.p2.get_gramps_id())
|
||||
new.add_attribute(attr)
|
||||
|
||||
new = RelLib.Person()
|
||||
trans = self.db.transaction_begin()
|
||||
# store GRAMPS ID of the destination person
|
||||
new.set_gramps_id(self.p1.get_gramps_id())
|
||||
|
||||
self.merge_person_information(new,trans)
|
||||
self.merge_family_information(new,trans)
|
||||
self.db.commit_person(new,trans)
|
||||
self.db.remove_person(self.old_handle,trans)
|
||||
self.db.transaction_commit(trans,"Merge Person")
|
||||
def merge_names(self, new):
|
||||
"""
|
||||
Merges the names of the two people into the destination. The
|
||||
primary name of the destination person is kept as the primary
|
||||
name.
|
||||
|
||||
def convert_child_ids(self, family_id, id1, id2, trans):
|
||||
new_list = []
|
||||
change = False
|
||||
family = self.db.get_family_from_handle(family_id)
|
||||
The other person's name is stored as an alternate name if it is
|
||||
not entirely identical to the destination person's primary name.
|
||||
|
||||
for child_id in family.get_child_handle_list():
|
||||
if child_id == id2:
|
||||
new_list.append(id1)
|
||||
change = True
|
||||
else:
|
||||
new_list.append(child_id)
|
||||
if change:
|
||||
family.set_child_handle_list(new_list)
|
||||
In the current implementation, If only one person has a
|
||||
nickname, it is assigned as the merged person's nickname. If
|
||||
both people have nicknames, then the nickname of the second
|
||||
person is lost.
|
||||
|
||||
Remaining alternate names are then added to the merged
|
||||
person's alternate names.
|
||||
"""
|
||||
p1_name = self.p1.get_primary_name()
|
||||
p2_name = self.p2.get_primary_name()
|
||||
|
||||
new.set_primary_name(self.p1.get_primary_name())
|
||||
if not p2_name.is_equal(p1_name):
|
||||
new.add_alternate_name(p2_name)
|
||||
|
||||
if self.p1.get_nick_name() == "":
|
||||
new.set_nick_name(self.p2.get_nick_name())
|
||||
else:
|
||||
new.set_nick_name(self.p1.get_nick_name())
|
||||
|
||||
for name in self.p1.get_alternate_names():
|
||||
new.add_alternate_name(name)
|
||||
for name in self.p2.get_alternate_names():
|
||||
new.add_alternate_name(name)
|
||||
|
||||
def merge_birth(self, new,trans):
|
||||
"""
|
||||
Merges the birth events of the two people. If the primary
|
||||
person does not have a birth event, then the birth event from
|
||||
the secodnary person is selected. If the primary person has
|
||||
a birth date, then the merged person gets the primary person's
|
||||
birth event, and the secondary person's birth event is added
|
||||
as a 'Alternate Birth' event.
|
||||
"""
|
||||
handle1 = self.p1.get_birth_handle()
|
||||
handle2 = self.p2.get_birth_handle()
|
||||
|
||||
if handle1:
|
||||
new.set_birth_handle(handle1)
|
||||
if handle2:
|
||||
event = self.db.get_event_from_handle(handle2)
|
||||
event.set_name('Alternate Birth')
|
||||
self.db.add_event(event,trans)
|
||||
new.add_event_handle(event.get_handle())
|
||||
elif not handle1 and handle2:
|
||||
new.set_birth_handle(handle2)
|
||||
|
||||
def merge_death(self, new, trans):
|
||||
"""
|
||||
Merges the death events of the two people. If the primary
|
||||
person does not have a death event, then the death event from
|
||||
the secodnary person is selected. If the primary person has
|
||||
a death date, then the merged person gets the primary person's
|
||||
death event, and the secondary person's death event is added
|
||||
as a 'Alternate Death' event.
|
||||
"""
|
||||
handle1 = self.p1.get_death_handle()
|
||||
handle2 = self.p2.get_death_handle()
|
||||
|
||||
if handle1:
|
||||
new.set_death_handle(handle1)
|
||||
if handle2:
|
||||
event = self.db.get_event_from_handle(handle2)
|
||||
event.set_handle(Utils.create_id())
|
||||
event.set_name('Alternate Death')
|
||||
new.add_event_handle(event.get_handle())
|
||||
self.db.add_event(event,trans)
|
||||
elif not handle1 and handle2:
|
||||
new.set_death_handle(handle2)
|
||||
|
||||
def merge_event_lists(self, new):
|
||||
"""
|
||||
Merges the events from the two people into the destination
|
||||
person. Duplicates are not transferred.
|
||||
"""
|
||||
data_list = new.get_event_list()
|
||||
for handle in self.p1.get_event_list():
|
||||
if handle not in data_list:
|
||||
data_list.append(handle)
|
||||
for handle in self.p2.get_event_list():
|
||||
if handle not in data_list:
|
||||
data_list.append(handle)
|
||||
new.set_event_list(data_list)
|
||||
|
||||
def merge_family_information(self, new, trans):
|
||||
"""
|
||||
Merge the parent families and the relationship families of the
|
||||
selected people.
|
||||
"""
|
||||
self.merge_parents(new, trans)
|
||||
self.merge_relationships(new, trans)
|
||||
|
||||
def merge_parents(self, new, trans):
|
||||
"""
|
||||
Merging the parent list is not too difficult. We grab the
|
||||
parent list of the destination person. We then loop through
|
||||
the parent list of the secondary person, adding to the parent
|
||||
list any parents that are not already there. This eliminates
|
||||
any duplicates.
|
||||
|
||||
Once this has been completed, we loop through each family,
|
||||
converting any child handles referring to the secondary person
|
||||
to the destination person.
|
||||
"""
|
||||
parent_list = self.p1.get_parent_family_handle_list()
|
||||
|
||||
# copy handles of families that are not common between the
|
||||
# two lists
|
||||
for fid in self.p2.get_parent_family_handle_list():
|
||||
if fid not in parent_list:
|
||||
parent_list.append(fid)
|
||||
|
||||
# loop through the combined list, converting the child handles
|
||||
# of the families, and adding the families to the merged
|
||||
# person
|
||||
|
||||
for (family_handle,mrel,frel) in parent_list:
|
||||
self.convert_child_ids(family_handle, self.new_handle,
|
||||
self.old_handle, trans)
|
||||
new.add_parent_family_handle(family_handle, mrel, frel)
|
||||
|
||||
def convert_child_ids(self, fhandle, new_handle, old_handle, trans):
|
||||
"""
|
||||
Search the family associated with fhandle, and replace all
|
||||
child handles that match old_handle with new_handle.
|
||||
"""
|
||||
family = self.db.get_family_from_handle(fhandle)
|
||||
new_child_list = []
|
||||
orig_list = family.get_child_handle_list()
|
||||
|
||||
# loop through original child list. If a handle matches the
|
||||
# old handle, replace it with the new handle if the new handle
|
||||
# is not already in the list
|
||||
for child_id in orig_list:
|
||||
if child_id == old_handle:
|
||||
if new_handle not in new_child_list:
|
||||
new_child_list.append(new_handle)
|
||||
elif child_id not in new_child_list:
|
||||
new_child_list.append(child_id)
|
||||
|
||||
# compare the new list with the original list. If this list
|
||||
# is different, we need to save the changes to the database.
|
||||
if new_child_list != orig_list:
|
||||
family.set_child_handle_list(new_child_list)
|
||||
self.db.commit_family(family,trans)
|
||||
|
||||
def merge_parents(self, new, trans):
|
||||
f1_list = self.p1.get_parent_family_handle_list()
|
||||
f2_list = self.p2.get_parent_family_handle_list()
|
||||
|
||||
parent_list = f1_list
|
||||
|
||||
for fid in f2_list:
|
||||
self.convert_child_ids(fid[0], self.new_handle, self.old_handle, trans)
|
||||
parent_list.append(fid)
|
||||
for fid in parent_list:
|
||||
new.add_parent_family_handle(fid[0],fid[1],fid[2])
|
||||
|
||||
def merge_family_information(self, new, trans):
|
||||
self.merge_parents(new, trans)
|
||||
self.merge_families(new, trans)
|
||||
def merge_relationships(self,new,trans):
|
||||
"""
|
||||
Merges the relationships associated with the merged people.
|
||||
"""
|
||||
|
||||
def find_family(self,family):
|
||||
if self.p1.get_gender() == RelLib.Person.MALE:
|
||||
mother_handle = family.get_mother_handle()
|
||||
father_handle = self.p1.get_handle()
|
||||
else:
|
||||
father_handle = family.get_father_handle()
|
||||
mother_handle = self.p1.get_handle()
|
||||
family_num = 0
|
||||
family_list = self.p1.get_family_handle_list()
|
||||
|
||||
for src_handle in self.p2.get_family_handle_list():
|
||||
|
||||
for myfamily_handle in self.db.get_family_handles():
|
||||
myfamily = self.db.get_family_from_handle(myfamily_handle)
|
||||
if (myfamily.get_father_handle() == father_handle and
|
||||
myfamily.get_mother_handle() == mother_handle):
|
||||
return myfamily
|
||||
return None
|
||||
src_family = self.db.get_family_from_handle(src_handle)
|
||||
family_num += 1
|
||||
|
||||
if not src_family or src_family in family_list:
|
||||
continue
|
||||
|
||||
tgt_family = self.find_modified_family(src_family)
|
||||
|
||||
# existing family is found
|
||||
if tgt_family:
|
||||
# The target family is already a family in the person's
|
||||
# family list.
|
||||
if tgt_family.get_handle() in self.p1.get_family_handle_list():
|
||||
self.merge_existing_family(new, src_family, tgt_family, trans)
|
||||
continue
|
||||
|
||||
# This is the case the family is not already in the person's
|
||||
# family list.
|
||||
else:
|
||||
self.merge_family_pair(tgt_family,src_family,trans)
|
||||
|
||||
# change parents of the family to point to the new
|
||||
# family
|
||||
self.adjust_family_pointers(tgt_family, src_family, trans)
|
||||
|
||||
new.remove_family_handle(src_handle)
|
||||
self.db.remove_family(src_handle,trans)
|
||||
if __debug__:
|
||||
print "Deleted src_family %s" % src_handle
|
||||
else:
|
||||
for fid in self.p1.get_family_handle_list():
|
||||
if fid not in new.get_family_handle_list():
|
||||
new.add_family_handle(fid)
|
||||
|
||||
if src_handle in new.get_family_handle_list():
|
||||
continue
|
||||
src_family = self.db.get_family_from_handle(src_handle)
|
||||
new.add_family_handle(src_handle)
|
||||
if src_family.get_father_handle() == self.old_handle:
|
||||
src_family.set_father_handle(self.new_handle)
|
||||
if __debug__:
|
||||
print "Family %s now has father %s" % (
|
||||
src_handle, self.new_handle)
|
||||
if src_family.get_mother_handle() == self.old_handle:
|
||||
src_family.set_mother_handle(self.new_handle)
|
||||
if __debug__:
|
||||
print "Family %s now has mother %s" % (
|
||||
src_handle, self.new_handle)
|
||||
self.db.commit_family(src_family,trans)
|
||||
|
||||
# a little debugging here
|
||||
|
||||
cursor = self.db.get_family_cursor()
|
||||
data = cursor.first()
|
||||
while data:
|
||||
fam = RelLib.Family()
|
||||
fam.unserialize(data[1])
|
||||
if self.p2 in fam.get_child_handle_list():
|
||||
fam.remove_child_handle(self.p2)
|
||||
fam.add_child_handle(self.p1)
|
||||
if self.p2 == fam.get_father_handle():
|
||||
fam.set_father_handle(self.p1)
|
||||
if self.p2 == fam.get_mother_handle():
|
||||
fam.set_mother_handle(self.p1)
|
||||
if fam.get_father_handle() == None and fam.get_mother_handle() == None:
|
||||
self.delete_empty_family(fam,trans)
|
||||
data = cursor.next()
|
||||
|
||||
def find_modified_family(self,family):
|
||||
"""
|
||||
Look for a existing family that matches the merged person. This means
|
||||
looking at the current family, and replacing the secondary person's
|
||||
handle with the merged person's handle. Search the family table for
|
||||
a family that matches this new mother/father pair.
|
||||
|
||||
If no family is found, return None
|
||||
"""
|
||||
|
||||
family_handle = family.get_handle()
|
||||
|
||||
if __debug__:
|
||||
print "SourceFamily: %s" % family_handle
|
||||
|
||||
# Determine the mother and father handles for the search.
|
||||
# This is determined by replacing the secodnary person's
|
||||
# handle with the primary person's handle in the mother/father
|
||||
# pair.
|
||||
|
||||
mhandle = family.get_mother_handle()
|
||||
if mhandle == self.old_handle:
|
||||
mhandle = self.new_handle
|
||||
|
||||
fhandle = family.get_father_handle()
|
||||
if fhandle == self.old_handle:
|
||||
fhandle = self.new_handle
|
||||
|
||||
# loop through the families using a cursor. Check the handles
|
||||
# for a mother/father match.
|
||||
|
||||
cursor = self.db.get_family_cursor()
|
||||
node = cursor.next()
|
||||
myfamily = None
|
||||
while node:
|
||||
# data[2] == father_handle field, data[2] == mother_handle field
|
||||
(thandle,data) = node
|
||||
if data[2] == fhandle and data[3] == mhandle and thandle != family_handle:
|
||||
myfamily = RelLib.Family()
|
||||
myfamily.unserialize(data)
|
||||
break
|
||||
node = cursor.next()
|
||||
|
||||
if __debug__:
|
||||
if myfamily:
|
||||
print "TargetFamily: %s" % myfamily.get_handle()
|
||||
else:
|
||||
print "TargetFamily: None"
|
||||
|
||||
cursor.close()
|
||||
return myfamily
|
||||
|
||||
def merge_existing_family(self, new, src_family, tgt_family, trans):
|
||||
|
||||
src_family_handle = src_family.get_handle()
|
||||
|
||||
father_id = tgt_family.get_father_handle()
|
||||
father = self.db.get_person_from_handle(father_id)
|
||||
|
||||
mother_id = tgt_family.get_mother_handle()
|
||||
mother = self.db.get_person_from_handle(mother_id)
|
||||
|
||||
if father and src_family_handle in father.get_family_handle_list():
|
||||
father.remove_family_handle(src_family_handle)
|
||||
if __debug__:
|
||||
print "Removed family %s from father %s" % (src_family_handle, father_id)
|
||||
self.db.commit_person(father,trans)
|
||||
if mother and src_family_handle in mother.get_family_handle_list():
|
||||
mother.remove_family_handle(src_family_handle)
|
||||
if __debug__:
|
||||
print "Removed family %s from mother %s" % (src_family_handle, mother_id)
|
||||
self.db.commit_person(mother,trans)
|
||||
|
||||
self.merge_family_pair(tgt_family,src_family,trans)
|
||||
|
||||
for child_handle in src_family.get_child_handle_list():
|
||||
if child_handle != self.new_handle:
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
if child.remove_parent_family_handle(src_family_handle):
|
||||
self.db.commit_person(child,trans)
|
||||
|
||||
# delete the old source family
|
||||
self.db.remove_family(src_family_handle,trans)
|
||||
if __debug__:
|
||||
print "Deleted src_family %s" % src_family_handle
|
||||
self.db.commit_family(tgt_family,trans)
|
||||
new.add_family_handle(tgt_family.get_handle())
|
||||
|
||||
def merge_family_pair(self,tgt_family,src_family,trans):
|
||||
|
||||
@ -391,13 +721,13 @@ class MergePeople:
|
||||
if child_handle not in tgt_family.get_child_handle_list():
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
parents = child.get_parent_family_handle_list()
|
||||
tgt_family.add_child_handle(child)
|
||||
if child.get_main_parents_family_handle() == src_family:
|
||||
child.set_main_parent_family_handle(tgt_family)
|
||||
tgt_family.add_child_handle(child_handle)
|
||||
if child.get_main_parents_family_handle() == src_family.get_handle():
|
||||
child.set_main_parent_family_handle(tgt_family.get_handle())
|
||||
i = 0
|
||||
for fam in parents[:]:
|
||||
if fam[0] == src_family.get_handle():
|
||||
parents[i] = (tgt_family,fam[1],fam[2])
|
||||
parents[i] = (tgt_family.get_handle(),fam[1],fam[2])
|
||||
i += 1
|
||||
self.db.commit_person(child,trans)
|
||||
|
||||
@ -430,135 +760,48 @@ class MergePeople:
|
||||
for photo in src_family.get_media_list():
|
||||
tgt_family.add_media_reference(photo)
|
||||
|
||||
def merge_families(self,new,trans):
|
||||
def adjust_family_pointers(self, tgt_family, src_family, trans):
|
||||
"""
|
||||
Remove the people from one family and merge them into the other.
|
||||
It is not necessary to remove from the src_family, since the
|
||||
src_family is going to be removed.
|
||||
"""
|
||||
src_family_handle = src_family.get_handle()
|
||||
tgt_family_handle = tgt_family.get_handle()
|
||||
|
||||
family_num = 0
|
||||
family_list = self.p1.get_family_handle_list()
|
||||
|
||||
for src_family_handle in self.p2.get_family_handle_list():
|
||||
father_handle = src_family.get_father_handle()
|
||||
if father_handle:
|
||||
father = self.db.get_person_from_handle(father_handle)
|
||||
|
||||
src_family = self.db.get_family_from_handle(src_family_handle)
|
||||
family_num += 1
|
||||
# add to new family
|
||||
father.add_family_handle(tgt_family_handle)
|
||||
if __debug__:
|
||||
print "Added family %s to father %s" % (
|
||||
tgt_family_handle, father_handle)
|
||||
|
||||
if not src_family or src_family in family_list:
|
||||
continue
|
||||
# commit the change
|
||||
self.db.commit_person(father,trans)
|
||||
|
||||
tgt_family = self.find_family(src_family)
|
||||
mother_handle = src_family.get_mother_handle()
|
||||
if mother_handle:
|
||||
mother = self.db.get_person_from_handle(mother_handle)
|
||||
|
||||
#
|
||||
# This is the case where a new family to be added to the
|
||||
# p1 as a result of the merge already exists as a
|
||||
# family. In this case, we need to remove the old source
|
||||
# family (with the pre-merge identity of the p1) from
|
||||
# both the parents
|
||||
#
|
||||
# add to new family
|
||||
mother.add_family_handle(tgt_family_handle)
|
||||
if __debug__:
|
||||
print "Added family %s to mother %s" % (
|
||||
tgt_family_handle, mother_handle)
|
||||
|
||||
if tgt_family:
|
||||
tgt_family_handle = tgt_family.get_handle()
|
||||
if tgt_family_handle in self.p1.get_family_handle_list():
|
||||
|
||||
father_id = tgt_family.get_father_handle()
|
||||
father = self.db.get_person_from_handle(father_id)
|
||||
|
||||
mother_id = tgt_family.get_mother_handle()
|
||||
mother = self.db.get_person_from_handle(mother_id)
|
||||
# commit the change
|
||||
self.db.commit_person(mother,trans)
|
||||
|
||||
if father and src_family_handle in father.get_family_handle_list():
|
||||
father.remove_family_handle(src_family_handle)
|
||||
self.db.commit_person(father,trans)
|
||||
if mother and src_family_handle in mother.get_family_handle_list():
|
||||
mother.remove_family_handle(src_family_handle)
|
||||
self.db.commit_person(mother,trans)
|
||||
|
||||
self.merge_family_pair(tgt_family,src_family,trans)
|
||||
|
||||
for child_handle in src_family.get_child_handle_list():
|
||||
if child_handle != self.new_handle:
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
if child.remove_parent_family_handle(src_family_handle):
|
||||
self.db.commit_person(child,trans)
|
||||
# remove the children from the old family
|
||||
for child_handle in src_family.get_child_handle_list():
|
||||
if child_handle != self.new_handle:
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
if child.remove_parent_family_handle(src_family_handle):
|
||||
self.db.commit_person(child,trans)
|
||||
|
||||
# delete the old source family
|
||||
self.db.remove_family(src_family_handle,trans)
|
||||
self.db.commit_family(tgt_family,trans)
|
||||
|
||||
new.add_family_handle(tgt_family_handle)
|
||||
|
||||
continue
|
||||
|
||||
# This is the case where a new family to be added
|
||||
# and it is not already in the list.
|
||||
|
||||
else:
|
||||
|
||||
# tgt_family a duplicate family, transfer children from
|
||||
# the p2 family, and delete the family. Not sure
|
||||
# what to do about marriage/divorce date/place yet.
|
||||
|
||||
# transfer child to new family, alter children to
|
||||
# point to the correct family
|
||||
|
||||
self.merge_family_pair(tgt_family,src_family,trans)
|
||||
|
||||
# change parents of the family to point to the new
|
||||
# family
|
||||
|
||||
father_handle = src_family.get_father_handle()
|
||||
if father_handle:
|
||||
father = self.db.get_person_from_handle(father_handle)
|
||||
father.remove_family_handle(src_family_handle)
|
||||
father.add_family_handle(tgt_family_handle)
|
||||
self.db.commit_person(father,trans)
|
||||
|
||||
mother_handle = src_family.get_mother_handle()
|
||||
if mother_handle:
|
||||
mother = self.db.get_person_from_handle(mother_handle)
|
||||
mother.remove_family_handle(src_family_handle)
|
||||
mother.add_family_handle(tgt_family_handle)
|
||||
self.db.commit_person(mother,trans)
|
||||
|
||||
for child_handle in src_family.get_child_handle_list():
|
||||
if child_handle != self.new_handle:
|
||||
child = self.db.get_person_from_handle(child_handle)
|
||||
if child.remove_parent_family_handle(src_family_handle):
|
||||
self.db.commit_person(child,trans)
|
||||
|
||||
new.remove_family_handle(src_family_handle)
|
||||
self.db.remove_family(src_family_handle,trans)
|
||||
|
||||
else:
|
||||
|
||||
for fid in self.p1.get_family_handle_list():
|
||||
new.add_family_handle(fid)
|
||||
|
||||
for src_family_handle in self.p2.get_family_handle_list():
|
||||
if src_family_handle in self.p1.get_family_handle_list():
|
||||
continue
|
||||
src_family = self.db.get_family_from_handle(src_family_handle)
|
||||
new.add_family_handle(src_family_handle)
|
||||
if src_family.get_father_handle() == self.old_handle:
|
||||
src_family.set_father_handle(self.new_handle)
|
||||
if src_family.get_mother_handle() == self.old_handle:
|
||||
src_family.set_mother_handle(self.new_handle)
|
||||
self.db.commit_family(src_family,trans)
|
||||
|
||||
# a little debugging here
|
||||
|
||||
cursor = self.db.get_family_cursor()
|
||||
data = cursor.first()
|
||||
while data:
|
||||
fam = RelLib.Family()
|
||||
fam.unserialize(data[1])
|
||||
if self.p2 in fam.get_child_handle_list():
|
||||
fam.remove_child_handle(self.p2)
|
||||
fam.add_child_handle(self.p1)
|
||||
if self.p2 == fam.get_father_handle():
|
||||
fam.set_father_handle(self.p1)
|
||||
if self.p2 == fam.get_mother_handle():
|
||||
fam.set_mother_handle(self.p1)
|
||||
if fam.get_father_handle() == None and fam.get_mother_handle() == None:
|
||||
self.delete_empty_family(fam,trans)
|
||||
data = cursor.next()
|
||||
|
||||
def remove_marriage(self,family,person,trans):
|
||||
if person:
|
||||
@ -576,13 +819,8 @@ class MergePeople:
|
||||
child.remove_parent_family_handle(family_handle)
|
||||
self.db.commit_person(child,trans)
|
||||
self.db.remove_family(family_handle,trans)
|
||||
|
||||
def merge_gramps_ids(self,new):
|
||||
new.set_gramps_id(self.p1.get_gramps_id())
|
||||
attr = RelLib.Attribute()
|
||||
attr.set_type('Merged GRAMPS ID')
|
||||
attr.set_value(self.p2.get_gramps_id())
|
||||
new.add_attribute(attr)
|
||||
if __debug__:
|
||||
print "Deleted empty family %s" % family_handle
|
||||
|
||||
def merge_notes(self, note1, note2):
|
||||
if note1 and not note2:
|
||||
@ -595,49 +833,3 @@ class MergePeople:
|
||||
return note1
|
||||
return None
|
||||
|
||||
def merge_names(self, new):
|
||||
new.set_primary_name(self.p1.get_primary_name())
|
||||
new.add_alternate_name(self.p2.get_primary_name())
|
||||
if self.p1.get_nick_name() == "":
|
||||
new.set_nick_name(self.p2.get_nick_name())
|
||||
else:
|
||||
new.set_nick_name(self.p1.get_nick_name())
|
||||
|
||||
def merge_death(self, new, trans):
|
||||
handle1 = self.p1.get_death_handle()
|
||||
handle2 = self.p2.get_death_handle()
|
||||
|
||||
if handle1:
|
||||
new.set_death_handle(handle1)
|
||||
if handle2:
|
||||
event = self.db.get_event_from_handle(handle2)
|
||||
event.set_handle(Utils.create_id())
|
||||
event.set_name('Alternate Death')
|
||||
new.add_event_handle(event.get_handle())
|
||||
self.db.add_event(event,trans)
|
||||
elif not handle1 and handle2:
|
||||
new.set_death_handle(handle2)
|
||||
|
||||
def merge_birth(self, new,trans):
|
||||
handle1 = self.p1.get_birth_handle()
|
||||
handle2 = self.p2.get_birth_handle()
|
||||
|
||||
if handle1:
|
||||
new.set_birth_handle(handle1)
|
||||
if handle2:
|
||||
event = self.db.get_event_from_handle(handle2)
|
||||
event.set_name('Alternate Birth')
|
||||
self.db.add_event(event,trans)
|
||||
new.add_event_handle(event.get_handle())
|
||||
elif not handle1 and handle2:
|
||||
new.set_birth_handle(handle2)
|
||||
|
||||
def merge_event_lists(self, new):
|
||||
data_list = new.get_event_list()
|
||||
for handle in self.p1.get_event_list():
|
||||
if handle not in data_list:
|
||||
data_list.append(handle)
|
||||
for handle in self.p2.get_event_list():
|
||||
if handle not in data_list:
|
||||
data_list.append(handle)
|
||||
new.set_event_list(data_list)
|
||||
|
@ -82,21 +82,49 @@ class PlaceView:
|
||||
|
||||
self.list.set_model(self.model)
|
||||
self.topWindow = self.glade.get_widget("gramps")
|
||||
|
||||
self.sort_col = 0
|
||||
|
||||
self.columns = []
|
||||
self.change_db(db)
|
||||
|
||||
def column_clicked(self,obj,data):
|
||||
if self.sort_col != data:
|
||||
order = gtk.SORT_ASCENDING
|
||||
else:
|
||||
if (self.columns[data].get_sort_order() == gtk.SORT_DESCENDING
|
||||
or self.columns[data].get_sort_indicator() == False):
|
||||
order = gtk.SORT_ASCENDING
|
||||
else:
|
||||
order = gtk.SORT_DESCENDING
|
||||
self.sort_col = data
|
||||
handle = self.first_selected()
|
||||
self.model = DisplayModels.PlaceModel(self.parent.db,
|
||||
self.sort_col,order)
|
||||
self.list.set_model(self.model)
|
||||
|
||||
colmap = self.parent.db.get_place_column_order()
|
||||
|
||||
if handle:
|
||||
path = self.model.on_get_path(handle)
|
||||
self.selection.select_path(path)
|
||||
self.list.scroll_to_cell(path,None,1,0.5,0)
|
||||
for i in range(0,len(self.columns)):
|
||||
self.columns[i].set_sort_indicator(i==colmap[data][1]-1)
|
||||
self.columns[self.sort_col].set_sort_order(order)
|
||||
|
||||
def build_columns(self):
|
||||
for column in self.columns:
|
||||
self.list.remove_column(column)
|
||||
|
||||
column = gtk.TreeViewColumn(_('Place Name'), self.renderer,text=0)
|
||||
column.set_resizable(True)
|
||||
|
||||
column.set_min_width(225)
|
||||
column.connect('clicked',self.column_clicked,0)
|
||||
column.set_clickable(True)
|
||||
self.list.append_column(column)
|
||||
self.columns = [column]
|
||||
|
||||
index = 1
|
||||
for pair in self.parent.db.get_place_column_order():
|
||||
if not pair[0]:
|
||||
continue
|
||||
@ -104,6 +132,9 @@ class PlaceView:
|
||||
column = gtk.TreeViewColumn(name, self.renderer, text=pair[1])
|
||||
column.set_resizable(True)
|
||||
column.set_min_width(75)
|
||||
column.set_clickable(True)
|
||||
column.connect('clicked',self.column_clicked,index)
|
||||
index += 1
|
||||
self.columns.append(column)
|
||||
self.list.append_column(column)
|
||||
|
||||
@ -236,6 +267,14 @@ class PlaceView:
|
||||
place = self.parent.db.get_place_from_handle(place_handle)
|
||||
EditPlace.EditPlace(self.parent, place,self.topWindow)
|
||||
|
||||
def first_selected(self):
|
||||
mlist = []
|
||||
self.selection.selected_foreach(self.blist,mlist)
|
||||
if mlist:
|
||||
return mlist[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def blist(self,store,path,iter,list):
|
||||
handle = store.get_value(iter,_HANDLE_COL)
|
||||
list.append(handle)
|
||||
|
@ -438,9 +438,9 @@ class GedcomParser:
|
||||
ln = len(l)
|
||||
try:
|
||||
if ln == 2:
|
||||
self.groups = (int(l[0]),l[1],"")
|
||||
self.groups = (int(l[0]),unicode(l[1]),u"")
|
||||
else:
|
||||
self.groups = (int(l[0]),l[1],l[2])
|
||||
self.groups = (int(l[0]),unicode(l[1]),unicode(l[2]))
|
||||
except:
|
||||
if self.text == "":
|
||||
msg = _("Warning: line %d was blank, so it was ignored.\n") % self.index
|
||||
@ -528,9 +528,9 @@ class GedcomParser:
|
||||
|
||||
def parse_trailer(self):
|
||||
matches = self.get_next()
|
||||
if matches[1] != "TRLR":
|
||||
if matches[0] >= 0 and matches[1] != "TRLR":
|
||||
self.barf(0)
|
||||
self.f.close()
|
||||
self.f.close()
|
||||
|
||||
def parse_header(self):
|
||||
self.parse_header_head()
|
||||
@ -551,7 +551,7 @@ class GedcomParser:
|
||||
self.backup()
|
||||
return
|
||||
elif matches[1] == "NAME":
|
||||
self.def_src.set_author(unicode(matches[2]))
|
||||
self.def_src.set_author(matches[2])
|
||||
elif matches[1] == ["ADDR"]:
|
||||
self.ignore_sub_junk(level+1)
|
||||
|
||||
@ -573,7 +573,7 @@ class GedcomParser:
|
||||
title = matches[2] + self.parse_continue_data(level+1)
|
||||
title = title.replace('\n',' ')
|
||||
self.source.set_title(title)
|
||||
elif matches[1] == "TAXT" or matches[1] == "PERI": # EasyTree Sierra On-Line
|
||||
elif matches[1] in ["TAXT","PERI"]: # EasyTree Sierra On-Line
|
||||
if self.source.get_title() == "":
|
||||
title = matches[2] + self.parse_continue_data(level+1)
|
||||
title = title.replace('\n',' ')
|
||||
@ -603,7 +603,7 @@ class GedcomParser:
|
||||
note = "%s %s" % (matches[1],matches[2])
|
||||
|
||||
def parse_record(self):
|
||||
while 1:
|
||||
while True:
|
||||
matches = self.get_next()
|
||||
if matches[2] == "FAM":
|
||||
if self.fam_count % UPDATE == 0 and self.window:
|
||||
@ -654,6 +654,12 @@ class GedcomParser:
|
||||
self.ignore_sub_junk(1)
|
||||
elif matches[2] == "SOUR":
|
||||
self.parse_source(matches[1],1)
|
||||
elif matches[2].startswith("SOUR "):
|
||||
# A source formatted in a single line, for example:
|
||||
# 0 @S62@ SOUR This is the title of the source
|
||||
source = self.find_or_create_source(matches[1][1:-1])
|
||||
source.set_title( matches[2][5:])
|
||||
self.db.commit_source(source, self.trans)
|
||||
elif matches[2][0:4] == "NOTE":
|
||||
if self.nmap.has_key(matches[1]):
|
||||
noteobj = self.nmap[matches[1]]
|
||||
@ -668,7 +674,7 @@ class GedcomParser:
|
||||
# TODO: Add support for extended Locations.
|
||||
# See: http://en.wiki.genealogy.net/index.php/Gedcom_5.5EL
|
||||
self.ignore_sub_junk(1)
|
||||
elif matches[0] < 1 or matches[1] == "TRLR":
|
||||
elif matches[0] < 0 or matches[1] == "TRLR":
|
||||
self.backup()
|
||||
return
|
||||
else:
|
||||
@ -914,9 +920,9 @@ class GedcomParser:
|
||||
def parse_individual(self):
|
||||
name_cnt = 0
|
||||
note = ""
|
||||
while 1:
|
||||
while True:
|
||||
matches = self.get_next()
|
||||
|
||||
|
||||
if int(matches[0]) < 1:
|
||||
self.backup()
|
||||
return
|
||||
@ -1019,6 +1025,8 @@ class GedcomParser:
|
||||
self.person.add_address(addr)
|
||||
elif matches[1] == "BIRT":
|
||||
event = RelLib.Event()
|
||||
if matches[2]:
|
||||
event.set_description(matches[2])
|
||||
self.db.add_event(event, self.trans)
|
||||
if self.person.get_birth_handle():
|
||||
event.set_name("Alternate Birth")
|
||||
@ -1037,6 +1045,8 @@ class GedcomParser:
|
||||
self.db.commit_event(event, self.trans)
|
||||
elif matches[1] == "DEAT":
|
||||
event = RelLib.Event()
|
||||
if matches[2]:
|
||||
event.set_description(matches[2])
|
||||
self.db.add_event(event, self.trans)
|
||||
if self.person.get_death_handle():
|
||||
event.set_name("Alternate Death")
|
||||
@ -1074,7 +1084,7 @@ class GedcomParser:
|
||||
attr.set_type(matches[1])
|
||||
attr.set_value(matches[2])
|
||||
self.person.add_attribute(attr)
|
||||
elif matches[1] in ["CHAN","ASSO","ANCI","DESI","RIN"]:
|
||||
elif matches[1] in ["CHAN","ASSO","ANCI","DESI","RIN","_TODO"]:
|
||||
self.ignore_sub_junk(2)
|
||||
else:
|
||||
event = RelLib.Event()
|
||||
@ -1150,9 +1160,12 @@ class GedcomParser:
|
||||
filename = ""
|
||||
title = "no title"
|
||||
note = ""
|
||||
while 1:
|
||||
while True:
|
||||
matches = self.get_next()
|
||||
if matches[1] == "FORM":
|
||||
if int(matches[0]) < level:
|
||||
self.backup()
|
||||
break
|
||||
elif matches[1] == "FORM":
|
||||
form = matches[2].lower()
|
||||
elif matches[1] == "TITL":
|
||||
title = matches[2]
|
||||
@ -1162,9 +1175,6 @@ class GedcomParser:
|
||||
note = matches[2] + self.parse_continue_data(level+1)
|
||||
elif matches[1][0] == "_":
|
||||
self.ignore_sub_junk(level+1)
|
||||
elif int(matches[0]) < level:
|
||||
self.backup()
|
||||
break
|
||||
else:
|
||||
self.barf(level+1)
|
||||
|
||||
@ -1180,21 +1190,22 @@ class GedcomParser:
|
||||
self.warn(_("\tThe following paths were tried:\n\t\t"))
|
||||
self.warn("\n\t\t".join(path))
|
||||
self.warn('\n')
|
||||
path = filename.replace('\\','/')
|
||||
photo_handle = self.media_map.get(path)
|
||||
if photo_handle == None:
|
||||
photo = RelLib.MediaObject()
|
||||
photo.set_path(path)
|
||||
photo.set_description(title)
|
||||
photo.set_mime_type(GrampsMime.get_type(os.path.abspath(path)))
|
||||
self.db.add_object(photo, self.trans)
|
||||
self.media_map[path] = photo.get_handle()
|
||||
else:
|
||||
photo_handle = self.media_map.get(path)
|
||||
if photo_handle == None:
|
||||
photo = RelLib.MediaObject()
|
||||
photo.set_path(path)
|
||||
photo.set_description(title)
|
||||
photo.set_mime_type(GrampsMime.get_type(os.path.abspath(path)))
|
||||
self.db.add_object(photo, self.trans)
|
||||
self.media_map[path] = photo.get_handle()
|
||||
else:
|
||||
photo = self.db.get_object_from_handle(photo_handle)
|
||||
oref = RelLib.MediaRef()
|
||||
oref.set_reference_handle(photo.get_handle())
|
||||
self.person.add_media_reference(oref)
|
||||
self.db.commit_person(self.person, self.trans)
|
||||
photo = self.db.get_object_from_handle(photo_handle)
|
||||
oref = RelLib.MediaRef()
|
||||
oref.set_reference_handle(photo.get_handle())
|
||||
oref.set_note(note)
|
||||
self.person.add_media_reference(oref)
|
||||
self.db.commit_person(self.person, self.trans)
|
||||
|
||||
def parse_family_object(self,level):
|
||||
form = ""
|
||||
@ -1224,21 +1235,22 @@ class GedcomParser:
|
||||
self.warn(_("\tThe following paths were tried:\n\t\t"))
|
||||
self.warn("\n\t\t".join(path))
|
||||
self.warn('\n')
|
||||
path = filename.replace('\\','/')
|
||||
photo_handle = self.media_map.get(path)
|
||||
if photo_handle == None:
|
||||
photo = RelLib.MediaObject()
|
||||
photo.set_path(path)
|
||||
photo.set_description(title)
|
||||
photo.set_mime_type(GrampsMime.get_type(os.path.abspath(path)))
|
||||
self.db.add_object(photo, self.trans)
|
||||
self.media_map[path] = photo.get_handle()
|
||||
else:
|
||||
photo_handle = self.media_map.get(path)
|
||||
if photo_handle == None:
|
||||
photo = RelLib.MediaObject()
|
||||
photo.set_path(path)
|
||||
photo.set_description(title)
|
||||
photo.set_mime_type(GrampsMime.get_type(os.path.abspath(path)))
|
||||
self.db.add_object(photo, self.trans)
|
||||
self.media_map[path] = photo.get_handle()
|
||||
else:
|
||||
photo = self.db.get_object_from_handle(photo_handle)
|
||||
oref = RelLib.MediaRef()
|
||||
oref.set_reference_handle(photo.get_handle())
|
||||
self.family.add_media_reference(oref)
|
||||
self.db.commit_family(self.family, self.trans)
|
||||
photo = self.db.get_object_from_handle(photo_handle)
|
||||
oref = RelLib.MediaRef()
|
||||
oref.set_reference_handle(photo.get_handle())
|
||||
oref.set_note(note)
|
||||
self.family.add_media_reference(oref)
|
||||
self.db.commit_family(self.family, self.trans)
|
||||
|
||||
def parse_residence(self,address,level):
|
||||
note = ""
|
||||
@ -1296,8 +1308,14 @@ class GedcomParser:
|
||||
address.set_postal_code(matches[2])
|
||||
elif matches[1] == "CTRY":
|
||||
address.set_country(matches[2])
|
||||
elif matches[1] == "PHON":
|
||||
address.set_phone(matches[2])
|
||||
elif matches[1] == "NOTE":
|
||||
note = self.parse_note(matches,address,level+1,note)
|
||||
elif matches[1] == "_LOC":
|
||||
pass # ignore unsupported extended location syntax
|
||||
elif matches[1] == "_NAME":
|
||||
pass # ignore
|
||||
else:
|
||||
self.barf(level+1)
|
||||
|
||||
@ -1357,6 +1375,8 @@ class GedcomParser:
|
||||
event.set_name(name)
|
||||
else:
|
||||
event.set_description(matches[2])
|
||||
elif matches[1] == "_PRIV" and matches[2] == "Y":
|
||||
event.set_privacy(True)
|
||||
elif matches[1] == "DATE":
|
||||
event.set_date_object(self.extract_date(matches[2]))
|
||||
elif matches[1] == "SOUR":
|
||||
@ -1585,10 +1605,13 @@ class GedcomParser:
|
||||
return
|
||||
elif matches[1] == "PAGE":
|
||||
source.set_page(matches[2] + self.parse_continue_data(level+1))
|
||||
elif matches[1] == "DATE":
|
||||
source.set_date_object(self.extract_date(matches[2]))
|
||||
elif matches[1] == "DATA":
|
||||
date,text = self.parse_source_data(level+1)
|
||||
d = self.dp.parse(date)
|
||||
source.set_date_object(d)
|
||||
if date:
|
||||
d = self.dp.parse(date)
|
||||
source.set_date_object(d)
|
||||
source.set_text(text)
|
||||
elif matches[1] in ["OBJE","REFN","TEXT"]:
|
||||
self.ignore_sub_junk(level+1)
|
||||
@ -1721,9 +1744,9 @@ class GedcomParser:
|
||||
pass
|
||||
elif matches[1] == "FILE":
|
||||
filename = os.path.basename(matches[2]).split('\\')[-1]
|
||||
self.def_src.set_title(_("Import from %s") % unicode(filename))
|
||||
self.def_src.set_title(_("Import from %s") % filename)
|
||||
elif matches[1] == "COPR":
|
||||
self.def_src.set_publication_info(unicode(matches[2]))
|
||||
self.def_src.set_publication_info(matches[2])
|
||||
elif matches[1] in ["CORP","DATA","SUBM","SUBN","LANG"]:
|
||||
self.ignore_sub_junk(2)
|
||||
elif matches[1] == "DEST":
|
||||
@ -1751,7 +1774,7 @@ class GedcomParser:
|
||||
elif matches[1] == "DATE":
|
||||
date = self.parse_date(2)
|
||||
date.date = matches[2]
|
||||
self.def_src.set_data_item('Creation date',unicode(matches[2]))
|
||||
self.def_src.set_data_item('Creation date',matches[2])
|
||||
elif matches[1] == "NOTE":
|
||||
note = matches[2] + self.parse_continue_data(2)
|
||||
elif matches[1][0] == "_":
|
||||
|
@ -24,7 +24,6 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
import string
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@ -96,6 +96,8 @@ class BaseObject:
|
||||
# Run through its own items
|
||||
patern_upper = pattern.upper()
|
||||
for item in self.get_text_data_list():
|
||||
if not item:
|
||||
continue
|
||||
if case_sensitive:
|
||||
if item.find(pattern) != -1:
|
||||
return True
|
||||
@ -127,7 +129,7 @@ class BaseObject:
|
||||
else:
|
||||
pattern_obj = re.compile(pattern,re.IGNORECASE)
|
||||
for item in self.get_text_data_list():
|
||||
if pattern_obj.match(item):
|
||||
if item and pattern_obj.match(item):
|
||||
return True
|
||||
|
||||
# Run through child objects
|
||||
@ -521,10 +523,13 @@ class SourceNote(BaseObject,NoteBase):
|
||||
@param new_handle: The source handle to replace the old one with.
|
||||
@type new_handle: str
|
||||
"""
|
||||
while old_handle in self.source_list:
|
||||
ix = self.source_list.index(old_handle)
|
||||
self.source_list[ix] = new_handle
|
||||
|
||||
refs_list = [ src_ref.ref for src_ref in self.source_list ]
|
||||
n_replace = refs_list.count(old_handle)
|
||||
for ix_replace in xrange(n_replace):
|
||||
ix = refs_list.index(old_handle)
|
||||
self.source_list[ix].ref = new_handle
|
||||
refs_list.pop(ix)
|
||||
|
||||
for item in self.get_sourcref_child_list():
|
||||
item.replace_source_references(old_handle,new_handle)
|
||||
|
||||
@ -618,9 +623,12 @@ class MediaBase:
|
||||
@param new_handle: The media handle to replace the old one with.
|
||||
@type new_handle: str
|
||||
"""
|
||||
while old_handle in self.media_list:
|
||||
ix = self.media_list.index(old_handle)
|
||||
self.media_list[ix] = new_handle
|
||||
refs_list = [ media_ref.ref for media_ref in self.media_list ]
|
||||
n_replace = refs_list.count(old_handle)
|
||||
for ix_replace in xrange(n_replace):
|
||||
ix = refs_list.index(old_handle)
|
||||
self.media_list[ix].ref = new_handle
|
||||
refs_list.pop(ix)
|
||||
|
||||
class DateBase:
|
||||
"""
|
||||
@ -1038,7 +1046,7 @@ class Person(PrimaryObject,PrivateSourceNote,MediaBase,AttributeBase):
|
||||
@return: Returns the list of all textual attributes of the object.
|
||||
@rtype: list
|
||||
"""
|
||||
return [self.nickname]
|
||||
return [self.nickname,self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
@ -1768,6 +1776,15 @@ class Family(PrimaryObject,SourceNote,MediaBase,AttributeBase):
|
||||
if self.lds_seal and self.lds_seal.place == old_handle:
|
||||
self.lds_seal.place = new_handle
|
||||
|
||||
def get_text_data_list(self):
|
||||
"""
|
||||
Returns the list of all textual attributes of the object.
|
||||
|
||||
@return: Returns the list of all textual attributes of the object.
|
||||
@rtype: list
|
||||
"""
|
||||
return [self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
Returns the list of child objects that may carry textual data.
|
||||
@ -2119,7 +2136,7 @@ class Event(PrimaryObject,PrivateSourceNote,MediaBase,DateBase,PlaceBase):
|
||||
@return: Returns the list of all textual attributes of the object.
|
||||
@rtype: list
|
||||
"""
|
||||
return [self.description,self.name,self.cause,self.get_date()]
|
||||
return [self.description,self.name,self.cause,self.get_date(),self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
@ -2394,7 +2411,7 @@ class Place(PrimaryObject,SourceNote,MediaBase):
|
||||
@return: Returns the list of all textual attributes of the object.
|
||||
@rtype: list
|
||||
"""
|
||||
return [self.long,self.lat,self.title]
|
||||
return [self.long,self.lat,self.title,self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
@ -2653,7 +2670,7 @@ class MediaObject(PrimaryObject,SourceNote,DateBase,AttributeBase):
|
||||
@return: Returns the list of all textual attributes of the object.
|
||||
@rtype: list
|
||||
"""
|
||||
return [self.path,self.mime,self.desc,self.get_date()]
|
||||
return [self.path,self.mime,self.desc,self.get_date(),self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
@ -2757,7 +2774,7 @@ class Source(PrimaryObject,MediaBase,NoteBase):
|
||||
@return: Returns the list of all textual attributes of the object.
|
||||
@rtype: list
|
||||
"""
|
||||
return [self.title,self.author,self.pubinfo,self.abbrev]
|
||||
return [self.title,self.author,self.pubinfo,self.abbrev,self.gramps_id]
|
||||
|
||||
def get_text_data_child_list(self):
|
||||
"""
|
||||
@ -2939,7 +2956,7 @@ class LdsOrd(SourceNote,DateBase,PlaceBase):
|
||||
if self.place:
|
||||
return [('Place',self.place)]
|
||||
else:
|
||||
return []
|
||||
return []
|
||||
|
||||
def get_handle_referents(self):
|
||||
"""
|
||||
@ -3879,7 +3896,7 @@ class Witness(BaseObject,PrivacyBase):
|
||||
if self.type == Event.ID:
|
||||
return [('Person',self.val)]
|
||||
else:
|
||||
return []
|
||||
return []
|
||||
|
||||
def set_type(self,type):
|
||||
self.type = type
|
||||
@ -4035,6 +4052,8 @@ class GenderStats:
|
||||
return (0, 0, 0)
|
||||
|
||||
def count_person (self, person, db, undo = 0):
|
||||
if not person:
|
||||
return
|
||||
# Let the Person do their own counting later
|
||||
person.db = db
|
||||
|
||||
|
@ -416,9 +416,10 @@ def insert_images(database, doc, person, w_cm=4.0, h_cm=4.0):
|
||||
for photo in photos :
|
||||
object_handle = photo.get_reference_handle()
|
||||
media_object = database.get_object_from_handle(object_handle)
|
||||
if media_object.get_mime_type()[0:5] == "image":
|
||||
mime_type = media_object.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
filename = media_object.get_path()
|
||||
doc.add_media_object(filename,"row")
|
||||
doc.add_media_object(filename,"row",w_cm,h_cm)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -795,6 +796,10 @@ def married_str(database,person,spouse,event,endnotes=None,
|
||||
@rtype: unicode
|
||||
"""
|
||||
|
||||
# not all families have a spouse.
|
||||
if not spouse:
|
||||
return u""
|
||||
|
||||
if not endnotes:
|
||||
endnotes = empty_notes
|
||||
|
||||
@ -1803,4 +1808,4 @@ def old_calc_age(database,person):
|
||||
if age == 0:
|
||||
age = death.get_day() + 31 - birth.get_day() # calc age in days
|
||||
units = 3 # day
|
||||
return (age,units)
|
||||
return (age,units)
|
||||
|
@ -295,10 +295,12 @@ class SelectChild:
|
||||
self.family = RelLib.Family()
|
||||
self.db.add_family(self.family,trans)
|
||||
self.person.add_family_handle(self.family.get_handle())
|
||||
self.db.commit_person(self.person,trans)
|
||||
if self.person.get_gender() == RelLib.Person.MALE:
|
||||
self.family.set_father_handle(self.person)
|
||||
self.family.set_father_handle(self.person.get_handle())
|
||||
else:
|
||||
self.family.set_mother_handle(self.person)
|
||||
self.family.set_mother_handle(self.person.get_handle())
|
||||
self.db.commit_family(self.family,trans)
|
||||
|
||||
if handle in (self.family.get_father_handle(),self.family.get_mother_handle()):
|
||||
ErrorDialog(_("Error selecting a child"),
|
||||
@ -328,6 +330,7 @@ class SelectChild:
|
||||
n = select_child.get_primary_name().get_regular_name()
|
||||
self.db.transaction_commit(trans,_("Add Child to Family (%s)") % n)
|
||||
self.close(obj)
|
||||
self.callback()
|
||||
|
||||
def on_show_toggled(self,obj):
|
||||
self.redraw_child_list(not obj.get_active())
|
||||
@ -378,4 +381,3 @@ class SelectChild:
|
||||
return ("","%sdóttir" % fname)
|
||||
else:
|
||||
return ("","")
|
||||
|
||||
|
@ -113,15 +113,14 @@ class SelectObject:
|
||||
data = self.object_model.get_data(node,range(self.ncols))
|
||||
handle = data[4]
|
||||
obj = self.db.get_object_from_handle(handle)
|
||||
the_type = Utils.get_mime_description(obj.get_mime_type())
|
||||
the_type = obj.get_mime_type()
|
||||
path = obj.get_path()
|
||||
|
||||
if the_type[0:5] == "image":
|
||||
image = ImgManip.get_thumbnail_image(obj.get_path())
|
||||
self.preview.set_from_pixbuf(image)
|
||||
if the_type and the_type[0:5] == "image":
|
||||
image = ImgManip.get_thumbnail_image(path)
|
||||
else:
|
||||
icon_image = Utils.find_mime_type_pixbuf(the_type)
|
||||
self.preview.set_from_pixbuf(icon_image)
|
||||
image = Utils.find_mime_type_pixbuf(the_type)
|
||||
self.preview.set_from_pixbuf(image)
|
||||
|
||||
self.object_handle.set_text(obj.get_gramps_id())
|
||||
self.object_type.set_text(the_type)
|
||||
|
@ -67,21 +67,47 @@ class SourceView:
|
||||
def __init__(self,parent,db,glade):
|
||||
self.parent = parent
|
||||
self.parent.connect('database-changed',self.change_db)
|
||||
|
||||
self.glade = glade
|
||||
self.list = glade.get_widget("source_list")
|
||||
#self.list.set_property('fixed-height-mode',True)
|
||||
self.list.connect('button-press-event',self.button_press)
|
||||
self.list.connect('key-press-event',self.key_press)
|
||||
self.selection = self.list.get_selection()
|
||||
self.selection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||
|
||||
self.renderer = gtk.CellRendererText()
|
||||
|
||||
self.model = DisplayModels.SourceModel(self.parent.db)
|
||||
self.model = DisplayModels.SourceModel(self.parent.db,0)
|
||||
self.sort_col = 0
|
||||
|
||||
self.list.set_model(self.model)
|
||||
self.list.set_headers_clickable(True)
|
||||
self.topWindow = self.glade.get_widget("gramps")
|
||||
|
||||
self.columns = []
|
||||
self.change_db(db)
|
||||
|
||||
def column_clicked(self,obj,data):
|
||||
if self.sort_col != data:
|
||||
order = gtk.SORT_ASCENDING
|
||||
else:
|
||||
if (self.columns[data].get_sort_order() == gtk.SORT_DESCENDING
|
||||
or self.columns[data].get_sort_indicator() == False):
|
||||
order = gtk.SORT_ASCENDING
|
||||
else:
|
||||
order = gtk.SORT_DESCENDING
|
||||
self.sort_col = data
|
||||
handle = self.first_selected()
|
||||
self.model = DisplayModels.SourceModel(self.parent.db,
|
||||
self.sort_col,order)
|
||||
self.list.set_model(self.model)
|
||||
colmap = self.parent.db.get_place_column_order()
|
||||
|
||||
if handle:
|
||||
path = self.model.on_get_path(handle)
|
||||
self.selection.select_path(path)
|
||||
self.list.scroll_to_cell(path,None,1,0.5,0)
|
||||
for i in range(0,len(self.columns)):
|
||||
self.columns[i].set_sort_indicator(i==colmap[data][1]-1)
|
||||
self.columns[self.sort_col].set_sort_order(order)
|
||||
|
||||
def build_columns(self):
|
||||
for column in self.columns:
|
||||
@ -90,21 +116,24 @@ class SourceView:
|
||||
column = gtk.TreeViewColumn(_('Title'), self.renderer,text=0)
|
||||
column.set_resizable(True)
|
||||
column.set_min_width(225)
|
||||
column.set_clickable(True)
|
||||
column.connect('clicked',self.column_clicked,0)
|
||||
self.list.append_column(column)
|
||||
self.columns = [column]
|
||||
|
||||
index = 1
|
||||
for pair in self.parent.db.get_source_column_order():
|
||||
if not pair[0]:
|
||||
continue
|
||||
name = column_names[pair[1]]
|
||||
column = gtk.TreeViewColumn(name, self.renderer, text=pair[1])
|
||||
column.connect('clicked',self.column_clicked,index)
|
||||
column.set_resizable(True)
|
||||
column.set_min_width(75)
|
||||
column.set_clickable(True)
|
||||
self.columns.append(column)
|
||||
self.list.append_column(column)
|
||||
|
||||
def on_click(self,column):
|
||||
self.click_col = column
|
||||
index += 1
|
||||
|
||||
def change_db(self,db):
|
||||
db.connect('source-add', self.source_add)
|
||||
@ -116,7 +145,7 @@ class SourceView:
|
||||
|
||||
def build_tree(self):
|
||||
self.list.set_model(None)
|
||||
self.model = DisplayModels.SourceModel(self.parent.db)
|
||||
self.model = DisplayModels.SourceModel(self.parent.db,self.sort_col)
|
||||
self.list.set_model(self.model)
|
||||
self.selection = self.list.get_selection()
|
||||
self.selection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||
@ -216,6 +245,14 @@ class SourceView:
|
||||
for handle in handle_list:
|
||||
self.model.delete_row_by_handle(handle)
|
||||
|
||||
def first_selected(self):
|
||||
mlist = []
|
||||
self.selection.selected_foreach(self.blist,mlist)
|
||||
if mlist:
|
||||
return mlist[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def blist(self,store,path,iter,sel_list):
|
||||
handle = store.get_value(iter,_HANDLE_COL)
|
||||
sel_list.append(handle)
|
||||
|
@ -286,6 +286,8 @@ class SourceTab:
|
||||
def drag_data_get(self,widget, context, sel_data, info, time):
|
||||
|
||||
store,node = self.selection.get_selected()
|
||||
if not node:
|
||||
return
|
||||
ev = store.get_value(node,2)
|
||||
|
||||
bits_per = 8; # we're going to pass a string
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000-2004 Donald N. Allingham
|
||||
# Copyright (C) 2000-2005 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
|
||||
@ -37,10 +37,9 @@ __version__ = "$Revision$"
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python classes
|
||||
# Gramps modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import string
|
||||
|
||||
import NameDisplay
|
||||
|
||||
@ -126,15 +125,15 @@ class SubstKeywords:
|
||||
def replace(self,line):
|
||||
"""Returns a new line of text with the substitutions performed."""
|
||||
|
||||
line = string.replace(line,"$n",self.n)
|
||||
line = string.replace(line,"$N",self.N)
|
||||
line = string.replace(line,"$b",self.b)
|
||||
line = string.replace(line,"$B",self.B)
|
||||
line = string.replace(line,"$d",self.d)
|
||||
line = string.replace(line,"$D",self.D)
|
||||
line = string.replace(line,"$i",self.i)
|
||||
line = string.replace(line,"$S",self.S)
|
||||
line = string.replace(line,"$s",self.s)
|
||||
line = string.replace(line,"$m",self.m)
|
||||
line = string.replace(line,"$M",self.M)
|
||||
return string.replace(line,"$$",'$')
|
||||
line = line.replace("$n",self.n)
|
||||
line = line.replace("$N",self.N)
|
||||
line = line.replace("$b",self.b)
|
||||
line = line.replace("$B",self.B)
|
||||
line = line.replace("$d",self.d)
|
||||
line = line.replace("$D",self.D)
|
||||
line = line.replace("$i",self.i)
|
||||
line = line.replace("$S",self.S)
|
||||
line = line.replace("$s",self.s)
|
||||
line = line.replace("$m",self.m)
|
||||
line = line.replace("$M",self.M)
|
||||
return line.replace("$$",'$')
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2000 Donald N. Allingham
|
||||
# Copyright (C) 2000-2005 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
|
||||
@ -17,9 +17,11 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
import gzip
|
||||
import cStringIO
|
||||
import string
|
||||
|
||||
_BLKSIZE=512
|
||||
nul = '\0'
|
||||
@ -87,75 +89,74 @@ class TarFile:
|
||||
class ReadTarFile:
|
||||
def __init__(self,name,wd="/tmp"):
|
||||
self.name = name
|
||||
self.wd = wd
|
||||
self.wd = wd
|
||||
self.f = gzip.open(name,"rb")
|
||||
self.pos = 0
|
||||
|
||||
def extract_files(self):
|
||||
data = {}
|
||||
while 1:
|
||||
buf = self.f.read(100)
|
||||
while 1:
|
||||
buf = self.f.read(100)
|
||||
if buf == '':
|
||||
return
|
||||
return
|
||||
index = 0
|
||||
for b in buf:
|
||||
if b != nul:
|
||||
index = index + 1
|
||||
else:
|
||||
if index == 0:
|
||||
for b in buf:
|
||||
if b != nul:
|
||||
index = index + 1
|
||||
else:
|
||||
if index == 0:
|
||||
return data
|
||||
continue
|
||||
filename = buf[0:index]
|
||||
continue
|
||||
filename = buf[0:index]
|
||||
if filename == None:
|
||||
return data
|
||||
self.f.read(24) # modes
|
||||
l = string.replace(self.f.read(12),chr(0),' ')
|
||||
self.f.read(24) # modes
|
||||
l = self.f.read(12)(chr(0),' ')
|
||||
length = int(l,8)
|
||||
self.f.read(12)
|
||||
self.f.read(6)
|
||||
self.f.read(111)
|
||||
self.f.read(12)
|
||||
self.f.read(6)
|
||||
self.f.read(111)
|
||||
|
||||
self.f.read(64)
|
||||
self.f.read(183)
|
||||
self.f.read(64)
|
||||
self.f.read(183)
|
||||
foo = cStringIO.StringIO()
|
||||
data[filename] = foo
|
||||
foo.write(self.f.read(length))
|
||||
foo.reset()
|
||||
self.f.read(_BLKSIZE-(length%_BLKSIZE))
|
||||
foo.write(self.f.read(length))
|
||||
foo.reset()
|
||||
self.f.read(_BLKSIZE-(length%_BLKSIZE))
|
||||
return data
|
||||
|
||||
def extract(self):
|
||||
while 1:
|
||||
buf = self.f.read(100)
|
||||
while 1:
|
||||
buf = self.f.read(100)
|
||||
if buf == '':
|
||||
return
|
||||
return
|
||||
index = 0
|
||||
for b in buf:
|
||||
if b != nul:
|
||||
index = index + 1
|
||||
else:
|
||||
if index == 0:
|
||||
for b in buf:
|
||||
if b != nul:
|
||||
index = index + 1
|
||||
else:
|
||||
if index == 0:
|
||||
return
|
||||
continue
|
||||
filename = buf[0:index]
|
||||
self.f.read(24) # modes
|
||||
continue
|
||||
filename = buf[0:index]
|
||||
self.f.read(24) # modes
|
||||
l = self.f.read(12)
|
||||
length_string = "";
|
||||
for char in l:
|
||||
if ord(char) != 0:
|
||||
length_string = length_string + char
|
||||
length = int(length_string,8)
|
||||
self.f.read(12)
|
||||
self.f.read(6)
|
||||
self.f.read(111)
|
||||
self.f.read(12)
|
||||
self.f.read(6)
|
||||
self.f.read(111)
|
||||
|
||||
self.f.read(64)
|
||||
self.f.read(183)
|
||||
self.f.read(64)
|
||||
self.f.read(183)
|
||||
foo = open("%s/%s" % (self.wd,filename),"wb")
|
||||
foo.write(self.f.read(length))
|
||||
foo.close()
|
||||
self.f.read(_BLKSIZE-(length%_BLKSIZE))
|
||||
foo.write(self.f.read(length))
|
||||
foo.close()
|
||||
self.f.read(_BLKSIZE-(length%_BLKSIZE))
|
||||
|
||||
def close(self):
|
||||
self.f.close()
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#-------------------------------------------------------------------------
|
||||
from xml.parsers.expat import ParserCreate
|
||||
from random import Random
|
||||
from gettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -68,7 +69,7 @@ class TipOfDay:
|
||||
index = 0
|
||||
rval = 0
|
||||
while rval == 0:
|
||||
tip.set_text(tip_list[new_index[index]])
|
||||
tip.set_text(_(tip_list[new_index[index]]))
|
||||
tip.set_use_markup(1)
|
||||
rval = top.run()
|
||||
if index >= len(tip_list)-1:
|
||||
|
@ -59,7 +59,7 @@ def keep_utf8(s):
|
||||
return s
|
||||
|
||||
def iso8859(s):
|
||||
return s.encode('iso-8859-1')
|
||||
return s.encode('iso-8859-1','replace')
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -136,6 +136,8 @@ def add_persons_sources(db,person,slist,private):
|
||||
for event_handle in elist:
|
||||
if event_handle:
|
||||
event = db.get_event_from_handle(event_handle)
|
||||
if not event:
|
||||
continue
|
||||
if private and event.get_privacy():
|
||||
continue
|
||||
for source_ref in event.get_source_references():
|
||||
@ -713,6 +715,8 @@ class GedcomWriter:
|
||||
if not self.plist.has_key(person_handle):
|
||||
continue
|
||||
person = self.db.get_person_from_handle(person_handle)
|
||||
if not person:
|
||||
continue
|
||||
self.writeln("1 CHIL @%s@" % person.get_gramps_id())
|
||||
if self.adopt == GedcomInfo.ADOPT_FTW:
|
||||
if person.get_main_parents_family_handle() == family.get_handle():
|
||||
@ -737,6 +741,8 @@ class GedcomWriter:
|
||||
sorted = []
|
||||
for key in self.slist.keys():
|
||||
source = self.db.get_source_from_handle(key)
|
||||
if not source:
|
||||
continue
|
||||
data = (self.sid (source.get_gramps_id ()), source)
|
||||
sorted.append (data)
|
||||
sorted.sort ()
|
||||
@ -791,16 +797,22 @@ class GedcomWriter:
|
||||
if not restricted:
|
||||
birth_handle = person.get_birth_handle()
|
||||
birth = self.db.get_event_from_handle(birth_handle)
|
||||
if birth_handle and not (self.private and birth.get_privacy()):
|
||||
if birth_handle and birth and not (self.private and birth.get_privacy()):
|
||||
if not birth.get_date_object().is_empty() or birth.get_place_handle():
|
||||
self.writeln("1 BIRT")
|
||||
if birth.get_description() != "":
|
||||
self.writeln("1 BIRT %s" % birth.get_description())
|
||||
else:
|
||||
self.writeln("1 BIRT")
|
||||
self.dump_event_stats(birth)
|
||||
|
||||
death_handle = person.get_death_handle()
|
||||
death = self.db.get_event_from_handle(death_handle)
|
||||
if death_handle and not (self.private and death.get_privacy()):
|
||||
if death_handle and death and not (self.private and death.get_privacy()):
|
||||
if not death.get_date_object().is_empty() or death.get_place_handle():
|
||||
self.writeln("1 DEAT")
|
||||
if birth.get_description() != "":
|
||||
self.writeln("1 DEAT %s" % death.get_description())
|
||||
else:
|
||||
self.writeln("1 DEAT")
|
||||
self.dump_event_stats(death)
|
||||
|
||||
ad = 0
|
||||
@ -813,6 +825,8 @@ class GedcomWriter:
|
||||
if not event_handle:
|
||||
continue
|
||||
event = self.db.get_event_from_handle(event_handle)
|
||||
if not event:
|
||||
continue
|
||||
if self.private and event.get_privacy():
|
||||
continue
|
||||
name = event.get_name()
|
||||
|
@ -306,13 +306,11 @@ class XmlWriter:
|
||||
frel=' frel="%s"' % const.child_rel_notrans[alt[2]]
|
||||
else:
|
||||
frel=''
|
||||
parent_family = self.db.get_family_from_handle (alt[0])
|
||||
self.g.write(" <childof hlink=\"%s\"%s%s/>\n" % \
|
||||
(parent_family.get_handle(), mrel, frel))
|
||||
(alt[0], mrel, frel))
|
||||
|
||||
for family_handle in person.get_family_handle_list():
|
||||
family = self.db.get_family_from_handle (family_handle)
|
||||
self.write_ref("parentin",family.get_handle(),3)
|
||||
self.write_ref("parentin",family_handle,3)
|
||||
|
||||
self.write_note("note",person.get_note_object(),3)
|
||||
for s in person.get_source_references():
|
||||
@ -341,11 +339,9 @@ class XmlWriter:
|
||||
fhandle = family.get_father_handle()
|
||||
mhandle = family.get_mother_handle()
|
||||
if fhandle:
|
||||
fid = self.db.get_person_from_handle (fhandle).get_handle()
|
||||
self.write_ref("father",fid,3)
|
||||
self.write_ref("father",fhandle,3)
|
||||
if mhandle:
|
||||
mid = self.db.get_person_from_handle (mhandle).get_handle()
|
||||
self.write_ref("mother",mid,3)
|
||||
self.write_ref("mother",mhandle,3)
|
||||
for event_handle in family.get_event_list():
|
||||
event = self.db.get_event_from_handle(event_handle)
|
||||
self.dump_event(event,3)
|
||||
@ -355,8 +351,7 @@ class XmlWriter:
|
||||
|
||||
if len(family.get_child_handle_list()) > 0:
|
||||
for person_handle in family.get_child_handle_list():
|
||||
person = self.db.get_person_from_handle (person_handle)
|
||||
self.write_ref("child",person.get_handle(),3)
|
||||
self.write_ref("child",person_handle,3)
|
||||
self.write_attribute_list(family.get_attribute_list())
|
||||
self.write_note("note",family.get_note_object(),3)
|
||||
for s in family.get_source_references():
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2003 Donald N. Allingham
|
||||
# Copyright (C) 2003-2005 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
|
||||
@ -18,6 +18,8 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
import cStringIO
|
||||
|
||||
_onebyte = {
|
||||
@ -331,6 +333,3 @@ def utf8_to_ansel(s):
|
||||
ans = buff.getvalue()
|
||||
buff.close()
|
||||
return ans
|
||||
|
||||
|
||||
|
||||
|
@ -4,5 +4,5 @@ then
|
||||
mv po/template.po po/template.po.bak
|
||||
fi
|
||||
|
||||
./get_strings -o po/template.po *.py */*.py *.glade */*.glade
|
||||
./get_strings -o po/template.po *.py */*.py *.glade */*.glade data/tips.xml
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
# This is the src/data level Makefile
|
||||
# $Id$
|
||||
#
|
||||
SUBDIRS = templates
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/data
|
||||
|
||||
@ -31,24 +33,18 @@ SHARED_MIME_UNINSTALLATION =
|
||||
if !PACKAGER_MODE
|
||||
if GCONF_SCHEMAS_INSTALL
|
||||
GCONF_SCHEMAS_INSTALLATION += \
|
||||
$(INSTALL) -d $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR) ;\
|
||||
$(INSTALL_DATA) $(top_srcdir)/src/data/gramps.schemas $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR) ;\
|
||||
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) \
|
||||
gconftool-2 --makefile-install-rule $(top_srcdir)/src/data/gramps.schemas ;\
|
||||
gconftool-2 --makefile-install-rule $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR)/gramps.schemas ;\
|
||||
pkill gconfd ; echo Restarting gconfd
|
||||
|
||||
GCONF_SCHEMAS_UNINSTALLATION += \
|
||||
rm $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR)/gramps.schemas ;\
|
||||
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) \
|
||||
gconftool-2 --makefile-uninstall-rule $(top_srcdir)/src/data/gramps.schemas
|
||||
gconftool-2 --makefile-uninstall-rule $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR)/gramps.schemas
|
||||
endif
|
||||
if SHARED_MIME_INSTALL
|
||||
SHARED_MIME_INSTALLATION += \
|
||||
$(INSTALL) -d $(DESTDIR)$(SHARED_MIME_DIR)/packages ;\
|
||||
$(INSTALL_DATA) $(top_srcdir)/src/data/gramps.xml $(DESTDIR)$(SHARED_MIME_DIR)/packages ;\
|
||||
update-mime-database $(DESTDIR)$(SHARED_MIME_DIR)
|
||||
SHARED_MIME_UNINSTALLATION += \
|
||||
rm $(DESTDIR)$(SHARED_MIME_DIR)/packages/gramps.xml ;\
|
||||
update-mime-database $(DESTDIR)$(SHARED_MIME_DIR)
|
||||
endif
|
||||
endif
|
||||
@ -63,6 +59,10 @@ install-data-local:
|
||||
$(INSTALL) -d $(DESTDIR)$(prefix)/share/mime-info
|
||||
$(INSTALL_DATA) $(top_srcdir)/src/data/gramps.keys $(DESTDIR)$(prefix)/share/mime-info
|
||||
$(INSTALL_DATA) $(top_srcdir)/src/data/gramps.mime $(DESTDIR)$(prefix)/share/mime-info
|
||||
$(INSTALL) -d $(DESTDIR)$(SHARED_MIME_DIR)/packages
|
||||
$(INSTALL_DATA) $(top_srcdir)/src/data/gramps.xml $(DESTDIR)$(SHARED_MIME_DIR)/packages
|
||||
$(INSTALL) -d $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR)
|
||||
$(INSTALL_DATA) $(top_srcdir)/src/data/gramps.schemas $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR)
|
||||
$(SHARED_MIME_INSTALLATION)
|
||||
$(GCONF_SCHEMAS_INSTALLATION)
|
||||
|
||||
@ -72,5 +72,7 @@ uninstall-local:
|
||||
-rm $(DESTDIR)$(prefix)/share/mime-info/gramps.keys
|
||||
-rm $(DESTDIR)$(prefix)/share/mime-info/gramps.mime
|
||||
-rm $(DESTDIR)$(prefix)/share/application-registry/gramps.applications
|
||||
$(SHARED_MIME_UNINSTALLATION)
|
||||
$(GCONF_SCHEMAS_UNINSTALLATION)
|
||||
-rm $(DESTDIR)$(GCONF_SCHEMA_FILE_DIR)/gramps.schemas
|
||||
-rm $(DESTDIR)$(SHARED_MIME_DIR)/packages/gramps.xml
|
||||
$(SHARED_MIME_UNINSTALLATION)
|
||||
|
@ -7,13 +7,17 @@ Name[nb]=GRAMPS
|
||||
Name[ru]=GRAMPS
|
||||
Name[de]=GRAMPS
|
||||
Name[hu]=GRAMPS
|
||||
Name[nl]=GRAMPS genealogie
|
||||
Name[fi]=GRAMPS sukututkimusohjelma
|
||||
Comment=Manage genealogical information, perform genealogical research and analysis
|
||||
Comment[nl]=Een programma voor genealogie infomatie beheer en genealogisch onderzoek en analyse
|
||||
Comment[sv]=Ett släktforskningsprogram
|
||||
Comment[no]=Et slektsforskningsprogram
|
||||
Comment[nb]=Et slektsforskningsprogram
|
||||
Comment[ru]=Система исследования и анализа генеалогической информации
|
||||
Comment[de]=Ein Programm zur Ahnenforschung
|
||||
Comment[hu]=Örökléskutató és elemző program
|
||||
Comment[fi]=Hallinnoi, tutki ja analysoi sukutietoa
|
||||
Icon=gramps.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
|
@ -10,6 +10,9 @@
|
||||
<mime-type type="application/x-gedcom">
|
||||
<comment xml:lang="en">GEDCOM</comment>
|
||||
<glob pattern="*.ged"/>
|
||||
<glob pattern="*.gedcom"/>
|
||||
<glob pattern="*.GED"/>
|
||||
<glob pattern="*.GEDCOM"/>
|
||||
<magic priority="80">
|
||||
<match type="string" value="0 HEAD" offset="0:1"/>
|
||||
</magic>
|
||||
@ -29,6 +32,7 @@
|
||||
<mime-type type="application/x-geneweb">
|
||||
<comment xml:lang="en">GeneWeb source file</comment>
|
||||
<glob pattern="*.gw"/>
|
||||
<glob pattern="*.GW"/>
|
||||
<magic priority="80">
|
||||
<match type="string" value="fam " offset="0:64"/>
|
||||
</magic>
|
||||
|
@ -4,339 +4,341 @@
|
||||
|
||||
<tips>
|
||||
|
||||
<tip><i>You can represent a range of dates by using the format
|
||||
of "between January 4, 2000 and March 20, 2003"</i></tip>
|
||||
|
||||
|
||||
<tip>You can drag and drop an image from either the Media View or any
|
||||
gallery into another gallery</tip>
|
||||
|
||||
<tip>You can add an image to any gallery or the Media View by dragging and
|
||||
dropping from a file manager or a web browser.</tip>
|
||||
|
||||
<tip>You can set the birth order of children in a family even if you do not
|
||||
have birth dates by using drag and drop.</tip>
|
||||
|
||||
<tip>You can convert an alternate name to the person's preferred name by
|
||||
selecting the desired name in the person's name list, bringing up the context
|
||||
menu by clicking the right mouse button, and selecting from the menu.</tip>
|
||||
|
||||
<tip>
|
||||
<b>ASKING RELATIVES BEFORE IT IS TOO LATE</b>:
|
||||
Your oldest relatives could be your
|
||||
most important source of information. They usually know things about the
|
||||
family that hasn't been written down. They might tell you nuggets about
|
||||
people, the information about whom might one day be reduced to numbers. We
|
||||
often wonder why we didn't write down pieces of information that grandfather
|
||||
told us while we were young. Don't wait till it's too late...
|
||||
<tip>A range of dates can be given by using the format
|
||||
"between January 4, 2000 and March 20, 2003"
|
||||
</tip>
|
||||
|
||||
<!--
|
||||
<tip>
|
||||
<b>EXAMPLES OF A FAMILY TREE</b>: To see how a Gramps family tree database looks,
|
||||
check Help > Open example database. You'll find the elaborate Smith family
|
||||
database, It includes 42 individuals and 15 families, with fairly complete
|
||||
basic data about many of these individuals.
|
||||
In most cases double clicking on a name, source, place or media entry
|
||||
will bring up a window to allow you to edit the object. Note that the
|
||||
result can be dependent on context. For example, in the Family View
|
||||
clicking on a parent or child will bring up the relationship editor.
|
||||
</tip>
|
||||
|
||||
<tip>An image can be added to any gallery or the Media View by dragging and
|
||||
dropping it from a file manager or a web browser.
|
||||
</tip>
|
||||
|
||||
<tip>Birth order of children in a family can be set, even if they do not
|
||||
have birth dates, by using drag and drop.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Talk to Relatives Before It Is Too Late</b>:
|
||||
Your oldest relatives can be your most important source of information.
|
||||
They usually know things about the family that haven't been written down.
|
||||
They might tell you nuggets about
|
||||
people that may one day lead to a new avenue of research.
|
||||
At the very least, you will get to hear some great stories.
|
||||
Don't forget to record the conversations!
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Example of a Family Tree</b>: To see an example of what a family
|
||||
looks like in GRAMPS, check <b>Help > Open example database</b>.
|
||||
You will then be viewing the elaborate Smith family database, which
|
||||
includes 42 individuals and 15 families, with fairly complete
|
||||
data about many of the individuals.
|
||||
</tip>
|
||||
-->
|
||||
|
||||
|
||||
<tip>
|
||||
<b>THE PEOPLE VIEW</b>: The People view throws up a list of all individuals
|
||||
<b>The People View</b>: The People View shows a list of all individuals
|
||||
in the database.
|
||||
<!--
|
||||
You can sort the listing simply by clicking on numerous headings
|
||||
such as name, gender, birth date or death date. Clicking heading the second
|
||||
The listings can be sorted by simply clicking on a heading
|
||||
such as name, gender, birth date or death date. Clicking the heading a second
|
||||
time will reverse the sort.
|
||||
-->
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>FILTERING PEOPLE OUT</b>: In the People view, you can 'filter' out individuals
|
||||
based on certain criteria. Go to the Filter (just to the right of the People
|
||||
icon) and choose one of the dozen different presets. For instance, all
|
||||
<b>Filtering People</b>: In the People View, you can 'filter' individuals
|
||||
based on many criteria. Go to the Filter (just to the right of the People
|
||||
icon) and choose one of the dozen different presets. For example, all
|
||||
adopted people in the family tree can be located. People without a birth
|
||||
date mentioned can also be filtered. To get the results, click on Apply.
|
||||
date mentioned can also be filtered. To get the results click Apply.
|
||||
If the filter controls are not visible, enable them by choosing
|
||||
<b>View > Filter</b>.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>INVERTED FILTERING</b>: You can get another set of results by using the 'invert'
|
||||
option. For instance, if you choose to filter the 'People with children'
|
||||
preset filter, and then invert it, you'll find all the people without
|
||||
children in the family tree.
|
||||
<b>Inverted Filtering</b>:
|
||||
Filters can easily be reversed by using the 'invert' option.
|
||||
For instance, by inverting the 'People with children' filter you can
|
||||
select all people without children.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>LOCATING PEOPLE</b>: In the People view, you can locate any individual by
|
||||
through the list of surnames. Then, click on the names
|
||||
themselves to unfold display of all the individuals with the same last name.
|
||||
<b>Locating People</b>: By default, each surname in the People View is
|
||||
listed only once. By clicking on the arrow to the left of a name, the list
|
||||
will expand to show all individuals with that last name.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>TO ADD INFORMATION TO SELECTED PEOPLE</b>: First, locate them in the People
|
||||
view. (Use the list of surnames, and click on the names to unfold
|
||||
the display of all individuals sharing the name). Then, go to the Family
|
||||
view, and add the relevant information.
|
||||
<b>The Family View</b>: The Family View is used to display a typical
|
||||
family unit---the parents, spouses and children of an individual.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>THE FAMILY VIEW</b>: The Family view display a family of parents, grandparents
|
||||
and children along with the birth and death dates (if relevant) and
|
||||
relationships. You can navigate to nearby relatives with a single click.
|
||||
<b>Shifting a Family View</b>: Changing the Active Person in
|
||||
the Family View is easy. A spouse can be made the Active Person by
|
||||
clicking the button just to the right of the Active Person. A father
|
||||
can be made the Active Person by clicking on the arrow to the right of
|
||||
their name. A child can be made the Active Person by selecting them
|
||||
from the Children list and then clicking the arrow button to the right
|
||||
of the Children.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>IMPROVING GRAMPS</b>: Users are entitled to request enhancements to GRAMPS.
|
||||
<b>Who Was Born When</b>: The 'Compare individual events' tool allows you to
|
||||
compare data of all (or some of) the individuals in your database. This is
|
||||
useful, say, if you wish to list the birth dates of everyone in your
|
||||
database.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS comes with a rich set of tools. These allows you to undertake
|
||||
operations such as checking database for errors and consistency, as well as
|
||||
research and analysis tools such as event comparison, finding duplicate
|
||||
people, interactive descendant browser, and others.
|
||||
All tools can be accessed through the <b>Tools</b> menu.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Calculating Relationships</b>: This tool, under <b>Tools >
|
||||
Utilities > Relationship calculator</b> allows you to check if someone
|
||||
else in the family is related (by blood, not marriage) to you. Precise
|
||||
relationships as well as the common ancestors are reported.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>SoundEx can help with family research</b>:
|
||||
SoundEx solves a long standing problem in genealogy---how to handle
|
||||
spelling variations. The SoundEx utility takes a surname and generates
|
||||
a simplified form that is equivalent for similar sounding names.
|
||||
Knowing the SoundEx Code for a surname is very
|
||||
helpful for researching Census Data files (microfiche) at a library
|
||||
or other research facility. To get the SoundEx codes for surnames in
|
||||
your database, go to <b>Tools > Utilities > Generate SoundEx codes</b>.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Setting Your Preferences</b>: Not happy with some default behavior of GRAMPS?
|
||||
<b>Edit > Preferences</b> lets you to modify a
|
||||
number of settings, allowing you to tailor GRAMPS to your needs.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>GRAMPS Reports</b>: GRAMPS offers a wide variety of reports.
|
||||
The Text Reports are particularly useful if you want to send
|
||||
the results of your family tree to members of the family via email.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Starting a New Family Tree</b>: A good way to start a new family tree is
|
||||
to enter all the members of the family into the database (use <b>Edit
|
||||
> Add</b> or click on the Add button under the People menu). Then go to
|
||||
the Family View and create relationships between people.
|
||||
Then go about tracing the relationships among them all under the Family menu.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Unsure what a button does? Simply hold the mouse over a button and a tooltip
|
||||
will appear.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Unsure of a Date?</b> If you're unsure about the date an event occurred
|
||||
(for example birth or death), GRAMPS allows you to enter a wide
|
||||
range of date formats based on a guess or an estimate. For instance,
|
||||
"about 1908" is a valid entry for a birth date in GRAMPS.
|
||||
See section 3.7.2.2 of the GRAMPS manual for a complete description of
|
||||
date entry options.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Duplicate Entries</b>: <b>Tools > Database Processing > Find
|
||||
possible duplicate</b> people allows you to located (and merge) entries
|
||||
of the same person entered more than once in the database.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The 'merge' function allows you to combine separately listed people into
|
||||
one. This is very useful for combining two databases with overlapping
|
||||
people, or combining erroneously entered differing names for one individual.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
To easily merge two people, select them both (a second person can be selected
|
||||
by holding the Control key while clicking) and clicking on <b>Edit > Fast
|
||||
Merge</b>.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS maintains a list of previous Active People. You can move forward and
|
||||
backward through the list using <b>Go > Forward</b> and <b>Go >
|
||||
Back</b>.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Tired of having to take your hand off the keyboard to use the mouse?
|
||||
Many functions in GRAMPS have keyboard shortcuts. If one exists for a
|
||||
function it is displayed on the right side of the menu.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Don't forget to read the GRAMPS manual, <b>Help > User Manual</b>.
|
||||
The developers have worked hard to make most operations intuitive
|
||||
but the manual is full of information that will make your time spent
|
||||
on genealogy more productive.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Adding Children</b>: To add children in GRAMPS make either of the parents
|
||||
the Active Person then switch to the Family View.
|
||||
If the child is already in the database, click on the third button down to the
|
||||
right of the Children list.
|
||||
If the person is not already in the database, click on the second button down
|
||||
to the right of the Children list. After the child's information is entered
|
||||
they will automatically be listed as a child of the Active Person.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Editing The Relationship of a Child</b>: Not all children are the related by
|
||||
birth to their parents. You can edit the relationship of a
|
||||
child to each parent by selecting the child, right-clicking, and choosing
|
||||
"Edit the child parent relationship".
|
||||
Relationships can be any of Birth, Adopted, Stepchild, Sponsored, Foster, or
|
||||
Unknown.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Show All Checkbutton</b>: When adding a spouse or child, the
|
||||
list of people shown is filtered to display only people who could
|
||||
realistically fit the role (based on dates in the database). In case
|
||||
GRAMPS is wrong in making this choice, you can override that
|
||||
filter by checking the "Show All" checkbutton.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>GRAMPS Manual</b>: The GRAMPS manual is quite elaborate and well written.
|
||||
It includes details on keybindings and includes some useful tips that will
|
||||
help you in your genealogy work.
|
||||
Check it out.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Improving GRAMPS</b>: Users are encouraged to request enhancements to
|
||||
GRAMPS.
|
||||
Requesting an enhancement can be done either through the gramps-users or
|
||||
gramps-devel mailing lists, or by creating a Request for Enhancement (RFE) at
|
||||
http://sourceforge.net/tracker/?group_id=25770&atid=385140
|
||||
The last is preferred.
|
||||
http://sourceforge.net/tracker/?group_id=25770&atid=385140
|
||||
Filing an RFE is preferred.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>WHO WAS BORN WHEN</b>: The 'Compare individual events' tool allows you to
|
||||
compare data of all (or some of) the individuals in your database. This is
|
||||
useful, say, if you wish to list the birth-dates of everyone in your
|
||||
database. For best results, your data needs to be complete.
|
||||
<b>GRAMPS Mailing Lists</b>: Want answers to your queries about GRAMPS?
|
||||
Check out the gramps-users list.
|
||||
Many people are on the list, so you're likely to get an answer quickly.
|
||||
If you have questions related to the development of GRAMPS,
|
||||
try gramps-devel. Information on both mailing lists can be found at
|
||||
lists.sf.net.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>WHO'S THE OLDEST OF US ALL?</b> You can find out a lot of statistical
|
||||
information about your entire family, using the Tools > Utilities > Verify
|
||||
the database facility. For instance, what was the maximum age of any
|
||||
individual in the family? Or the largest husband-wife age difference. Or the
|
||||
minimum age at which anyone in your family ever married. Or even the minimum
|
||||
age at which a woman bore a child.
|
||||
<b>Contributing to GRAMPS</b>:
|
||||
Want to help with GRAMPS but can't program? Not a problem. A project
|
||||
as large as GRAMPS requires people with a wide variety of skills.
|
||||
Contributions can vary from writing documentation to testing development
|
||||
versions to helping with the web site.
|
||||
Start by subscribing to the gramps developers mailing list, gramps-devel
|
||||
and introducing yourself.
|
||||
Subscription information can be found at lists.sf.net.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>CALCULATING RELATIONSHIPS</b>: This allows you to check if someone else in the
|
||||
entire family is related (by blood, not marriage) to you. Precise
|
||||
relationships as well as the common ancestors are reported. See Tools >
|
||||
Utilities > Relationship calculator.
|
||||
GRAMPS is the Genealogical Research and Analysis Management Program System.
|
||||
It is a full-featured genealogy program letting you store, edit, and
|
||||
research genealogical data. Gramps database back end is so robust that
|
||||
some users are managing genealogies containing hundreds of thousands of
|
||||
people.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>USEFUL CODES FOR SURNAMES</b>: SoundEx is a utility that will allow you to type
|
||||
in a surname, then give you the SoundEx Code for that name. Knowing the
|
||||
SoundEx Code for a surname is very helpful for researching Census Data files
|
||||
(microfiche) at a library or other research facility. To get your Soundex
|
||||
codes for surnames in your database, go to Tools > Utilities > Generate
|
||||
SoundEx codes.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>SETTING YOUR PREFERENCES</b>: Edit > Preferences will allow you to choose a
|
||||
number of settings, determining how your GRAMPS program should work.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>GRAMPS REPORTS</b>: GRAMPS offers a wide number of reports that can be
|
||||
generated. The Text Reports are particularly useful if you want to send out
|
||||
the results of your family tree to members of the family, via e-mail.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>STARTING A NEW FAMILY TREE</b>: The best way to start a new family tree is
|
||||
probably to add-in all the members of the family into the database (use Edit
|
||||
> Add or click on the Add button under the People menu). Then go about
|
||||
tracing the relationships among them all under the Family menu.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>TRACING RELATIONSHIPS</b>: People from an existing database can easily be all
|
||||
linked into the family. Go to Family, and choose the second button to the
|
||||
right of the Relationship window. (The first button to the right of the
|
||||
relationship window adds a new person to the database, and adds to a new
|
||||
relationship.)
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>ASKING RELATIONS FOR DETAILS</b>: To get inputs for building your family tree,
|
||||
ask key members of your extended family (including other families connected
|
||||
to yours via marriage) to send in information. Most important is the full
|
||||
name, date and places of birth and death (if expired), relationship within
|
||||
the family.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>UNSURE ABOUT BIRTH-DATES?</b> If you're unsure about the birth-dates about
|
||||
individuals in your family, GRAMPS allows you to enter a wide range, based on
|
||||
a guess or an estimate. For instance, "about 1908" is also a valid entry. for a
|
||||
birth date in GRAMPS. Subsequently, the precise dates could be included once
|
||||
it is available.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>DUPLICATE ENTRIES</b>: Tools > Database Processing > Find possible duplicate
|
||||
people allows you to located (and merge) entries of the same person entered
|
||||
more than once in the database.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>ADDING A SIBLING</b>: To add siblings in Gramps, make either of your parents
|
||||
an active person (i.e. navigate to either of your parents). Then switch to the
|
||||
Family View and add a new child by clicking the button second from the top on
|
||||
the right of the Children list (the "New" button). Enter the data for the
|
||||
new person and click OK.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>EDITING THE RELATIONSHIP OF A CHILD</b>: You can edit the relationship of the
|
||||
child to each parent by selecting the child, right-clicking, and choosing
|
||||
"Edit the child-parent relationship" item. If this is not your child but
|
||||
your wife's child, you would select "Birth" in relationship to her and
|
||||
"Stepchild" in relationship to you.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>ADDING A CHILD</b>: If the child is already in the database, then you don't need
|
||||
to add him to the database. Just add the child to the family, which can be
|
||||
done by pressing the third button from the top (the "Select" button). Then,
|
||||
select the person from the list.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>SHOW-ALL CHECKBUTTON</b>: The list of people you can add into a family is
|
||||
filtered to display only people who could possibly be the child (based on he
|
||||
birth-dates). In case GRAMPS is wrong in making this choice, you can always
|
||||
over-ride that filtering by checking "Show all" checkbutton.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>KEYBINDINGS</b>: GRAMPS's manual is quite elaborate and well written; it also is
|
||||
detailed about keybindings (in a separate appendix) and other matters. Check
|
||||
it out.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>GRAMPS-USERS</b>: Want to answer your queries about GRAMPS? Check out the
|
||||
gramps-users list. Many users are on the list, so you're likely to get an
|
||||
answer faster. If you need to ask questions -- use either gramps-devel or
|
||||
gramps-users at lists.sf.net, as appropriate for your questions.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>TIPS OF THE DAY</b>: GRAMPS's has the option of popping up a
|
||||
window with the tip of the day about the use of GRAMPS. The tip is chosen
|
||||
randomly from the pool of tips. To add your own tip, send it in to
|
||||
gramps-users@lists.sf.net
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS (Genealogical Research and Analysis Management Programming System)
|
||||
offers you a well-designed user interface to make entering data easy, and
|
||||
browser-like controls to allow you to navigate your family tree with ease.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>DIFFERENT VIEWS</b>: There are six different views for navigating your family:
|
||||
<b>Different Views</b>: There are six different views for navigating your
|
||||
family:
|
||||
People, Family, Pedigree, Sources, Places, Media. Each helps you to achieve
|
||||
one or more specific tasks.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>CHANGING A CHILD/PARENT RELATIONSHIP</b>: In the Family view, a right-click on
|
||||
the Children allows you to edit the child/parent relationship. This is used
|
||||
to mark out children as adopted or step-children.
|
||||
<b>Bookmarking Individuals</b>:
|
||||
The Bookmark menu at the top of the window is a convenient place to store
|
||||
the names of frequently used individuals. Clicking on a bookmarked
|
||||
individual will make that person the Active Person.
|
||||
To create a bookmark for a person, make them the Active Person, right click on
|
||||
their name and click on 'add bookmark'.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>BOOKMARKING INDIVIDUALS</b>: To 'bookmark' individuals in your database,
|
||||
navigate to them using the Family view, then right-click and 'add bookmark'.
|
||||
You can visit these bookmarks much like in your browser, simply via Bookmark
|
||||
> Go to bookmark.
|
||||
<b>Incorrect Dates</b>: Everyone occasionally enters dates with a nonvalid
|
||||
format.
|
||||
Incorrect date formats will show up with the red button next to the
|
||||
date. Green means okay, and amber signifies acceptable.
|
||||
The Date Selection dialog can be invoked by clicking on the colored button.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>DATES</b>: Incorrect date formats will show up with the red button alongside the
|
||||
date. Green means okay, and amber signifies acceptable. Click on the colored
|
||||
button to invoke Date Selection dialog, if you like.
|
||||
<b>Listing Events</b>: Events in the life of any individual may be
|
||||
added to the database via the <b>Person > Edit Person >
|
||||
Events</b> option. This space can be used to include a wide range
|
||||
of options ranging from adoptions, to baptisms (and other religious
|
||||
ceremonies), burials, causes of death, Census listings, degrees
|
||||
earned, elections, emigration, military service, nobility titles,
|
||||
occupations, ordination, property, religion, retirement, wills, etc.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>LISTING EVENTS</b>: Events in the life of any individual in the database may be
|
||||
added via the Person > Edit Person > Events option. This space can be used
|
||||
to include a wide range of options ranging from adoptions, to baptisms (and
|
||||
other religious ceremonies), burials, causes of death, Census listings,
|
||||
degrees earned in education, divorce filings, elections, emigration,
|
||||
military service, nobility titles, number of marriages, occupations,
|
||||
ordination, property, religion, retirement, wills, etc.
|
||||
</tip>
|
||||
|
||||
<!--
|
||||
<tip>
|
||||
GRAMPS' People view gives you a list of all individuals in the database. You
|
||||
can sort the listing by differing priorities simply by clicking on headings
|
||||
like name, gender, bate date or death date.
|
||||
</tip>
|
||||
-->
|
||||
|
||||
<tip>
|
||||
<b>CHANGING PREFERRED NAME</b>: If a person has several names, it is very easy
|
||||
to manage these names in Gramps. Find the person in the Family view,
|
||||
double-click on the record, and open Names tab. You can add different
|
||||
types of names here, like Married Name, Birth Name, etc. Selecting a
|
||||
preferred name is just a matter of right-clicking on the name and
|
||||
<b>Changing The Preferred Name</b>:
|
||||
It is easy to manage people with several names in GRAMPS.
|
||||
Make the person the Active Person,
|
||||
doubleclick on the record, and select the Names tab. Different
|
||||
types of names can be added. For example, Married Name, Birth Name, etc.
|
||||
Selecting a preferred name is just a matter of right-clicking on the name and
|
||||
choosing the only item in the menu.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The Pedigree view display the family in the traditional pedigree view. Hold
|
||||
the mouse over individuals to see more information about them and to move to
|
||||
more distant parts of the tree.
|
||||
The Pedigree View displays a traditional pedigree chart.
|
||||
Hold the mouse over an individual to see more information about them or
|
||||
right click on an individual to view a menu to quickly access their spouses,
|
||||
siblings, children, or parents.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The Sources view shows all the family's referenced sources in a single view.
|
||||
<!--
|
||||
The Sources View shows a list of all sources in a single window.
|
||||
Double-click on each to edit, add notes, and to see which individuals
|
||||
reference the source.-->
|
||||
reference the source.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The Places view shows all places referred to in the database.
|
||||
<!--
|
||||
It also allows
|
||||
you to sort the list by half-a-dozen different criteria, such as City,
|
||||
The Places View shows a list of all places in the database.
|
||||
The list can be sorted by a number of different criteria, such as City,
|
||||
County or State.
|
||||
-->
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The Media list includes all forms of media referenced by the database. These
|
||||
could be graphic images, videos, sound clips, spreadsheets, documents, and
|
||||
The Media View shows a list of all media entered in the database. These
|
||||
can be graphic images, videos, sound clips, spreadsheets, documents, and
|
||||
more.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS allows you to bookmark key individuals in your family tree, for quick
|
||||
access. The number able to be marked is unlimited.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS comes with a rich set of tools. This allows you to undertake
|
||||
operations such as checking database for errors and consistency, as well as
|
||||
the research and analysis tools such as event comparison, finding duplicate
|
||||
people, interactive descendant browser, and others.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The 'merge' function allows you to combine separately-listed people into
|
||||
one. This is very useful for combining two databases with overlapping
|
||||
people, or combining erroneously-entered differing names for one individual.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The Soundex generator allows you to generate the standard codes commonly
|
||||
used in genealogy, to compare similar sounding names even though spelled
|
||||
differently.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Custom filters allow you to dig out family data and interesting facts, in a
|
||||
number of interesting selections. Such custom filters can be used in addition
|
||||
to the numerous preset filters.
|
||||
Filters allow you to limit the people seen in the People View. In addition
|
||||
to the many preset filters, Custom Filters
|
||||
can be created that allow you to create filters limited only by your
|
||||
imagination.
|
||||
Custom filters can be created from <b>Tools > Utilities > Custom
|
||||
Filter Editor</b>.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
@ -347,168 +349,23 @@ programs.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
You can convert your data into a GRAMPS 'package', which is a compressed
|
||||
file containing your family tree data and any other files used. This is
|
||||
useful for backup or sharing with other GRAMPS users.
|
||||
You can convert your data into a GRAMPS package, which is a
|
||||
compressed file containing your family tree data and includes all
|
||||
other files used by the database, such as images. This file is
|
||||
completely portable so is useful for backups or sharing with other
|
||||
GRAMPS users. This format has advantages over GEDCOM in that no
|
||||
information is ever lost in exporting and importing.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Make your data portable -- you can export your family tree data and media
|
||||
Make your data portable --- your family tree data and media can be exported
|
||||
directly to the GNOME file manager (Nautilus), for burning onto a CD.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Web Family Tree (WFT) allows you to display your family tree online with
|
||||
only a single file, instead of many html files. GRAMPS allows you to export
|
||||
data to the WFT format.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS currently runs on Linux, BSD, and Solaris.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
There are several ways to report a bug, including the GRAMPS Bugs mailing
|
||||
list. The best way to report a bug is to use the GRAMPS Bug Tracker at
|
||||
Sourceforge. Using the bug tracker will make sure that your issue will be
|
||||
handled, and doesn't miss the developers' attention.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS is taken forward by a set of useful mailing-lists, which any serious
|
||||
user needs to consider joining. These lists include gramps-announce
|
||||
(announcements relating to the software project), gramps-bugs (to track
|
||||
bugs), gramps-devel (for developers), and gramps-users (for all users,
|
||||
including beginners).
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Tonnes of GRAMPS-related information at http://gramps.sourceforge.net/
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS stands for Genealogical Research and Analysis Management Programming
|
||||
System. It allows you to store, edit, and research genealogical data, with
|
||||
similar functionality to other genealogical programs.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS offers some unique features, including the ability to input any bits
|
||||
and pieces of information directly into GRAMPS and rearrange/manipulate any
|
||||
data events in the entire data base (in any order or sequence) to assist the
|
||||
user in doing research, analysis and correlation with the potential of
|
||||
filling relationship gaps.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Respect the privacy of people in your family tree. Genealogy shouldn't
|
||||
reveal anyone's current health condition, their financial information, and
|
||||
other information they would prefer be kept confidential.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Be accurate when recording genealogical information. Don't make assumptions
|
||||
while recording primary information; write it exactly as you see it. Use
|
||||
bracketed comments to indicate your additions, deletions or comments. Use of
|
||||
the Latin 'sic' is recommended to confirm the accurate transcription of what
|
||||
seems to be an error.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
You can link any 'media' (including non-text information) and other
|
||||
file-types to your GRAMPS family tree.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Privacy options allow the restriction of any information marked or
|
||||
information about living individuals. Data marked with this option can be
|
||||
excluded from reports and data exports.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS allows you to generate brief or detailed reports for the ancestors or
|
||||
descendents of any individual in your family tree, depending on your
|
||||
requirements.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Multiple styles of reports are currently available by default. Users can
|
||||
also create their own custom styles.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Eight output formats are supported by GRAMPS -- PDF, AbiWord, KWord,
|
||||
OpenOffice Writer, HTML, Rich Text Format (RTF), Latex, and plain text.
|
||||
These formats generate data which can be read on all computers, making
|
||||
it easy for anyone to access it.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Custom reports can be created by advanced users under the "plugin" system
|
||||
which allows the sharing of custom report styles between users.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Book report allows the user to collect a variety of reports in a single
|
||||
document, which in turn is easier to distribute, especially in a paper
|
||||
format.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Want improvements in GRAMPS? You can do it yourself too. Since GRAMPS is
|
||||
free/libre and open source software, nobody prevents you from taking all of
|
||||
the code and continuing its development in whatever direction you see fit.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Interested in getting notified when a GRAMPS release is made? Sign up on the
|
||||
gramps-announce mailing list ultra-low bandwidth, at
|
||||
http://lists.sourceforge.net/lists/listinfo/gramps-announce
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Have questions about GRAMPS, or are you looking to discuss GRAMPS
|
||||
related items? The best place is the gramps-users mailing list
|
||||
http://lists.sourceforge.net/lists/listinfo/gramps-users You need to
|
||||
first sign-up to be able to post.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Need enhancements for GRAMPS? Requesting an enhancement can be done either
|
||||
through the gramps-users or gramps-devel mailing lists, or by creating a
|
||||
Request for Enhancement (RFE)
|
||||
http://sourceforge.net/tracker/?group_id=25770&atid=385140
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Good genealogy tip: Information collated about your family is only as good
|
||||
as the source it came from. Take time and trouble to write down all the
|
||||
details of where the information came from.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Go from what you know to what you do not. Always record everything that is
|
||||
known before making conjecture. Often the facts at hand suggest plenty of
|
||||
direction for more research. Don't waste time looking through thousands of
|
||||
records hoping for a trail when you have other unexplored options.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Genealogy isn't only about dates and names. It is about people. Be
|
||||
descriptive. Include the <b>why</b> of how things happened, and how descendents
|
||||
might have been shaped by the events they went through. Narratives go a long
|
||||
way in making your family interesting to others too.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Join the gramps-users mailing list at
|
||||
http://lists.sourceforge.net/lists/listinfo/gramps-users
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
You can create graphical ancestor or descendent charts in several formats --
|
||||
box charts, a fan chart, multiple formats (OpenOffice Draw, PDF, PostScript,
|
||||
SVG), and custom charts.
|
||||
GRAMPS can export data to the Web Family Tree (WFT) format. This format
|
||||
allows a family tree to be displayed online using a single file, instead
|
||||
of many html files.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
@ -518,15 +375,94 @@ ready for upload to the World Wide Web.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Multiple calendars and date ranges are supported by GRAMPS.
|
||||
The best way to report a bug in GRAMPS is to use the GRAMPS Bug Tracker
|
||||
at Sourceforge, http://sourceforge.net/tracker/?group_id=25770&atid=385137
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Support is mature for multiple languages and cultures.
|
||||
The GRAMPS homepage is at http://gramps-project.org/
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS offers translations for 15 languages.
|
||||
GRAMPS has some unique features, including the ability to input any
|
||||
piece of information directly into GRAMPS.
|
||||
All data in the data base can be rearranged/manipulated to assist the
|
||||
user in doing research, analysis and correlation with the potential of
|
||||
filling relationship gaps.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS helps you to keep personal information secure by allowing you to
|
||||
mark information as private. Data marked as private can be excluded from
|
||||
reports and data exports.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Be accurate when recording genealogical information. Don't make assumptions
|
||||
while recording primary information; write it exactly as you see it. Use
|
||||
bracketed comments to indicate your additions, deletions or comments. Use of
|
||||
the Latin 'sic' is recommended to confirm the accurate transcription of what
|
||||
appears to be an error in a source.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
You can link any electronic media (including non-text information) and
|
||||
other file types to your GRAMPS family tree.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS allows you to generate a number of reports (both text and graphical)
|
||||
based on your genealogical information. There is great flexibility in
|
||||
selecting what people are included in the reports as well as the output
|
||||
format (html, pdf, OpenOffice, RTF, AbiWord, KWord, LaTeX and plain text).
|
||||
Experiment with the reports under the <b>Reports</b> menu to get an idea
|
||||
of how powerful GRAMPS is.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Custom reports can be created by advanced users under the "plugin" system.
|
||||
More information on custom reports can be found at
|
||||
http://developers.gramps-project.org
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
The Book report, <b>Reports > Books > Book Report</b>, allows users
|
||||
to collect a variety of reports into a single document. This single report
|
||||
is easier to distribute than multiple reports, especially when printed.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Interested in getting notified when a new version of GRAMPS is released?
|
||||
Join the gramps-announce mailing list at
|
||||
http://lists.sourceforge.net/lists/listinfo/gramps-announce
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
<b>Good genealogy tip</b>: Information collected about your family is only as
|
||||
good as the source it came from.
|
||||
Take time and trouble to record all the
|
||||
details of where the information came from. Whenever possible get a copy of
|
||||
original documents.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Go from what you know to what you do not. Always record everything that is
|
||||
known before making conjecture. Often the facts at hand suggest plenty of
|
||||
direction for more research. Don't waste time looking through thousands of
|
||||
records hoping for a trail when you have other unexplored leads.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Genealogy isn't only about dates and names. It is about people. Be
|
||||
descriptive. Include the <b>why</b> of how things happened, and how descendants
|
||||
might have been shaped by the events they went through. Narratives go a long
|
||||
way in making your family history come alive.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS has been translated to 15 languages. If GRAMPS supports your
|
||||
language and it is not being displayed, set the default language on
|
||||
your machine and restart GRAMPS.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
@ -536,7 +472,7 @@ email gramps-devel@lists.sf.net
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Relationship calculators in GRAMPS are available in four languages.
|
||||
Relationship calculators in GRAMPS are available in ten languages.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
@ -545,41 +481,26 @@ properly displayed.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
You can choose anyone as your 'home person' in GRAMPS. Use Edit -> Set Home
|
||||
Person. The home person is the person who is selected when the database is
|
||||
opened, when the home-button is pressed in your browser-like GRAMPS
|
||||
interface, and when Home is selected from the context menu anywhere.
|
||||
Anyone can be chosen as the 'home person' in GRAMPS. Use <b>Edit -> Set Home
|
||||
Person</b>. The home person is the person who is selected when the database is
|
||||
opened or when the home button is pressed.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
You can specify several names for a single person -- such as, birth name,
|
||||
marriage name, etc.
|
||||
Multiple names can be specified for individuals. Examples are birth name,
|
||||
marriage name or aliases.
|
||||
</tip>
|
||||
|
||||
<tip>An alternate name can be selected as a person's preferred name by
|
||||
selecting the desired name in the person's name list, bringing up the context
|
||||
menu by clicking the right mouse button, and selecting from the menu.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
To switch between the different names of a single individual (birth name,
|
||||
marriage name, etc) right-click on the name wanted in the list of
|
||||
alternative names (under the Names tag in the EditPerson dialog) and select
|
||||
an item from the context menu. This name will become the primary name, and
|
||||
will be used in all display-related places.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Many current GRAMPS users contribute reports, suggestions, and feedback to
|
||||
the developers through various public mailing lists. The program is only a
|
||||
few years old and already has wide capabilities and features. Would you like
|
||||
to help too?
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
Numerous GRAMPS releases are made each year.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS is written in a computer language called Python using GTK and GNOME
|
||||
libraries. While only well supported in certain Unix and Linux environments,
|
||||
these are multi-platform development libraries, meaning that GRAMPS can be
|
||||
ported to any platform the required libraries are ported to.
|
||||
GRAMPS is written in a computer language called Python using the GTK and GNOME
|
||||
libraries for the graphical interface.
|
||||
GRAMPS is supported on any computer system where these programs have been
|
||||
ported.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
@ -590,40 +511,11 @@ freely available under its license.
|
||||
|
||||
<tip>
|
||||
GRAMPS is freely distributable under the General Public License, see
|
||||
http://www.gnu.org/licenses/licenses.html#GPL !
|
||||
http://www.gnu.org/licenses/licenses.html#GPL
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS does not
|
||||
support TempleReady GEDCOM extensions, and offers limited drag-and-drop
|
||||
support. Currently, there is no support for drag and drop between databases.
|
||||
Graph reports are also limited in functionality.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS is the Genealogical Research and Analysis Management Program System.
|
||||
In other words, it a personal genealogy program letting you store, edit, and
|
||||
research genealogical data using the powers of your computer.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS can be downloaded from Sourceforge http://sf.net/projects/gramps at
|
||||
no charge. GRAMPS is an Free/Libre and Open Source Software project covered
|
||||
by the GNU General Public License http://www.gnu.org/copyleft/gpl.html .
|
||||
You have full access to the source code and are allowed to distribute the
|
||||
program and source code freely.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
A port of GRAMPS to Mac OS X exists from the Fink project
|
||||
http://fink.sourceforge.net/pdb/package.php/gramps . It is not unusual for
|
||||
this version to lag behind the Linux version. The port is not supported by
|
||||
the GRAMPS project (since few if any of us have Macs), but we try to help
|
||||
out where we can.
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS works with KDE too, as long as the required GNOME libraries are
|
||||
GRAMPS works even when using KDE, as long as the required GNOME libraries are
|
||||
installed.
|
||||
</tip>
|
||||
|
||||
@ -634,16 +526,8 @@ running the GNOME desktop.
|
||||
|
||||
<tip>
|
||||
GRAMPS makes every effort to maintain compatibility with GEDCOM, the general
|
||||
standard of recording genealogical information. We have import and export
|
||||
filters that enable GRAMPS to read and write GEDCOM files. Please do inform
|
||||
us about any GEDCOM flavor not supported by GRAMPS, and we will do our best
|
||||
to support it!
|
||||
</tip>
|
||||
|
||||
<tip>
|
||||
GRAMPS can produce many different charts and reports. Moreover, the plugin
|
||||
architecture enables a user (you) to create his own plugins which could be
|
||||
new reports, charts, or research tools.
|
||||
standard of recording genealogical information. Filters exist that make
|
||||
importing and exporting GEDCOM files trivial.
|
||||
</tip>
|
||||
|
||||
</tips>
|
||||
|
232
src/dates/Date_de.py
Normal file
232
src/dates/Date_de.py
Normal file
@ -0,0 +1,232 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2005 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
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
German-specific classes for parsing and displaying dates.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import re
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import Date
|
||||
from DateParser import DateParser
|
||||
from DateDisplay import DateDisplay
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# French parser
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateParserDE(DateParser):
|
||||
|
||||
month_to_int = DateParser.month_to_int
|
||||
# Always add german and austrian name variants no matter what the current locale is
|
||||
month_to_int[u"januar"] = 1
|
||||
month_to_int[u"jan"] = 1
|
||||
month_to_int[u"jänner"] = 1
|
||||
month_to_int[u"jän"] = 1
|
||||
# Add other common latin, local and historical variants
|
||||
month_to_int[u"januaris"] = 1
|
||||
month_to_int[u"jenner"] = 1
|
||||
month_to_int[u"feber"] = 2
|
||||
month_to_int[u"februaris"] = 2
|
||||
month_to_int[u"merz"] = 2
|
||||
month_to_int[u"aprilis"] = 4
|
||||
month_to_int[u"maius"] = 5
|
||||
month_to_int[u"junius"] = 6
|
||||
month_to_int[u"julius"] = 7
|
||||
month_to_int[u"augst"] = 8
|
||||
month_to_int[u"7ber"] = 9
|
||||
month_to_int[u"7bris"] = 9
|
||||
month_to_int[u"8ber"] = 10
|
||||
month_to_int[u"8bris"] = 10
|
||||
month_to_int[u"9ber"] = 11
|
||||
month_to_int[u"9bris"] = 11
|
||||
month_to_int[u"10ber"] = 12
|
||||
month_to_int[u"10bris"] = 12
|
||||
month_to_int[u"xber"] = 12
|
||||
month_to_int[u"xbris"] = 12
|
||||
|
||||
modifier_to_int = {
|
||||
u'vor' : Date.MOD_BEFORE,
|
||||
u'nach' : Date.MOD_AFTER,
|
||||
u'gegen' : Date.MOD_ABOUT,
|
||||
u'um' : Date.MOD_ABOUT,
|
||||
u'etwa' : Date.MOD_ABOUT,
|
||||
u'circa' : Date.MOD_ABOUT,
|
||||
u'ca.' : Date.MOD_ABOUT,
|
||||
}
|
||||
|
||||
calendar_to_int = {
|
||||
u'Gregorianisch' : Date.CAL_GREGORIAN,
|
||||
u'Greg.' : Date.CAL_GREGORIAN,
|
||||
u'Julianisch' : Date.CAL_JULIAN,
|
||||
u'Jul.' : Date.CAL_JULIAN,
|
||||
u'Hebräisch' : Date.CAL_HEBREW,
|
||||
u'Hebr.' : Date.CAL_HEBREW,
|
||||
u'Islamisch' : Date.CAL_ISLAMIC,
|
||||
u'Isl.' : Date.CAL_ISLAMIC,
|
||||
u'Französisch Republikanisch': Date.CAL_FRENCH,
|
||||
u'Franz.' : Date.CAL_FRENCH,
|
||||
u'Persisch' : Date.CAL_PERSIAN,
|
||||
}
|
||||
|
||||
quality_to_int = {
|
||||
u'geschätzt' : Date.QUAL_ESTIMATED,
|
||||
u'gesch.' : Date.QUAL_ESTIMATED,
|
||||
u'errechnet' : Date.QUAL_CALCULATED,
|
||||
u'berechnet' : Date.QUAL_CALCULATED,
|
||||
u'ber.' : Date.QUAL_CALCULATED,
|
||||
}
|
||||
|
||||
bce = DateParser.bce + ["vor (unserer|der) Zeit(rechnung)?", "v\. (u|d)\. Z\.", "vor Christus", "vor Christi Geburt", "v\. Chr\."]
|
||||
|
||||
def init_strings(self):
|
||||
DateParser.init_strings(self)
|
||||
self._span = re.compile("(von|vom)\s+(.+)\s+(bis)\s+(.+)",re.IGNORECASE)
|
||||
self._range = re.compile("(zwischen)\s+(.+)\s+(und)\s+(.+)", re.IGNORECASE)
|
||||
self._text2 = re.compile('(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % self._mon_str,
|
||||
re.IGNORECASE)
|
||||
self._jtext2= re.compile('(\d+)?.?\s+?%s\s*((\d+)(/\d+)?)?' % self._jmon_str,
|
||||
re.IGNORECASE)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# French display
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateDisplayDE(DateDisplay):
|
||||
|
||||
calendar = (
|
||||
"", u" (Julianisch)", u" (Hebräisch)",
|
||||
u" (Französisch Republikanisch)", u" (Persisch)", u" (Islamisch)"
|
||||
)
|
||||
|
||||
_mod_str = ("",u"vor ",u"nach ",u"circa ","","","")
|
||||
|
||||
_qual_str = ("",u"geschätzt ",u"errechnet ")
|
||||
|
||||
_bce_str = "%s v. u. Z."
|
||||
|
||||
formats = (
|
||||
"JJJJ-MM-DD (ISO)", "Numerisch", "Monat Tag Jahr",
|
||||
"MONAT Tag Jahr", "Tag. Monat Jahr", "Tag. MONAT Jahr"
|
||||
)
|
||||
|
||||
def _display_gregorian(self,date_val):
|
||||
year = self._slash_year(date_val[2],date_val[3])
|
||||
if self.format == 0:
|
||||
value = self.display_iso(date_val)
|
||||
elif self.format == 1:
|
||||
if date_val[0] == 0 and date_val[1] == 0:
|
||||
value = str(date_val[2])
|
||||
else:
|
||||
value = self._tformat.replace('%m',str(date_val[1]))
|
||||
value = value.replace('%d',str(date_val[0]))
|
||||
value = value.replace('%Y',str(date_val[2]))
|
||||
elif self.format == 2:
|
||||
# Month Day, Year
|
||||
if date_val[0] == 0:
|
||||
if date_val[1] == 0:
|
||||
value = year
|
||||
else:
|
||||
value = "%s %s" % (self._months[date_val[1]],year)
|
||||
else:
|
||||
value = "%s %d, %s" % (self._months[date_val[1]],date_val[0],year)
|
||||
elif self.format == 3:
|
||||
# MON Day, Year
|
||||
if date_val[0] == 0:
|
||||
if date_val[1] == 0:
|
||||
value = year
|
||||
else:
|
||||
value = "%s %s" % (self._MONS[date_val[1]],year)
|
||||
else:
|
||||
value = "%s %d, %s" % (self._MONS[date_val[1]],date_val[0],year)
|
||||
elif self.format == 4:
|
||||
# Day Month Year
|
||||
if date_val[0] == 0:
|
||||
if date_val[1] == 0:
|
||||
value = year
|
||||
else:
|
||||
value = "%s %s" % (self._months[date_val[1]],year)
|
||||
else:
|
||||
value = "%d. %s %s" % (date_val[0],self._months[date_val[1]],year)
|
||||
else:
|
||||
# Day MON Year
|
||||
if date_val[0] == 0:
|
||||
if date_val[1] == 0:
|
||||
value = year
|
||||
else:
|
||||
value = "%s %s" % (self._MONS[date_val[1]],year)
|
||||
else:
|
||||
value = "%d. %s %s" % (date_val[0],self._MONS[date_val[1]],year)
|
||||
return value
|
||||
|
||||
def display(self,date):
|
||||
"""
|
||||
Returns a text string representing the date.
|
||||
"""
|
||||
mod = date.get_modifier()
|
||||
cal = date.get_calendar()
|
||||
qual = date.get_quality()
|
||||
start = date.get_start_date()
|
||||
|
||||
qual_str = self._qual_str[qual]
|
||||
|
||||
if mod == Date.MOD_TEXTONLY:
|
||||
return date.get_text()
|
||||
elif start == Date.EMPTY:
|
||||
return ""
|
||||
elif mod == Date.MOD_SPAN:
|
||||
d1 = self.display_cal[cal](start)
|
||||
d2 = self.display_cal[cal](date.get_stop_date())
|
||||
return "%s%s %s %s %s%s" % (qual_str,u'von',d1,u'bis',d2,self.calendar[cal])
|
||||
elif mod == Date.MOD_RANGE:
|
||||
d1 = self.display_cal[cal](start)
|
||||
d2 = self.display_cal[cal](date.get_stop_date())
|
||||
return "%szwischen %s und %s%s" % (qual_str,d1,d2,self.calendar[cal])
|
||||
else:
|
||||
text = self.display_cal[date.get_calendar()](start)
|
||||
return "%s%s%s%s" % (qual_str,self._mod_str[mod],text,self.calendar[cal])
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Register classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from DateHandler import register_datehandler
|
||||
register_datehandler(('de_DE','german'),DateParserDE, DateDisplayDE)
|
||||
register_datehandler(('de_AT','german (Austria)'),DateParserDE, DateDisplayDE)
|
||||
register_datehandler(('de_CH','german (Switzerland)'),DateParserDE, DateDisplayDE)
|
||||
register_datehandler(('de_LI','german (Lichtenstein)'),DateParserDE, DateDisplayDE)
|
||||
register_datehandler(('de_LU','german (Luxembourg)'),DateParserDE, DateDisplayDE)
|
||||
register_datehandler(('de_BE','german (Belgium)'),DateParserDE, DateDisplayDE)
|
@ -1,175 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2005 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
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Finnish-specific classes for parsing and displaying dates.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import re
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import Date
|
||||
from DateParser import DateParser
|
||||
from DateDisplay import DateDisplay
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Finnish parser
|
||||
#
|
||||
# This handles only dates where days and months are given as numeric, as:
|
||||
# - That's how they are normally used in Finland
|
||||
# - Parsing Finnish is much more complicated than English
|
||||
#-------------------------------------------------------------------------
|
||||
class DateParserFI(DateParser):
|
||||
|
||||
# NOTE: these need to be in lower case because the "key" comparison
|
||||
# is done as lower case. In the display method correct capitalization
|
||||
# can be used.
|
||||
|
||||
modifier_to_int = {
|
||||
# examples:
|
||||
# - ennen 1.1.2005
|
||||
# - 1.1.2005 jälkeen
|
||||
# - noin 1.1.2005
|
||||
u'ennen' : Date.MOD_BEFORE,
|
||||
u'e.' : Date.MOD_BEFORE,
|
||||
u'jälkeen' : Date.MOD_AFTER,
|
||||
u'j.' : Date.MOD_AFTER,
|
||||
u'noin' : Date.MOD_ABOUT,
|
||||
u'n.' : Date.MOD_ABOUT,
|
||||
}
|
||||
|
||||
bce = ["ekr", "ekr\."]
|
||||
|
||||
calendar_to_int = {
|
||||
u'gregoriaaninen' : Date.CAL_GREGORIAN,
|
||||
u'greg.' : Date.CAL_GREGORIAN,
|
||||
u'juliaaninen' : Date.CAL_JULIAN,
|
||||
u'jul.' : Date.CAL_JULIAN,
|
||||
u'heprealainen' : Date.CAL_HEBREW,
|
||||
u'hepr.' : Date.CAL_HEBREW,
|
||||
u'islamilainen' : Date.CAL_ISLAMIC,
|
||||
u'isl.' : Date.CAL_ISLAMIC,
|
||||
u'ranskan vallankumouksen aikainen': Date.CAL_FRENCH,
|
||||
u'ranskan v.' : Date.CAL_FRENCH,
|
||||
u'persialainen' : Date.CAL_PERSIAN,
|
||||
u'pers.' : Date.CAL_PERSIAN,
|
||||
}
|
||||
|
||||
quality_to_int = {
|
||||
u'arviolta' : Date.QUAL_ESTIMATED,
|
||||
u'arv.' : Date.QUAL_ESTIMATED,
|
||||
u'laskettuna' : Date.QUAL_CALCULATED,
|
||||
u'lask.' : Date.QUAL_CALCULATED,
|
||||
}
|
||||
|
||||
def init_strings(self):
|
||||
DateParser.init_strings(self)
|
||||
# date, whitespace
|
||||
self._span = re.compile("(?P<start>.+)\s+-\s+(?P<stop>.+)",
|
||||
re.IGNORECASE)
|
||||
self._range = re.compile("(?P<start>.+)\s+ja\s+(?P<stop>.+)\s+väliltä",
|
||||
re.IGNORECASE)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Finnish display
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateDisplayFI(DateDisplay):
|
||||
|
||||
calendar = ("",
|
||||
u"(Juliaaninen)",
|
||||
u"(Heprealainen)",
|
||||
u"(Ranskan v.)",
|
||||
u"(Persialainen)",
|
||||
u"(Islamilainen)")
|
||||
|
||||
_qual_str = ("", "laskettuna", "arviolta")
|
||||
|
||||
formats = (
|
||||
"VVVV-KK-PP (ISO)",
|
||||
"PP.KK.VVVV"
|
||||
)
|
||||
|
||||
def display(self,date):
|
||||
"""
|
||||
Returns a text string representing the date.
|
||||
"""
|
||||
mod = date.get_modifier()
|
||||
qual = date.get_quality()
|
||||
cal = date.get_calendar()
|
||||
start = date.get_start_date()
|
||||
|
||||
if mod == Date.MOD_TEXTONLY:
|
||||
return date.get_text()
|
||||
if start == Date.EMPTY:
|
||||
return ""
|
||||
|
||||
# select numerical date format
|
||||
self.format = 1
|
||||
|
||||
if mod == Date.MOD_SPAN:
|
||||
d1 = self.display_cal[cal](start)
|
||||
d2 = self.display_cal[cal](date.get_stop_date())
|
||||
text = "%s - %s" % (d1, d2)
|
||||
elif mod == Date.MOD_RANGE:
|
||||
d1 = self.display_cal[cal](start)
|
||||
d2 = self.display_cal[cal](date.get_stop_date())
|
||||
text = "%s ja %s väliltä" % (d1, d2)
|
||||
else:
|
||||
text = self.display_cal[date.get_calendar()](start)
|
||||
if mod == Date.MOD_BEFORE:
|
||||
text = "ennen " + text
|
||||
elif mod == Date.MOD_AFTER:
|
||||
# kludge: should be actually after the date
|
||||
text = "jälkeen " + text
|
||||
elif mod == Date.MOD_ABOUT:
|
||||
text = "noin " + text
|
||||
|
||||
if qual:
|
||||
# prepend quality
|
||||
text = "%s %s" % (self._qual_str[qual], text)
|
||||
if cal:
|
||||
# append calendar type
|
||||
text = "%s %s" % (text, self.calendar[cal])
|
||||
|
||||
return text
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Register classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from DateHandler import register_datehandler
|
||||
register_datehandler(('fi_FI','finnish'), DateParserFI, DateDisplayFI)
|
||||
|
@ -6,10 +6,10 @@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@/dates
|
||||
|
||||
pkgdata_PYTHON = \
|
||||
Date_de.py\
|
||||
Date_ru.py\
|
||||
Date_fr.py\
|
||||
Date_es.py\
|
||||
Date_fi.py
|
||||
Date_es.py
|
||||
|
||||
pkgpyexecdir = @pkgpyexecdir@/dates
|
||||
pkgpythondir = @pkgpythondir@/dates
|
||||
|
@ -9,6 +9,7 @@
|
||||
# Completely butchered to add glade support for the GRAMPS
|
||||
# project by Don Allingham (dallingham@users.sourceforge.net)
|
||||
#
|
||||
# Further bastardized by Alex Roitman to support tips.xml file
|
||||
|
||||
# $Id$
|
||||
|
||||
@ -120,7 +121,6 @@ import getopt
|
||||
import tokenize
|
||||
import operator
|
||||
import re
|
||||
import string
|
||||
import os
|
||||
|
||||
from xml.sax import make_parser,handler,SAXParseException
|
||||
@ -213,6 +213,87 @@ class GladeParser(handler.ContentHandler):
|
||||
def characters(self, data):
|
||||
self.text = self.text + data
|
||||
|
||||
class TipExtractor:
|
||||
|
||||
def __init__(self,msgs):
|
||||
self.strings = msgs
|
||||
|
||||
def add_string(self, str, lineno):
|
||||
if str.strip() == "":
|
||||
return
|
||||
if _ignore.has_key(str):
|
||||
return
|
||||
entry = (self.file, lineno)
|
||||
if self.strings.has_key(str):
|
||||
self.strings[str][entry] = 0
|
||||
else:
|
||||
self.strings[str] = {entry: 0}
|
||||
|
||||
def parse(self,file):
|
||||
self.p = make_parser()
|
||||
self.p.setContentHandler(TipParser(self,file))
|
||||
filename = "file://" + os.path.abspath(file)
|
||||
self.file = file
|
||||
self.p.parse(filename)
|
||||
|
||||
class TipParser(handler.ContentHandler):
|
||||
"""
|
||||
SAX parsing class for the Tips XML file.
|
||||
|
||||
This parser needs to extract strings in *exactly* the same way
|
||||
as the TipOfDay.TipParser does. Otherwise, msgid's won't be correctly
|
||||
matched.
|
||||
"""
|
||||
|
||||
def __init__(self,parent,filename):
|
||||
"""
|
||||
Creates a SheetParser class that populates the passed StyleSheetList
|
||||
class.
|
||||
|
||||
sheetlist - StyleSheetList instance to be loaded from the file.
|
||||
"""
|
||||
handler.ContentHandler.__init__(self)
|
||||
self.parent = parent
|
||||
self.translate = 0
|
||||
self.text = ""
|
||||
self.filename = filename
|
||||
self.lineno = 0
|
||||
|
||||
def startElement(self,tag,attrs):
|
||||
"""
|
||||
Overridden class that handles the start of a XML element
|
||||
"""
|
||||
if tag == "tip":
|
||||
self.text = ""
|
||||
elif tag != "tips":
|
||||
# let all the other tags through, except for the "tips" tag
|
||||
self.text = self.text + "<%s>" % tag
|
||||
|
||||
def endElement(self,tag):
|
||||
"Overridden class that handles the start of a XML element"
|
||||
if tag == "tip":
|
||||
if not _int_re.match(self.text):
|
||||
text = self.escape(self.text)
|
||||
self.parent.add_string(' '.join(text.split()),
|
||||
self.locator.getLineNumber())
|
||||
elif tag != "tips":
|
||||
# let all the other tags through, except for the "tips" tag
|
||||
self.text = self.text + "</%s>" % tag
|
||||
|
||||
def setDocumentLocator(self,locator):
|
||||
self.locator = locator
|
||||
|
||||
def characters(self, data):
|
||||
self.text = self.text + data
|
||||
|
||||
def escape(self,text):
|
||||
"""
|
||||
The tip's text will be interpreted as a markup, so we need to escape
|
||||
some special chars.
|
||||
"""
|
||||
text = text.replace('&','&'); # Must be first
|
||||
return text
|
||||
|
||||
# The normal pot-file header. msgmerge and Emacs's po-mode work better if it's
|
||||
# there.
|
||||
pot_header = _('''\
|
||||
@ -270,7 +351,7 @@ def escape(s):
|
||||
s = list(s)
|
||||
for i in range(len(s)):
|
||||
s[i] = escapes[ord(s[i])]
|
||||
return string.join(s,'')
|
||||
return ''.join(s)
|
||||
|
||||
|
||||
def safe_eval(s):
|
||||
@ -281,7 +362,7 @@ def safe_eval(s):
|
||||
def normalize(s):
|
||||
# This converts the various Python string types into a format that is
|
||||
# appropriate for .po files, namely much closer to C style.
|
||||
lines = string.split(s,'\n')
|
||||
lines = s.split('\n')
|
||||
if len(lines) == 1:
|
||||
s = '"' + escape(s) + '"'
|
||||
else:
|
||||
@ -291,7 +372,7 @@ def normalize(s):
|
||||
for i in range(len(lines)):
|
||||
lines[i] = escape(lines[i])
|
||||
lineterm = '\\n"\n"'
|
||||
s = '""\n"' + string.join(lines,lineterm) + '"'
|
||||
s = '""\n"' + lineterm.join(lines) + '"'
|
||||
return s
|
||||
|
||||
class TokenEater:
|
||||
@ -342,7 +423,7 @@ class TokenEater:
|
||||
# of messages seen. Reset state for the next batch. If there
|
||||
# were no strings inside _(), then just ignore this entry.
|
||||
if self.__data:
|
||||
self.__addentry(string.join(self.__data,''))
|
||||
self.__addentry(''.join(self.__data))
|
||||
self.__state = self.__waiting
|
||||
elif ttype == tokenize.STRING:
|
||||
self.__data.append(safe_eval(tstring))
|
||||
@ -499,13 +580,18 @@ def main():
|
||||
# slurp through all the files
|
||||
eater = TokenEater(options)
|
||||
p = GladeExtractor(eater.get_messages())
|
||||
tp = TipExtractor(eater.get_messages())
|
||||
|
||||
for filename in args:
|
||||
if filename[-5:] == 'glade':
|
||||
print 'Working on %s' % filename
|
||||
p.parse(filename)
|
||||
elif filename[-3:] == 'xml':
|
||||
elif filename[-8:] == 'tips.xml':
|
||||
# Using our own custom Tips parser for tips.xml
|
||||
print 'Working on %s' % filename
|
||||
tp.parse(filename)
|
||||
elif filename[-3:] == 'xml':
|
||||
# THIS IS NOT WORKING -- something has changed in SAX/Expat
|
||||
try:
|
||||
parser = make_parser()
|
||||
pxml = XMLParser(filename,eater.get_messages())
|
||||
|
488
src/gramps.glade
488
src/gramps.glade
@ -7802,37 +7802,6 @@ Other</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="button99">
|
||||
<property name="border_width">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke birth event editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_edit_birth_clicked" object="editPerson"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2262">
|
||||
<property name="visible">True</property>
|
||||
<property name="pixbuf">edit_sm.png</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
<property name="right_attach">5</property>
|
||||
<property name="top_attach">13</property>
|
||||
<property name="bottom_attach">14</property>
|
||||
<property name="x_options"></property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="surname">
|
||||
<property name="visible">True</property>
|
||||
@ -7938,97 +7907,6 @@ Other</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="button126">
|
||||
<property name="border_width">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke death event editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_edit_death_clicked" object="editPerson"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2263">
|
||||
<property name="visible">True</property>
|
||||
<property name="pixbuf">edit_sm.png</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">10</property>
|
||||
<property name="right_attach">11</property>
|
||||
<property name="top_attach">13</property>
|
||||
<property name="bottom_attach">14</property>
|
||||
<property name="x_options">shrink</property>
|
||||
<property name="y_options">shrink</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox98">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="deathDate">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">True</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="death_stat">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke date editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NONE</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_edit_date_death_clicked" last_modification_time="Sat, 18 Sep 2004 02:30:11 GMT"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="death_stat_child">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">8</property>
|
||||
<property name="right_attach">10</property>
|
||||
<property name="top_attach">13</property>
|
||||
<property name="bottom_attach">14</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkFrame" id="frame5">
|
||||
<property name="visible">True</property>
|
||||
@ -8067,10 +7945,6 @@ Other</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">label_item</property>
|
||||
@ -8131,6 +8005,366 @@ Other</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTable" id="table52">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label25">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Date:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_CENTER</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label123">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Place:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_CENTER</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">birth_place</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="birth_place">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">True</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="button99">
|
||||
<property name="border_width">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke birth event editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_edit_birth_clicked" object="editPerson"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2262">
|
||||
<property name="visible">True</property>
|
||||
<property name="pixbuf">edit_sm.png</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="x_options">shrink|fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox97">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="birthDate">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">True</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="birth_stat">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke date editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NONE</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="birth_stat_child">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">5</property>
|
||||
<property name="top_attach">13</property>
|
||||
<property name="bottom_attach">15</property>
|
||||
<property name="x_options">expand|shrink|fill</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTable" id="table53">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">2</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label302">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">D_ate:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_CENTER</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">deathDate</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox98">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="deathDate">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">True</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="death_stat">
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke date editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NONE</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_edit_date_death_clicked" last_modification_time="Sat, 18 Sep 2004 02:30:11 GMT"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="death_stat_child">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="button126">
|
||||
<property name="border_width">1</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="tooltip" translatable="yes">Invoke death event editor</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_edit_death_clicked" object="editPerson"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2263">
|
||||
<property name="visible">True</property>
|
||||
<property name="pixbuf">edit_sm.png</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label303">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Plac_e:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_CENTER</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">death_place</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEntry" id="death_place">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="visibility">True</property>
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">7</property>
|
||||
<property name="right_attach">11</property>
|
||||
<property name="top_attach">13</property>
|
||||
<property name="bottom_attach">15</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
@ -31617,7 +31851,7 @@ Family name Given name
|
||||
<property name="max_length">0</property>
|
||||
<property name="text" translatable="yes"></property>
|
||||
<property name="has_frame">True</property>
|
||||
<property name="invisible_char" translatable="yes">*</property>
|
||||
<property name="invisible_char">*</property>
|
||||
<property name="activates_default">False</property>
|
||||
</widget>
|
||||
<packing>
|
||||
|
@ -961,23 +961,28 @@ class Gramps(GrampsDBCallback.GrampsDBCallback):
|
||||
all.add_rule(GenericFilter.IsMale([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People with unknown gender"))
|
||||
all.add_rule(GenericFilter.HasUnknownGender([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("Disconnected individuals"))
|
||||
all.add_rule(GenericFilter.Disconnected([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("Name contains..."))
|
||||
all.set_name(_("People with names containing..."))
|
||||
all.add_rule(GenericFilter.SearchName([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People who were adopted"))
|
||||
all.set_name(_("Adopted people"))
|
||||
all.add_rule(GenericFilter.HaveAltFamilies([]))
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People who have images"))
|
||||
all.set_name(_("People with images"))
|
||||
all.add_rule(GenericFilter.HavePhotos([]))
|
||||
filter_list.append(all)
|
||||
|
||||
@ -1002,7 +1007,7 @@ class Gramps(GrampsDBCallback.GrampsDBCallback):
|
||||
filter_list.append(all)
|
||||
|
||||
all = GenericFilter.GenericFilter()
|
||||
all.set_name(_("People without a birth date"))
|
||||
all.set_name(_("People without a known birth date"))
|
||||
all.add_rule(GenericFilter.NoBirthdate([]))
|
||||
filter_list.append(all)
|
||||
|
||||
@ -1031,15 +1036,15 @@ class Gramps(GrampsDBCallback.GrampsDBCallback):
|
||||
all.add_rule(GenericFilter.IsWitness([]))
|
||||
filter_list.append(all)
|
||||
|
||||
# all = GenericFilter.ParamFilter()
|
||||
# all.set_name(_("Any textual record contains..."))
|
||||
# all.add_rule(GenericFilter.HasTextMatchingSubstringOf([]))
|
||||
# filter_list.append(all)
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People with records containing..."))
|
||||
all.add_rule(GenericFilter.HasTextMatchingSubstringOf([]))
|
||||
filter_list.append(all)
|
||||
|
||||
# all = GenericFilter.ParamFilter()
|
||||
# all.set_name(_("Any textual record matches regular expression..."))
|
||||
# all.add_rule(GenericFilter.HasTextMatchingRegexpOf([]))
|
||||
# filter_list.append(all)
|
||||
all = GenericFilter.ParamFilter()
|
||||
all.set_name(_("People with records matching regular expression..."))
|
||||
all.add_rule(GenericFilter.HasTextMatchingRegexpOf([]))
|
||||
filter_list.append(all)
|
||||
|
||||
self.filter_model = GenericFilter.FilterStore(filter_list)
|
||||
self.filter_list.set_model(self.filter_model)
|
||||
@ -1248,7 +1253,6 @@ class Gramps(GrampsDBCallback.GrampsDBCallback):
|
||||
self.progress.set_fraction(0)
|
||||
|
||||
def read_file(self,filename,callback=None):
|
||||
self.topWindow.set_resizable(False)
|
||||
mode = "w"
|
||||
filename = os.path.normpath(os.path.abspath(filename))
|
||||
|
||||
@ -1289,9 +1293,11 @@ class Gramps(GrampsDBCallback.GrampsDBCallback):
|
||||
except db.DBAccessError, msg:
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('%s could not be opened.' % filename) + '\n' + msg[1])
|
||||
return 0
|
||||
except (db.DBError), msg:
|
||||
ErrorDialog(_('Cannot open database'),
|
||||
_('%s could not be opened.' % filename) + '\n' + msg[1])
|
||||
gtk.main_quit()
|
||||
|
||||
self.topWindow.set_resizable(True)
|
||||
# Undo/Redo always start with standard labels and insensitive state
|
||||
self.undo_callback(None)
|
||||
self.redo_callback(None)
|
||||
@ -1878,7 +1884,40 @@ class Gramps(GrampsDBCallback.GrampsDBCallback):
|
||||
task(self.db,self.active_person,self.tool_callback,self)
|
||||
|
||||
def open_example(self,obj):
|
||||
pass
|
||||
import shutil
|
||||
dest = os.path.expanduser("~/.gramps/example")
|
||||
if not os.path.isdir(dest):
|
||||
try:
|
||||
os.mkdir(dest)
|
||||
except IOError,msg:
|
||||
ErrorDialog(_('Could not create example database'),
|
||||
_('The directory ~/.gramps/example could not '
|
||||
'be created.') + '\n' + str(msg) )
|
||||
except OSError,msg:
|
||||
ErrorDialog(_('Could not create example database'),
|
||||
_('The directory ~/.gramps/example could not '
|
||||
'be created.') + '\n' + str(msg) )
|
||||
except:
|
||||
ErrorDialog(_('Could not create example database'),
|
||||
_('The directory ~/.gramps/example could not '
|
||||
'be created.'))
|
||||
try:
|
||||
example_dir = "%s/share/gramps/example" % const.prefixdir
|
||||
for filename in os.listdir(example_dir):
|
||||
shutil.copyfile("%s/%s" % (example_dir,filename),
|
||||
"%s/%s" % (dest,filename) )
|
||||
try:
|
||||
shutil.copystat("%s/%s" % (example_dir,filename),
|
||||
"%s/%s" % (dest,filename))
|
||||
except:
|
||||
pass
|
||||
except IOError,msg:
|
||||
ErrorDialog(_('Could not create example database'),str(msg))
|
||||
except OSError,msg:
|
||||
ErrorDialog(_('Could not create example database'),str(msg))
|
||||
|
||||
filename = "%s/%s" % (dest,const.xmlFile)
|
||||
DbPrompter.open_native(self,filename,const.app_gramps_xml)
|
||||
|
||||
DARKEN = 1.4
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="has_separator">False</property>
|
||||
|
||||
<child internal-child="vbox">
|
||||
@ -100,10 +99,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">6</property>
|
||||
@ -156,10 +151,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@ -184,10 +175,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@ -306,7 +293,6 @@
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="has_separator">False</property>
|
||||
|
||||
<child internal-child="vbox">
|
||||
@ -404,10 +390,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">10</property>
|
||||
@ -438,7 +420,7 @@
|
||||
<widget class="GtkTextView" id="text1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="overwrite">False</property>
|
||||
<property name="accepts_tab">True</property>
|
||||
<property name="justification">GTK_JUSTIFY_LEFT</property>
|
||||
@ -475,7 +457,7 @@
|
||||
<widget class="GtkTextView" id="text2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">True</property>
|
||||
<property name="editable">False</property>
|
||||
<property name="overwrite">False</property>
|
||||
<property name="accepts_tab">True</property>
|
||||
<property name="justification">GTK_JUSTIFY_LEFT</property>
|
||||
@ -576,7 +558,6 @@
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="has_separator">False</property>
|
||||
|
||||
<child internal-child="vbox">
|
||||
@ -660,10 +641,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
@ -687,10 +664,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
@ -715,10 +688,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">4</property>
|
||||
@ -1190,7 +1159,6 @@
|
||||
<property name="skip_pager_hint">False</property>
|
||||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="has_separator">False</property>
|
||||
|
||||
<child internal-child="vbox">
|
||||
@ -1273,10 +1241,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
@ -1298,10 +1262,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">6</property>
|
||||
@ -1332,10 +1292,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
@ -1360,10 +1316,6 @@
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
|
@ -370,7 +370,8 @@ class ComprehensiveAncestorsReport (Report.Report):
|
||||
for media_ref in partner.get_media_list ()[:1]:
|
||||
object_handle = media_ref.get_reference_handle()
|
||||
mobject = self.database.get_object_from_handle(object_handle)
|
||||
if mobject.get_mime_type()[0:5] == "image":
|
||||
mime_type = mobject.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
spouse.append ((self.doc.add_media_object,
|
||||
[mobject.get_path (),
|
||||
'right', 2, 2]))
|
||||
@ -403,7 +404,8 @@ class ComprehensiveAncestorsReport (Report.Report):
|
||||
for media_ref in photos[:1]:
|
||||
object_handle = media_ref.get_reference_handle()
|
||||
mobject = self.database.get_object_from_handle(object_handle)
|
||||
if mobject.get_mime_type()[0:5] == "image":
|
||||
mime_type = mobject.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
ret.append ((self.doc.add_media_object,
|
||||
[mobject.get_path (), 'left', 2, 2]))
|
||||
ret.append ((self.doc.end_cell, []))
|
||||
|
@ -239,7 +239,7 @@ class CheckIntegrity:
|
||||
place = self.db.get_place_from_handle(handle)
|
||||
if place.has_media_reference(ObjectId):
|
||||
place.remove_media_references([ObjectId])
|
||||
self.db.commit_place(p,self.trans)
|
||||
self.db.commit_place(place,self.trans)
|
||||
|
||||
self.removed_photo.append(ObjectId)
|
||||
self.db.remove_object(ObjectId,self.trans)
|
||||
|
@ -65,6 +65,14 @@ _menulist = {
|
||||
_('Relationship type:') : const.family_relations,
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Sorting function for the filter rules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def by_rule_name(f,s):
|
||||
return cmp(f.name,s.name)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# MyBoolean - check button with standard interface
|
||||
@ -213,7 +221,7 @@ class MyID(gtk.HBox):
|
||||
if val == None:
|
||||
self.set_text('')
|
||||
else:
|
||||
self.set_text(val.get_handle())
|
||||
self.set_text(val.get_gramps_id())
|
||||
|
||||
def get_text(self):
|
||||
return unicode(self.entry.get_text())
|
||||
@ -550,7 +558,7 @@ class EditFilter:
|
||||
def draw_rules(self):
|
||||
self.rlist.clear()
|
||||
for r in self.filter.get_rules():
|
||||
self.rlist.add([r.trans_name(),r.display_values()],r)
|
||||
self.rlist.add([r.name,r.display_values()],r)
|
||||
|
||||
def on_ok_clicked(self,obj):
|
||||
n = unicode(self.fname.get_text()).strip()
|
||||
@ -636,26 +644,21 @@ class EditRule:
|
||||
self.valuebox.add(self.notebook)
|
||||
self.page_num = 0
|
||||
self.page = []
|
||||
self.name2page = {}
|
||||
self.class2page = {}
|
||||
the_map = {}
|
||||
the_list = []
|
||||
keylist = GenericFilter.tasks.keys()
|
||||
keylist.sort()
|
||||
for name in keylist:
|
||||
cname = GenericFilter.tasks[name]
|
||||
arglist = cname.labels
|
||||
for class_obj in GenericFilter.editor_rule_list:
|
||||
arglist = class_obj.labels
|
||||
vallist = []
|
||||
tlist = []
|
||||
self.page.append((name,cname,vallist,tlist))
|
||||
self.page.append((class_obj,vallist,tlist))
|
||||
pos = 0
|
||||
l2 = gtk.Label(name)
|
||||
l2 = gtk.Label(class_obj.name)
|
||||
l2.set_alignment(0,0.5)
|
||||
l2.show()
|
||||
c = gtk.TreeView()
|
||||
c.set_data('d',pos)
|
||||
c.show()
|
||||
the_list.append(c)
|
||||
the_map[name] = c
|
||||
the_map[class_obj] = c
|
||||
# Only add a table with parameters if there are any parameters
|
||||
if arglist:
|
||||
table = gtk.Table(3,len(arglist))
|
||||
@ -698,11 +701,11 @@ class EditRule:
|
||||
table.attach(l,1,2,pos,pos+1,gtk.FILL,0,5,5)
|
||||
table.attach(t,2,3,pos,pos+1,gtk.EXPAND|gtk.FILL,0,5,5)
|
||||
pos = pos + 1
|
||||
self.notebook.append_page(table,gtk.Label(name))
|
||||
self.name2page[name] = self.page_num
|
||||
self.notebook.append_page(table,gtk.Label(class_obj.name))
|
||||
self.class2page[class_obj] = self.page_num
|
||||
self.page_num = self.page_num + 1
|
||||
self.page_num = 0
|
||||
self.store = gtk.TreeStore(gobject.TYPE_STRING)
|
||||
self.store = gtk.TreeStore(gobject.TYPE_STRING,gobject.TYPE_PYOBJECT)
|
||||
self.selection = self.rname.get_selection()
|
||||
col = gtk.TreeViewColumn(_('Rule Name'),gtk.CellRendererText(),text=0)
|
||||
self.rname.append_column(col)
|
||||
@ -719,38 +722,46 @@ class EditRule:
|
||||
#
|
||||
sel_node = None
|
||||
if self.active_rule:
|
||||
self.sel_name = unicode(_(self.active_rule.name()))
|
||||
self.sel_class = self.active_rule.__class__
|
||||
else:
|
||||
self.sel_name = ""
|
||||
|
||||
for v in the_map.keys():
|
||||
the_filter = GenericFilter.tasks[v]([None])
|
||||
category = the_filter.category()
|
||||
if top_level.has_key(category):
|
||||
top_level[category].append(v)
|
||||
else:
|
||||
top_level[category] = [v]
|
||||
top_node[category] = self.store.insert_after(None,last_top)
|
||||
last_top = top_node[category]
|
||||
self.store.set(last_top,0,category)
|
||||
self.sel_class = None
|
||||
|
||||
keys = the_map.keys()
|
||||
keys.sort(by_rule_name)
|
||||
keys.reverse()
|
||||
catlist = []
|
||||
for class_obj in keys:
|
||||
category = class_obj.category
|
||||
if category not in catlist:
|
||||
catlist.append(category)
|
||||
catlist.sort()
|
||||
|
||||
for category in catlist:
|
||||
top_node[category] = self.store.insert_after(None,last_top)
|
||||
top_level[category] = []
|
||||
last_top = top_node[category]
|
||||
self.store.set(last_top,0,category,1,None)
|
||||
|
||||
for class_obj in keys:
|
||||
category = class_obj.category
|
||||
top_level[category].append(class_obj.name)
|
||||
node = self.store.insert_after(top_node[category],prev)
|
||||
self.store.set(node,0,v)
|
||||
self.store.set(node,0,class_obj.name,1,class_obj)
|
||||
|
||||
#
|
||||
# if this is an edit rule, save the node
|
||||
if v == self.sel_name:
|
||||
if class_obj == self.sel_class:
|
||||
sel_node = node
|
||||
|
||||
if sel_node:
|
||||
self.selection.select_iter(sel_node)
|
||||
page = self.name2page[self.sel_name]
|
||||
page = self.class2page[self.active_rule.__class__]
|
||||
self.notebook.set_current_page(page)
|
||||
self.display_values(self.sel_name)
|
||||
(n,c,v,t) = self.page[page]
|
||||
self.display_values(self.active_rule.__class__)
|
||||
(class_obj,vallist,tlist) = self.page[page]
|
||||
r = self.active_rule.values()
|
||||
for i in range(0,len(t)):
|
||||
t[i].set_text(r[i])
|
||||
for i in range(0,len(tlist)):
|
||||
tlist[i].set_text(r[i])
|
||||
|
||||
self.selection.connect('changed', self.on_node_selected)
|
||||
self.rule.signal_autoconnect({
|
||||
@ -777,7 +788,10 @@ class EditRule:
|
||||
|
||||
def add_itself_to_menu(self):
|
||||
self.parent.child_windows[self.win_key] = self
|
||||
label = self.sel_name
|
||||
if self.sel_class:
|
||||
label = self.sel_class.name
|
||||
else:
|
||||
label = ''
|
||||
if not label.strip():
|
||||
label = _("New Rule")
|
||||
label = "%s: %s" % (_('Rule'),label)
|
||||
@ -800,32 +814,32 @@ class EditRule:
|
||||
store,iter = self.selection.get_selected()
|
||||
if iter:
|
||||
try:
|
||||
key = unicode(store.get_value(iter,0))
|
||||
self.display_values(key)
|
||||
class_obj = store.get_value(iter,1)
|
||||
self.display_values(class_obj)
|
||||
except:
|
||||
self.valuebox.set_sensitive(0)
|
||||
self.rule_name.set_text(_('No rule selected'))
|
||||
self.rule.get_widget('description').set_text('')
|
||||
|
||||
def display_values(self,key):
|
||||
page = self.name2page[key]
|
||||
def display_values(self,class_obj):
|
||||
page = self.class2page[class_obj]
|
||||
self.notebook.set_current_page(page)
|
||||
self.valuebox.set_sensitive(1)
|
||||
self.rule_name.set_text(key)
|
||||
the_filter = GenericFilter.tasks[key]([None])
|
||||
self.rule.get_widget('description').set_text(the_filter.description())
|
||||
self.rule_name.set_text(class_obj.name)
|
||||
self.rule.get_widget('description').set_text(class_obj.description)
|
||||
|
||||
def rule_ok(self,obj):
|
||||
name = unicode(self.rule_name.get_text())
|
||||
class_def = GenericFilter.tasks[name]
|
||||
obj = class_def(None)
|
||||
if self.rule_name.get_text() == _('No rule selected'):
|
||||
return
|
||||
|
||||
try:
|
||||
page = self.name2page[name]
|
||||
(n,c,v,t) = self.page[page]
|
||||
page = self.notebook.get_current_page()
|
||||
(class_obj,vallist,tlist) = self.page[page]
|
||||
value_list = []
|
||||
for x in t:
|
||||
for x in tlist:
|
||||
value_list.append(unicode(x.get_text()))
|
||||
store,iter = self.parent.rlist.get_selected()
|
||||
new_rule = c(value_list)
|
||||
new_rule = class_obj(value_list)
|
||||
if self.active_rule:
|
||||
rule = self.parent.rlist.get_object(iter)
|
||||
self.parent.filter.delete_rule(rule)
|
||||
@ -839,7 +853,6 @@ class EditRule:
|
||||
self.window.destroy()
|
||||
DisplayTrace.DisplayTrace()
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
#
|
||||
|
@ -52,6 +52,7 @@ import Utils
|
||||
import const
|
||||
from QuestionDialog import ErrorDialog
|
||||
from DateHandler import parser as _dp
|
||||
from htmlentitydefs import name2codepoint
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -419,6 +420,8 @@ class GeneWebParser:
|
||||
person.set_primary_name(name)
|
||||
if gender != None:
|
||||
person.set_gender(gender)
|
||||
else:
|
||||
person.set_gender(RelLib.Person.UNKNOWN)
|
||||
self.db.commit_person(person,self.trans)
|
||||
personDataRe = re.compile("^[0-9<>~#\[({!].*$")
|
||||
dateRe = re.compile("^[0-9~<>?]+.*$")
|
||||
@ -660,7 +663,7 @@ class GeneWebParser:
|
||||
def get_or_create_person(self,firstname,lastname):
|
||||
person = None
|
||||
mykey = firstname+lastname
|
||||
if mykey in self.ikeys:
|
||||
if mykey in self.ikeys and firstname != "?" and lastname != "?":
|
||||
person = self.db.get_person_from_handle(self.ikeys[mykey])
|
||||
else:
|
||||
person = RelLib.Person()
|
||||
@ -696,7 +699,29 @@ class GeneWebParser:
|
||||
return sref
|
||||
|
||||
def decode(self,s):
|
||||
return( latin_utf8.latin_to_utf8( s.replace('_',' ')))
|
||||
s = latin_utf8.latin_to_utf8( s.replace('_',' '))
|
||||
charref_re = re.compile('(&#)(x?)([0-9a-zA-Z]+)(;)')
|
||||
for match in charref_re.finditer(s):
|
||||
try:
|
||||
if match.group(2): # HEX
|
||||
nchar = unichr(int(match.group(3),16))
|
||||
else: # Decimal
|
||||
nchar = unichr(int(match.group(3)))
|
||||
s = s.replace(match.group(0),nchar)
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
# replace named entities
|
||||
entref_re = re.compile('(&)([a-zA-Z]+)(;)')
|
||||
for match in entref_re.finditer(s):
|
||||
try:
|
||||
if match.group(2) in name2codepoint:
|
||||
nchar = unichr(name2codepoint[match.group(2)])
|
||||
s = s.replace(match.group(0),nchar)
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
|
||||
return( s)
|
||||
|
||||
def cnv(seld,s):
|
||||
return( latin_utf8.latin_to_utf8(s))
|
||||
|
@ -392,7 +392,8 @@ class IndivCompleteReport(Report.Report):
|
||||
if len(media_list) > 0:
|
||||
object_handle = media_list[0].get_reference_handle()
|
||||
object = self.database.get_object_from_handle(object_handle)
|
||||
if object.get_mime_type()[0:5] == "image":
|
||||
mime_type = object.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
file = object.get_path()
|
||||
self.doc.start_paragraph("IDS-Normal")
|
||||
self.doc.add_media_object(file,"row",4.0,4.0)
|
||||
|
@ -211,7 +211,8 @@ class IndivSummary(Report.Report):
|
||||
if len(media_list) > 0:
|
||||
object_handle = media_list[0].get_reference_handle()
|
||||
object = self.database.get_object_from_handle(object_handle)
|
||||
if object.get_mime_type()[0:5] == "image":
|
||||
mime_type = object.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
file = object.get_path()
|
||||
self.doc.start_paragraph("IVS-Normal")
|
||||
self.doc.add_media_object(file,"row",4.0,4.0)
|
||||
|
@ -401,7 +401,8 @@ class HomePage(BasePage):
|
||||
if not obj:
|
||||
print "%s object not found" % note_id
|
||||
else:
|
||||
if obj.get_mime_type()[0:5] == "image":
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
newpath = obj.gramps_id + os.path.splitext(obj.get_path())[1]
|
||||
shutil.copyfile(obj.get_path(),
|
||||
os.path.join(html_dir,newpath))
|
||||
|
@ -680,7 +680,7 @@ class ScratchPadListView:
|
||||
return
|
||||
|
||||
# Just select the first match.
|
||||
wrapper_class = self._target_type_to_wrapper_class_map[possible_wrappers[0]]
|
||||
wrapper_class = self._target_type_to_wrapper_class_map[str(possible_wrappers[0])]
|
||||
|
||||
o = wrapper_class(self._gramps_model,sel_data)
|
||||
|
||||
|
@ -412,7 +412,7 @@ class Extract:
|
||||
genders - which gender(s) to include into statistics
|
||||
year_from - use only persons who've born this year of after
|
||||
year_to - use only persons who've born this year or before
|
||||
no_years - use also people without any birth year
|
||||
no_years - use also people without known birth year
|
||||
|
||||
Returns an array of tuple of:
|
||||
- Extraction method title
|
||||
@ -774,7 +774,7 @@ class StatisticsChartOptions(ReportOptions.ReportOptions):
|
||||
"Earlier than 'year_to' value"),
|
||||
'year_to' : ("=num", "Birth year until which to include people",
|
||||
"Smaller than %d" % self.options_dict['year_to']),
|
||||
'no_years' : ("=0/1", "Whether to include people without birth years",
|
||||
'no_years' : ("=0/1", "Whether to include people without known birth years",
|
||||
["Do not include", "Include"], True),
|
||||
'bar_items' : ("=num", "Use barchart instead of piechart with this many or more items",
|
||||
"Number of items with which piecharts still look good...")
|
||||
@ -878,9 +878,9 @@ class StatisticsChartOptions(ReportOptions.ReportOptions):
|
||||
dialog.add_option(_('People born between'), box, tip)
|
||||
box.show_all()
|
||||
|
||||
# include people without birth year?
|
||||
tip = _("Check this if you want people who have no birth date or year to be accounted also in the statistics.")
|
||||
self.no_years = gtk.CheckButton(_("Include people without birth years"))
|
||||
# include people without known birth year?
|
||||
tip = _("Check this if you want people who have no known birth date or year to be accounted also in the statistics.")
|
||||
self.no_years = gtk.CheckButton(_("Include people without known birth years"))
|
||||
self.no_years.set_active(self.options_dict['no_years'])
|
||||
dialog.add_option(None, self.no_years, tip)
|
||||
self.no_years.show()
|
||||
@ -899,7 +899,7 @@ class StatisticsChartOptions(ReportOptions.ReportOptions):
|
||||
tip = _("With fewer items pie chart and legend will be used instead of a bar chart.")
|
||||
self.bar_items = gtk.Entry(2)
|
||||
self.bar_items.set_text(str(self.options_dict['bar_items']))
|
||||
dialog.add_option(_("Min. bar char items"), self.bar_items, tip)
|
||||
dialog.add_option(_("Max. items for a pie"), self.bar_items, tip)
|
||||
|
||||
# -------------------------------------------------
|
||||
# List of available charts on a separate option tab
|
||||
|
@ -30,6 +30,8 @@
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import traceback
|
||||
import sys
|
||||
from random import randint,choice
|
||||
from gettext import gettext as _
|
||||
|
||||
@ -47,12 +49,14 @@ import gtk.glade
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import Errors
|
||||
import Date
|
||||
import RelLib
|
||||
import latin_utf8
|
||||
import Utils
|
||||
import const
|
||||
from QuestionDialog import ErrorDialog
|
||||
from DateHandler import parser as _dp
|
||||
from DateHandler import displayer as _dd
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -80,6 +84,10 @@ class TestcaseGenerator:
|
||||
self.check_bugs.set_active(True)
|
||||
self.top.vbox.pack_start(self.check_bugs,0,0,5)
|
||||
|
||||
self.check_dates = gtk.CheckButton( _("Generate date tests"))
|
||||
self.check_dates.set_active(True)
|
||||
self.top.vbox.pack_start(self.check_dates,0,0,5)
|
||||
|
||||
self.check_persons = gtk.CheckButton( _("Generate dummy families"))
|
||||
self.check_persons.set_active(True)
|
||||
self.top.vbox.pack_start(self.check_persons,0,0,5)
|
||||
@ -99,16 +107,17 @@ class TestcaseGenerator:
|
||||
|
||||
response = self.top.run()
|
||||
bugs = self.check_bugs.get_active()
|
||||
dates = self.check_dates.get_active()
|
||||
persons = self.check_persons.get_active()
|
||||
multiple_trans = self.check_trans.get_active()
|
||||
person_count = int(self.entry_count.get_text())
|
||||
self.top.destroy()
|
||||
|
||||
if response == gtk.RESPONSE_OK:
|
||||
self.run_generator(bugs,persons,person_count,multiple_trans)
|
||||
self.run_generator(bugs,dates,persons,person_count,multiple_trans)
|
||||
|
||||
|
||||
def run_generator( self, generate_bugs = 1, generate_families = 1, generate_max_persons = 2000, multiple_transactions=False):
|
||||
def run_generator( self, generate_bugs = 1, generate_dates = 1, generate_families = 1, generate_max_persons = 2000, multiple_transactions=False):
|
||||
title = "%s - GRAMPS" % _("Generate testcases")
|
||||
self.top = gtk.Window()
|
||||
self.top.set_title(title)
|
||||
@ -136,8 +145,114 @@ class TestcaseGenerator:
|
||||
self.trans.set_batch(True)
|
||||
self.db.disable_signals()
|
||||
|
||||
|
||||
if self.multiple_transactions:
|
||||
|
||||
print "TESTING SIGNALS..."
|
||||
|
||||
print "\nCREATE PERSON"
|
||||
p = RelLib.Person()
|
||||
self.db.add_person( p, self.trans)
|
||||
print "\nUPDATE PERSON"
|
||||
self.db.commit_person( p, self.trans)
|
||||
print "\nDELETE PERSON"
|
||||
self.db.remove_person( p.get_handle(), self.trans)
|
||||
|
||||
print "\nCREATE FAMILY"
|
||||
f = RelLib.Family()
|
||||
self.db.add_family( f, self.trans)
|
||||
print "\nUPDATE FAMILY"
|
||||
self.db.commit_family( f, self.trans)
|
||||
print "\nDELETE FAMILY"
|
||||
self.db.remove_family( f.get_handle(), self.trans)
|
||||
|
||||
print "\nCREATE EVENT"
|
||||
e = RelLib.Event()
|
||||
self.db.add_event( e, self.trans)
|
||||
print "\nUPDATE EVENT"
|
||||
self.db.commit_event( e, self.trans)
|
||||
print "\nDELETE EVENT"
|
||||
self.db.remove_event( e.get_handle(), self.trans)
|
||||
|
||||
print "\nCREATE PLACE"
|
||||
p = RelLib.Place()
|
||||
self.db.add_place( p, self.trans)
|
||||
print "\nUPDATE PLACE"
|
||||
self.db.commit_place( p, self.trans)
|
||||
print "\nDELETE PLACE"
|
||||
self.db.remove_place( p.get_handle(), self.trans)
|
||||
|
||||
print "\nCREATE SOURCE"
|
||||
s = RelLib.Source()
|
||||
self.db.add_source( s, self.trans)
|
||||
print "\nUPDATE SOURCE"
|
||||
self.db.commit_source( s, self.trans)
|
||||
print "\nDELETE SOURCE"
|
||||
self.db.remove_source( s.get_handle(), self.trans)
|
||||
|
||||
print "\nCREATE MEDIA"
|
||||
m = RelLib.MediaObject()
|
||||
self.db.add_object( m, self.trans)
|
||||
print "\nUPDATE MEDIA"
|
||||
self.db.commit_media_object( m, self.trans)
|
||||
print "\nDELETE MEDIA"
|
||||
self.db.remove_object( m.get_handle(), self.trans)
|
||||
|
||||
print "DONE."
|
||||
|
||||
|
||||
print "TESTING DB..."
|
||||
|
||||
print "\nCREATE PERSON None"
|
||||
self.db.add_person( None, self.trans)
|
||||
print "\nUPDATE PERSON None"
|
||||
self.db.commit_person( None, self.trans)
|
||||
print "\nDELETE PERSON Invalid Handle"
|
||||
self.db.remove_person( "Invalid Handle", self.trans)
|
||||
|
||||
print "\nCREATE FAMILY None"
|
||||
self.db.add_family( None, self.trans)
|
||||
print "\nUPDATE FAMILY None"
|
||||
self.db.commit_family( None, self.trans)
|
||||
print "\nDELETE FAMILY Invalid Handle"
|
||||
self.db.remove_family( "Invalid Handle", self.trans)
|
||||
|
||||
print "\nCREATE EVENT None"
|
||||
self.db.add_event( None, self.trans)
|
||||
print "\nUPDATE EVENT None"
|
||||
self.db.commit_event( None, self.trans)
|
||||
print "\nDELETE EVENT Invalid Handle"
|
||||
self.db.remove_event( "Invalid Handle", self.trans)
|
||||
|
||||
print "\nCREATE PLACE None"
|
||||
self.db.add_place( None, self.trans)
|
||||
print "\nUPDATE PLACE None"
|
||||
self.db.commit_place( None, self.trans)
|
||||
print "\nDELETE PLACE Invalid Handle"
|
||||
self.db.remove_place( "Invalid Handle", self.trans)
|
||||
|
||||
print "\nCREATE SOURCE None"
|
||||
self.db.add_source( None, self.trans)
|
||||
print "\nUPDATE SOURCE None"
|
||||
self.db.commit_source( None, self.trans)
|
||||
print "\nDELETE SOURCE Invalid Handle"
|
||||
self.db.remove_source( "Invalid Handle", self.trans)
|
||||
|
||||
print "\nCREATE MEDIA None"
|
||||
self.db.add_object( None, self.trans)
|
||||
print "\nUPDATE MEDIA None"
|
||||
self.db.commit_media_object( None, self.trans)
|
||||
print "\nDELETE MEDIA Invalid Handle"
|
||||
self.db.remove_object( "Invalid Handle", self.trans)
|
||||
|
||||
print "DONE."
|
||||
|
||||
|
||||
if generate_bugs:
|
||||
self.generate_broken_relations()
|
||||
|
||||
if generate_dates:
|
||||
self.generate_date_tests()
|
||||
|
||||
if generate_families:
|
||||
self.persons_todo.append( self.generate_person(0))
|
||||
@ -384,6 +499,103 @@ class TestcaseGenerator:
|
||||
self.commit_transaction() # COMMIT TRANSACTION STEP
|
||||
|
||||
|
||||
def generate_date_tests(self):
|
||||
dates = []
|
||||
# first some valid dates
|
||||
calendar = Date.CAL_GREGORIAN
|
||||
for quality in (Date.QUAL_NONE, Date.QUAL_ESTIMATED, Date.QUAL_CALCULATED):
|
||||
for modifier in (Date.MOD_NONE, Date.MOD_BEFORE, Date.MOD_AFTER, Date.MOD_ABOUT):
|
||||
for slash1 in (False,True):
|
||||
d = Date.Date()
|
||||
d.set(quality,modifier,calendar,(4,7,1789,slash1),"Text comment")
|
||||
dates.append( d)
|
||||
for modifier in (Date.MOD_RANGE, Date.MOD_SPAN):
|
||||
for slash1 in (False,True):
|
||||
for slash2 in (False,True):
|
||||
d = Date.Date()
|
||||
d.set(quality,modifier,calendar,(4,7,1789,slash1,5,8,1876,slash2),"Text comment")
|
||||
dates.append( d)
|
||||
modifier = Date.MOD_TEXTONLY
|
||||
d = Date.Date()
|
||||
d.set(quality,modifier,calendar,Date.EMPTY,"This is a textual date")
|
||||
dates.append( d)
|
||||
|
||||
# test invalid dates
|
||||
dateval = (4,7,1789,False,5,8,1876,False)
|
||||
for l in range(1,len(dateval)):
|
||||
d = Date.Date()
|
||||
try:
|
||||
d.set(Date.QUAL_NONE,Date.MOD_NONE,Date.CAL_GREGORIAN,dateval[:l],"Text comment")
|
||||
dates.append( d)
|
||||
except Errors.DateError, e:
|
||||
d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
|
||||
dates.append( d)
|
||||
except:
|
||||
d = Date.Date()
|
||||
d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
|
||||
dates.append( d)
|
||||
for l in range(1,len(dateval)):
|
||||
d = Date.Date()
|
||||
try:
|
||||
d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,dateval[:l],"Text comment")
|
||||
dates.append( d)
|
||||
except Errors.DateError, e:
|
||||
d.set_as_text("Date identified value correctly as invalid.\n%s" % e)
|
||||
dates.append( d)
|
||||
except:
|
||||
d = Date.Date()
|
||||
d.set_as_text("Date.set Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
|
||||
dates.append( d)
|
||||
d = Date.Date()
|
||||
d.set(Date.QUAL_NONE,Date.MOD_NONE,Date.CAL_GREGORIAN,(44,7,1789,False),"Text comment")
|
||||
dates.append( d)
|
||||
d = Date.Date()
|
||||
d.set(Date.QUAL_NONE,Date.MOD_NONE,Date.CAL_GREGORIAN,(4,77,1789,False),"Text comment")
|
||||
dates.append( d)
|
||||
d = Date.Date()
|
||||
d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,(4,7,1789,False,55,8,1876,False),"Text comment")
|
||||
dates.append( d)
|
||||
d = Date.Date()
|
||||
d.set(Date.QUAL_NONE,Date.MOD_SPAN,Date.CAL_GREGORIAN,(4,7,1789,False,5,88,1876,False),"Text comment")
|
||||
dates.append( d)
|
||||
|
||||
# now add them as birth to new persons
|
||||
for dateval in dates:
|
||||
bevent = RelLib.Event()
|
||||
bevent.set_name("Birth")
|
||||
bevent.set_date_object(dateval)
|
||||
bevent_h = self.db.add_event(bevent,self.trans)
|
||||
# for the death event display the date as text and parse it back to a new date
|
||||
ndate = None
|
||||
try:
|
||||
datestr = _dd.display( dateval)
|
||||
try:
|
||||
ndate = _dp.parse( datestr)
|
||||
if not ndate:
|
||||
ndate = Date.Date()
|
||||
ndate.set_as_text("DateParser None")
|
||||
except:
|
||||
ndate = Date.Date()
|
||||
ndate.set_as_text("DateParser Exception %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
|
||||
except:
|
||||
ndate = Date.Date()
|
||||
ndate.set_as_text("DateDisplay Exception: %s" % ("".join(traceback.format_exception(*sys.exc_info())),))
|
||||
|
||||
if dateval.get_modifier() != Date.MOD_TEXTONLY and ndate.get_modifier() == Date.MOD_TEXTONLY:
|
||||
# parser was unable to correctly parse the string
|
||||
ndate.set_as_text( "TEXTONLY: "+ndate.get_text())
|
||||
|
||||
|
||||
devent = RelLib.Event()
|
||||
devent.set_name("Death")
|
||||
devent.set_date_object(ndate)
|
||||
devent_h = self.db.add_event(devent,self.trans)
|
||||
person_h = self.generate_person(None, "DateTest")
|
||||
person = self.db.get_person_from_handle(person_h)
|
||||
person.set_birth_handle(bevent_h)
|
||||
person.set_death_handle(devent_h)
|
||||
self.db.commit_person(person,self.trans)
|
||||
self.commit_transaction() # COMMIT TRANSACTION STEP
|
||||
|
||||
def generate_person(self,gender=None,lastname=None,note=None):
|
||||
self.progress.set_fraction(min(1.0,max(0.0, 1.0*self.person_count/self.max_person_count)))
|
||||
|
@ -294,7 +294,8 @@ class IndividualPage:
|
||||
if self.photos and len(media_list) > 0:
|
||||
object_handle = media_list[0].get_reference_handle()
|
||||
object = self.db.get_object_from_handle(object_handle)
|
||||
if object.get_mime_type()[0:5] == "image":
|
||||
mime_type = object.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
src = object.get_path()
|
||||
junk,ext = os.path.splitext(src)
|
||||
base = '%s%s' % (object.get_gramps_id(),ext)
|
||||
@ -390,7 +391,8 @@ class IndividualPage:
|
||||
for object_ref in self.person.get_media_list():
|
||||
obj_id = object_ref.get_reference_handle()
|
||||
obj = self.db.get_object_from_handle(obj_id)
|
||||
if obj.get_mime_type()[0:5] != "image":
|
||||
mime_type = obj.get_mime_type()
|
||||
if not mime_type or not mime_type.startswith("image"):
|
||||
continue
|
||||
if object_ref.get_privacy():
|
||||
continue
|
||||
|
@ -121,7 +121,8 @@ class PackageWriter:
|
||||
root = os.path.basename(oldfile)
|
||||
if os.path.isfile(oldfile):
|
||||
self.copy_file(oldfile,'burn:///%s/%s' % (base,root))
|
||||
if obj.get_mime_type()[0:5] == "image":
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
self.make_thumbnail(base,root,obj.get_path())
|
||||
else:
|
||||
print "Warning: media file %s was not found," % root,\
|
||||
@ -223,7 +224,7 @@ class PackageWriter:
|
||||
if os.path.isfile(newfile):
|
||||
self.copy_file(newfile,'burn:///%s/%s' % (base,obase))
|
||||
ntype = GrampsMime.get_type(newfile)
|
||||
if ntype[0:5] == "image":
|
||||
if ntype and ntype.startswith("image"):
|
||||
self.make_thumbnail(base,obase,newfile)
|
||||
|
||||
fs_top = gtk.FileSelection("%s - GRAMPS" % _("Select file"))
|
||||
@ -244,7 +245,8 @@ class PackageWriter:
|
||||
root = os.path.basename(oldfile)
|
||||
if os.path.isfile(oldfile):
|
||||
self.copy_file(oldfile,'burn:///%s/%s' % (base,root))
|
||||
if obj.get_mime_type()[0:5] == "image":
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
self.make_thumbnail(base,root,obj.get_path())
|
||||
else:
|
||||
# File is lost => ask what to do
|
||||
|
3645
src/po/da.po
3645
src/po/da.po
File diff suppressed because it is too large
Load Diff
3669
src/po/es.po
3669
src/po/es.po
File diff suppressed because it is too large
Load Diff
3041
src/po/fi.po
3041
src/po/fi.po
File diff suppressed because it is too large
Load Diff
2554
src/po/fr.po
2554
src/po/fr.po
File diff suppressed because it is too large
Load Diff
3341
src/po/nb.po
3341
src/po/nb.po
File diff suppressed because it is too large
Load Diff
3341
src/po/no.po
3341
src/po/no.po
File diff suppressed because it is too large
Load Diff
3683
src/po/ru.po
3683
src/po/ru.po
File diff suppressed because it is too large
Load Diff
3271
src/po/sv.po
3271
src/po/sv.po
File diff suppressed because it is too large
Load Diff
3164
src/po/template.po
3164
src/po/template.po
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user