Initial revision

svn: r3
This commit is contained in:
Don Allingham
2001-05-13 01:56:57 +00:00
parent 36bc60e3ba
commit 391abdc688
126 changed files with 42522 additions and 0 deletions

339
gramps/COPYING Normal file
View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

36
gramps/Makefile.in Normal file
View File

@@ -0,0 +1,36 @@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
datadir = @datadir@/@PACKAGE@
INSTALL = @INSTALL@
@SET_MAKE@
all:
(cd src; ${MAKE} all)
(cd src/plugins; ${MAKE} all)
(cd src/filters; ${MAKE} all)
(cd src/data; ${MAKE} all)
install:
(cd src; ${MAKE} install)
(cd src/plugins; ${MAKE} install)
(cd src/filters; ${MAKE} install)
(cd src/data; ${MAKE} install)
-${INSTALL} -d ${bindir}
${INSTALL} -c gramps.sh ${bindir}/gramps
chmod +x ${bindir}/gramps
uninstall:
(cd src; ${MAKE} uninstall)
(cd src/plugins; ${MAKE} uninstall)
(cd src/filters; ${MAKE} uninstall)
(cd src/data; ${MAKE} uninstall)
rm ${bindir}/gramps
clean:
(cd src; ${MAKE} clean)
(cd src/plugins; ${MAKE} clean)
(cd src/filters; ${MAKE} clean)
(cd src/data; ${MAKE} clean)
rm -f core *~ config.cache config.log config.status

48
gramps/NEWS Normal file
View File

@@ -0,0 +1,48 @@
Version 0.1.4
* Implemented date ranges. Valid forms are "from <date> to <date>" and
"between <date> and <date>".
* Better support for partial dates. A question mark can optionally be
used for a placeholder for a year if the year is unknown. Illegal
date formats issue a warning upon an attempt to save the date.
* Start of internationalization (i18n) support. Had to include a single
C file to allow libglade to understand translations. This means that
binary releases are no longer going to be platform independant.
* Start of a generic output formatter for report generation. Currently
supports HTML, OpenOffice (625+), and AbiWord (0.7.13+). Allows
control of paragraph and font styles.
Version 0.1.3
* Allow the user to specifiy their preferred numerical date input format,
either DD/MM/YY or MM/DD/YY on the preferences dialog box.
* Handles file problems a bit more gracefully.
* Use ISO-8859-1 character set instead of ASCII to support languages other
than English. Eventually this should go to unicode, but python 1.5.2
does not have good unicode support. Python 2.X/Gnome 2.X will be the
migration for this feature.
* Handle ANSEL encoding for import and exporting GEDCOM files.
* Fixed a bug in the selection of parents, which did not accept new parents
if previous parents did not exist.
Version 0.1.2
* Allow the user the option to display alternate names in the person
list. Alternate names in the list have an '*' appended to the end
of the name.
* Merge function now gives the user the option of saving the name of
the merged individual as an alternate name if the names are not
the same.
* Added the "Alternate Birth" and "Alternate Death" to the event list,
to allow other birthdates to be recorded. Gramps makes a distinction
between the birthdate/deathdate and the alternates.
* GEDCOM import and export adapted to load/save alternate birth and
death dates. The first "BIRT" and "DEAT" tags are the ones used
for the primary dates, the others are loaded as alternates.
* Added the ability to store web page addresses for each person. From
the edit person page, the "Go" button brings up a web browser to
display the page.
* Fixed a bug in the relationship calculator that caused a traceback
when the person selected was a direct ancestor of the active person.
* Added the suffix field to the alternate name entry on the Edit Person
form.

17
gramps/README Normal file
View File

@@ -0,0 +1,17 @@
Please read the COPYING file first.
Requirements
--------------------------------
Python 1.5.2
Gnome 1.2 (included in Helix Gnome)
PyGnome 1.0.53 (included in Helix Gnome)
PyXML 0.6.2 (http://sourceforge.net/project/showfiles.php?group_id=6473)
--------------------------------
Donald Allingham
donaldallingham@home.com

21
gramps/TODO Normal file
View File

@@ -0,0 +1,21 @@
* More complete GEDCOM import and export. The current GEDCOM parse is
regular expression based, and not to sophisticated. It probably won't
take much to confuse it badly.
* Dates do not understand the concept of between
* Dates do not understand alternate calendars
* The GUI interface is not clean or consistant. It needs a considerable
amount of work.
* There are no sophisticated functions at all yet, such as merging of
databases or finding duplicate people.
* There are no logic rules yet, such as warning if a parent's birthday
is after a child's.
* I'm not happy with the mechanism for the selection of alternate parents.
It works, but is extremely clumsy and non-intuitive
* OpenOffice zip file is not handled very gracefully. Uses the "system"
call to generate the zip file using the hard coded path of /usr/bin/zip.
Python 2.0 provides a zip interface, so this may need to hold off until
the move is made to Python 2.0.
* Really need a generic OutputFormat class, that can be reused in all the
report generators. Derived classes can target OpenOffice, HTML, LaTeX,
KOffice, AbiWord, etc.
* And a whole lot more....

1104
gramps/configure vendored Executable file

File diff suppressed because it is too large Load Diff

113
gramps/configure.in Normal file
View File

@@ -0,0 +1,113 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/gramps.py)
dnl Checks for programs.
PACKAGE=gramps
AC_PATH_PROG(PYTHON, python)
AC_PATH_PROG(ZIP, zip)
AC_SUBST(PYTHON)
AC_SUBST(PACKAGE)
AC_PROG_INSTALL
AC_PROG_MAKE_SET
dnl Check for programs
AC_CHECK_PROG(HAVE_GNOME_CONFIG, gnome-config, "YES", "NO")
dnl Check if python bindings for gtk are installed
AC_MSG_CHECKING(Python bindings for sax/xml)
changequote(,)
cat > conftest.py <<EOF
try:
from xml.sax import saxexts, saxlib, saxutils
f = open("conftest.out", "w")
f.write("YES")
f.close()
except ImportError:
f = open("conftest.out", "w")
f.write("NO")
f.close()
EOF
changequote([, ])
$PYTHON conftest.py
has_sax=`cat conftest.out`
rm -f conftest.out conftest.py
if test "YES" != $has_sax
then
AC_MSG_ERROR([
**** The python interpreter can't find the SAX/XML bindings.])
fi
AC_MSG_RESULT(ok)
AC_MSG_CHECKING(Python bindings for gtk+)
changequote(,)
cat > conftest.py <<EOF
try:
import gtk
f = open("conftest.out", "w")
f.write("YES")
f.close()
except ImportError:
f = open("conftest.out", "w")
f.write("NO")
f.close()
EOF
changequote([, ])
$PYTHON conftest.py
has_pygtk=`cat conftest.out`
rm -f conftest.out conftest.py
if test "YES" != $has_pygtk
then
AC_MSG_ERROR([
**** The python interpreter can't find the python bindings for gtk.])
fi
AC_MSG_RESULT(ok)
AC_MSG_CHECKING(Python bindings for GNOME)
changequote(,)
cat > conftest.py <<EOF
try:
import gnome, gnome.ui, gnome.xmhtml
f = open("conftest.out", "w")
f.write("YES")
f.close()
except ImportError:
f = open("conftest.out", "w")
f.write("NO")
f.close()
EOF
changequote([, ])
$PYTHON conftest.py
has_pygnome=`cat conftest.out`
rm -f conftest.out conftest.py
if test "YES" != $has_pygnome
then
AC_MSG_ERROR([
**** The python interpreter can't find the python bindings for GNOME.])
fi
AC_MSG_RESULT(ok)
dnl Checks for libraries.
dnl Checks for header files.
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Checks for library functions.
AC_OUTPUT(Makefile \
src/Makefile\
src/plugins/Makefile\
src/filters/Makefile\
src/data/Makefile\
gramps.sh)

533
gramps/doc/gramps.sgml Normal file
View File

@@ -0,0 +1,533 @@
<!DOCTYPE article PUBLIC "-//GNOME//DTD DocBook PNG Variant V1.1//EN"[
<!-- if not using PNG graphic, replace reference above with
.....PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[
-->
<!ENTITY version "0.1.0"> <!-- replace with application version -->
]>
<!--
This is a GNOME documentation template, designed by the GNOME
Documentation Project Team. Please use it for writing GNOME
documentation, making obvious changes. In particular, all the words
written in UPPERCASE (with the exception of GNOME) should be
replaced. As for "legalnotice", please leave the reference
unchanged.
Remember that this is a guide, rather than a perfect model to follow
slavishly. Make your manual logical and readable. And don't forget
to remove these comments in your final documentation! ;-)
-->
<!--
(Do not remove this comment block.)
Maintained by the GNOME Documentation Project
http://developer.gnome.org/projects/gdp
Template version: 1.0.3
Template last modified: Nov 16, 2000
-->
<!-- =============Document Header ============================= -->
<article id="index"> <!-- please do not change the id -->
<artheader>
<title>GRAMPS User Manual</title>
<copyright>
<year>2001</year>
<holder>Donald N. Allingham</holder>
</copyright>
<!-- translators: uncomment this:
<copyright>
<year>2000</year>
<holder>ME-THE-TRANSLATOR (Latin translation)</holder>
</copyright>
-->
<!-- do not put authorname in the header except in copyright - use
section "authors" below -->
<!-- Use this legal notice for online documents which depend on -->
<!-- core GNOME packages. -->
<legalnotice id="legalnotice">
<para>
Permission is granted to copy, distribute and/or modify this document
under the terms of the <ulink type="help"
url="gnome-help:fdl"><citetitle>GNU Free Documentation
License</citetitle></ulink>, Version 1.1 or any later version
published by the Free Software Foundation with no Invariant Sections,
no Front-Cover Texts, and no Back-Cover Texts. A copy of the license
can be found <ulink type="help" url="gnome-help:fdl">here</ulink>.
</para>
<para>
Many of the names used by companies to distinguish their products and
services are claimed as trademarks. Where those names appear in any
GNOME documentation, and those trademarks are made aware to the members
of the GNOME Documentation Project, the names have been printed in caps
or initial caps.
</para>
</legalnotice>
<!-- Use this legal notice for documents which are placed on -->
<!-- the web, shipped in any way other than online documents -->
<!-- (eg. PS, PDF, or RTF), or which do not depend on the -->
<!-- core GNOME distribution. -->
<!-- -->
<!-- If you use this version, you must place the following -->
<!-- line in the document declaration at the top of your -->
<!-- document: -->
<!-- <!ENTITY FDL SYSTEM "fdl.sgml"> -->
<!-- and the following line at the bottom of your document -->
<!-- after the last </sect1>. -->
<!-- &FDL; -->
<!--
<legalnotice id="legalnotice">
<para>
Permission is granted to copy, distribute and/or modify this document
under the terms of the <link linkend="fdl"><citetitle>GNU
Free Documentation License</citetitle></link>, Version 1.1 or any later
version published by the Free Software Foundation with no Invariant
Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the
license can be found in <xref linkend="fdl">.
</para>
<para>
Many of the names used by companies to distinguish their products and
services are claimed as trademarks. Where those names appear in any
GNOME documentation, and those trademarks are made aware to the members
of the GNOME Documentation Project, the names have been printed in caps
or initial caps.
</para>
</legalnotice>
-->
<!-- This is the manual version, not application version. -->
<releaseinfo>
This is version 1.0 of GRAMPS manual.
</releaseinfo>
</artheader>
<!-- ============= Document Body ============================= -->
<!-- ============= Introduction ============================== -->
<sect1 id="intro">
<title>Introduction</title>
<para>
GRAMPS is an acronym for the Genealogical Research and Analysis
Management Programming System. It was conceived under the concept
that most genealogy programs were designed to provide the
researcher the capability to input information related to a
particular family tree. Most of these programs have allowed for
the arranging and storing of information consistent with the
GEDCOM standards. They usually provide a means for displaying
descendant or ancestral relationships by means of graphical
displays, charts, or reports. These may be augmented with
pictures or other media to enhance the data. Most provide for
inputting data on unconnected individuals/families that may or may
not have a relationship to the primary surname being researched.
Various other enhancements may also be provided in the
genealogical program that allows for different degrees of
importing and exporting data from other programs and printing of
the data contained in the various reports. GRAMPS, on the other
hand, attempts to provide all of the common capabilities of these
programs, but, more importantly, to provide a capability not
common to these programs. This is the ability to input any bits
and pieces of information directly into GRAMPS and
rearrange/manipulate any/all 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. In short, a tool that provides a way to input
all your research into one place and do your analysis and
correlation using the speed, power, and accuracy of your computer
instead of pencils and unmanageable reams of paper.
</para>
<para>
To run <application>GRAMPS</application>, select
<menuchoice>
<guisubmenu>Programs</guisubmenu>
<guisubmenu>Applications</guisubmenu>
<guimenuitem>gramps</guimenuitem>
</menuchoice>
from the <guimenu>Main Menu</guimenu>, or type
<command>gramps</command> on the command line.
</para>
<para>
<application>GRAMPS</application> is included in the
<filename>gramps</filename> package, which is part of the
GNOME desktop environment. This document describes version
&version; of <application>GRAMPS</application>.
</para>
</sect1>
<!-- ================ Usage ================================ -->
<!-- This section should describe basic usage of the application. -->
<sect1 id="usage">
<title>Using GRAMPS</title>
<para>
<application>GRAMPS</application> is a genealogy program.
This section describes basic usage of
<application>GRAMPS</application>.
</para>
<!-- ========= Basic Usage =========================== -->
<sect2 id="mainwin">
<title>Person List</title>
<para>
Starting <application>GRAMPS</application> opens the
<interface>Main window</interface>, shown in <xref
linkend="mainwindow-fig">. The window is at first empty.
<!-- ==== Figure ==== -->
<figure id="mainwindow-fig">
<title>GRAMPS Main Window</title>
<screenshot>
<screeninfo>GRAMPS Main Window</screeninfo>
<graphic fileref="mainwin" format="PNG" srccredit="Don Allingham">
</graphic>
</screenshot>
</figure>
<!-- ==== End of Figure ==== -->
</para>
</sect2>
<sect2 id="familyview">
<title>Family View</title>
<para>
</para>
</sect2>
<sect2 id="pedegreeview">
<title>Pedegree View</title>
<para>
</para>
</sect2>
<sect2 id="enteringdata">
<title>Entering data</title>
<para>
</para>
</sect2>
</sect1>
<!-- ============= Customization ============================= -->
<sect1 id="prefs">
<title>Customization</title>
<para>
To change the application settings, select
<menuchoice>
<guimenu>Settings</guimenu>
<guimenuitem>Preferences...</guimenuitem>
</menuchoice>. This opens the
<interface>Preferences</interface> dialog, shown in <xref
linkend="preferences-fig">.
</para>
<figure id="preferences-fig">
<title>Preferences Dialog</title>
<screenshot>
<screeninfo>Preferences Dialog</screeninfo>
<graphic fileref="preferences" format="png" srccredit="Don Allingham">
</graphic>
</screenshot>
</figure>
<para>
</para>
</sect1>
<!-- ============= Writing Filters ============================= -->
<sect1 id="writingfilters">
<title>Writing Filters</title>
<para>
Users can create their own filters and add them to
<application>GRAMPS</application>. By adding the filter to the
user's private filter directory
(<filename class="directory">~/.gramps/filters</filename>),
the filter will be automatically
recognized the next time that the program is started.
</para>
<sect2 id="createfilter">
<title>Creating a filter</title>
<para>
Filters are written in the <application>python</application>
language. Each filter is initialized with the qualifier string.
The qualifier string passes an additional text string to the
filter. This string can be used to further qualify the filter.
For example, if the filter is used to match names, the qualifier
would be used to provide the name that is being compared against.
</para>
<para>
Each filter is a python class, and should be in its own separate
module (file). The module should consist of the filter class
definition, and two functions &mdash; <function>create</function>,
and <function>need_qualifier</function>.
</para>
<para>
The <function>create</function> function takes a string as its
only argument, returns a instance of the filter class. The string
argument is the qualifier string used to provide more specific
information.
</para>
<para>
The <function>need_qualifier</function> function takes no
arguments, and returns either a 0 or 1 to indicate if a qualifier
string is needed by the filter. Regardless of what
<function>need_qualifier</function> indicates, a text string is
always passed to the filter and the <function>create</function>
function. The value returned by
<function>need_qualifier</function> indicates to the program
whether or not the qualifier field in the display should be
enabled or disabled.
</para>
<para>
The module documentation string (a text string as the first
statement in the module) is used for the description of the
module. This is the description that gets entered into filter
selection menus.
</para>
<para>
All filters must be derived from the
<function>Filter.Filter</function> class. The
<function>__init__</function> task may be overridden, but if so,
should call the <function>__init__</function> function on the
<function>Filter.Filter</function> class. The parent class
provides the variable <function>self.text</function>, which
contains the text string passed as the qualifier.
</para>
<para>
All filter classes must define a <function>match</function>
function. The function takes one argument (other than
<function>self</function>), which is an object of type
<function>Person</function> to compare against. The function
should return a 1 if the person matches the filter, or a zero if
the person does not.
</para>
<figure id="filtersrc">
<title>Sample filter implementation</title>
<programlisting>
"Names that contain a substring"
import Filter
import string
class SubString(Filter.Filter):
"Names that contain a substring"
def match(self,person):
name = person.getPrimaryName().getName()
return string.find(name,self.text) >= 0
def create(text):
return SubString(text)
def need_qualifier():
return 1
</programlisting>
</figure>
</sect2>
</sect1>
<!-- ============= Writing Reports ============================= -->
<sect1 id="writingreports">
<title>Writing Reports</title>
<para>
Users can create their own report generators and add them to
<application>GRAMPS</application>. By adding the report generator
to the user's private filter directory (<filename
class="directory">~/.gramps/plugins</filename>), the report
generator filter will be automatically recognized the next time
that the program is started.
</para>
<sect2 id="createreport">
<title>Creating a report generator</title>
<para>
Like filters, report generators are written in the
<application>python</application> language. Fewer restrictions
are made on report generators than on filters. The report
generator is passed the current <application>GRAMPS</application>
database and the active person. The generator needs to take
special care to make sure that it does not alter the database in
anyway.
</para>
<para>
The python documentation string (the first text string and first
statement) of the module is used to name the report generator. The
string consists of two parts, separated by a forward slash. The
first part of the string is the category of the report
generator. <application>GRAMPS</application> uses this part to
group similar reports together in the interface. The second part
of the string is the actual name of the reprot generator, and will
be displayed in the report menu.
</para>
<para>
A report generator module must supply the
<function>report</function> function, and can optionally define
the <function>get_description</function> and
<function>get_xpm_data</function> functions. The
<function>report</function> takes two arguments &mdash; a database
(of type <function>RelDataBase</function>) and the currently
selected person (of type <function>Person</function>). The
<function>report</function> is reponsible for generating the
actual report.
</para>
<para>
If the <function>get_description</function> is defined, it is used
to provide a more detailed description of the report. The
description is used to provide the user with more information in
the report selection window. The function takes no arguments, and
should return a text string.
</para>
<para>
If the <function>get_xpm_data</function> is defined, it is used to
provide an graphic logo for the report in the report selection
window. The function takes no arguments, and should return a list
of strings containing the XPM file data. The XPM image should be
48x48 pixels in size.
</para>
<figure id="reportsrc">
<title>Sample report implementation</title>
<programlisting>
"Category/report name"
def report(database,person):
... actual code ...
def get_description():
return "A detailed text description of what the report generator does"
def get_xpm_image():
return [
"... XPM image data"
]
</programlisting>
</figure>
</sect2>
</sect1>
<!-- ============= Writing Tools ============================= -->
<sect1 id="writingtools">
<title>Writing Tools</title>
<para>
</para>
</sect1>
<!-- ============= Various Sections ============================= -->
<!-- Here you should add, if necessary, several more sect1's,
describing other windows (besides the main one), file formats,
preferences dialogs, etc. as appropriate. Try not to make any of
these sections too long. -->
<!-- ============= Bugs ================================== -->
<!-- This section should describe known bugs and limitations of
the program if there are any - please be frank and list all
problems you know of. -->
<sect1 id="bugs">
<title>Known Bugs and Limitations</title>
<para>
This application has no known bugs.
</para>
</sect1>
<!-- ============= Authors ================================ -->
<sect1 id="authors">
<title>Authors</title>
<para>
<application>GRAMPS</application> was written by Donald N. Allingham
(<email>donaldallingham@home.com</email>). To find more information about
<application>GRAMPS</application>, please visit the <ulink
url="http://gramps.sourceforge.net" type="http">GRAMPS Web
page</ulink>. Please send all comments, suggestions, and bug
reports to the <ulink url="http://bugs.gnome.org" type="http">GNOME
bug tracking database</ulink>. (Instructions for submitting bug
reports can be found <ulink
url="http://bugs.gnome.org/Reporting.html" type="http">
on-line</ulink>.) You can also use <application>Bug Report
Tool</application> (<command>bug-buddy</command>), available in the
<guisubmenu>Utilities</guisubmenu> submenu of <guimenu>Main
Menu</guimenu>, for submitting bug reports.
</para>
<para>
This manual was written by Donald N. Allingham
(<email>donaldallingham@home.com</email>) and Lawrence L. Allingham
(<email>llkla@erinet.com</email>).
</para>
<!-- For translations: uncomment this:
<para>
Latin translation was done by ME
(<email>MYNAME@MYADDRESS</email>). Please send all comments and
suggestions regarding this translation to SOMEWHERE.
</para>
-->
</sect1>
<!-- ============= Application License ============================= -->
<sect1 id="license">
<title>License</title>
<para>
This program is free software; you can redistribute it and/or
modify it under the terms of the <ulink type="help" url="gnome-help:gpl">
<citetitle>GNU General Public License</citetitle></ulink> as
published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later
version.
</para>
<para>
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
<citetitle>GNU General Public License</citetitle> for more details.
</para>
<para>
A copy of the <citetitle>GNU General Public License</citetitle> is
included as an appendix to the <citetitle>GNOME Users
Guide</citetitle>. You may also obtain a copy of the
<citetitle>GNU General Public License</citetitle> from the Free
Software Foundation by visiting <ulink type="http"
url="http://www.fsf.org">their Web site</ulink> or by writing to
<address>
Free Software Foundation, Inc.
<street>59 Temple Place</street> - Suite 330
<city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>
<country>USA</country>
</address>
</para>
</sect1>
</article>

10
gramps/gramps.sh.in Normal file
View File

@@ -0,0 +1,10 @@
#! /bin/sh
# @configure_input@
prefix=@prefix@
PYTHONPATH=@datadir@/@PACKAGE@
export PYTHONPATH
GRAMPSI18N=@prefix@/share/locale
export GRAMPSI18N
@PYTHON@ @datadir@/@PACKAGE@/gramps.py $*

62
gramps/gramps.spec Normal file
View File

@@ -0,0 +1,62 @@
%define ver 0.1.3
%define rel 1
%define prefix /usr
Summary: Genealogical Research and Analysis Management Programming System.
Name: gramps
Version: %ver
Release: %rel
Copyright: GPL
Group: Applications/Genealogy
Source: http://download.sourceforge.net/gramps/gramps-%{ver}.tar.gz
BuildRoot: /var/tmp/%{name}-%{version}-root
URL: http://gramps.sourceforge.net
Requires: python >= 1.5.2
Requires: pygnome >= 1.0.53
Requires: PyXML
%description
GRAMPS is an acronym for the Genealogical Research and Analysis
Management Programming System. It was conceived under the concept
that most genealogy programs were designed to provide the
researcher the capability to input information related to a
particular family tree.
%prep
%setup
%build
if [ ! -f configure ]; then
CFLAGS="$MYCFLAGS" ./autogen.sh $MYARCH_FLAGS --prefix=%prefix
else
CFLAGS="$MYCFLAGS" ./configure $MYARCH_FLAGS --prefix=%prefix
fi
make
%install
rm -rf $RPM_BUILD_ROOT
make GNOME_DATADIR=$RPM_BUILD_ROOT%{prefix}/share prefix=$RPM_BUILD_ROOT%{prefix} install
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-, root, root)
%doc README COPYING TODO
%{prefix}/bin/gramps
%{prefix}/share/gnome/apps/Applications/gramps.desktop
%{prefix}/share/pixmaps/gramps.png
# %{prefix}/share/gramps/*
%{prefix}/share/locale/*/LC_MESSAGES/gramps.mo
%{prefix}/share/gramps/*.pyo
%{prefix}/share/gramps/*.glade
%{prefix}/share/gramps/*.sxw
%{prefix}/share/gramps/*.xpm
%{prefix}/share/gramps/*.jpg
%{prefix}/share/gramps/filters/*
%{prefix}/share/gramps/plugins/*

250
gramps/install-sh Normal file
View File

@@ -0,0 +1,250 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

68
gramps/py-compile Normal file
View File

@@ -0,0 +1,68 @@
#!/bin/sh
# called as "py-compile [--basedir DIR] PY_FILES ...
if [ -z "$PYTHON" ]; then
PYTHON=python
fi
basedir=
case "$1" in
--basedir)
basedir=$2
shift 2
;;
--help)
echo "Usage: py-compile [--basedir DIR] PY_FILES ..."
echo "Byte compile some python scripts. This should be performed"
echo "after they have been moved to the final installation location"
exit 0
;;
--version)
echo "py-compile version 0.0"
exit 0
;;
esac
if [ $# = 0 ]; then
echo "No files given to $0" 1>&2
exit 1
fi
# if basedir was given, then it should be prepended to filenames before
# byte compilation.
if [ -z "$basedir" ]; then
trans="path = file"
else
trans="path = os.path.join('$basedir', file)"
fi
$PYTHON -c "
import sys, os, string, py_compile
files = '''$*'''
print 'Byte-compiling python modules...'
for file in string.split(files):
$trans
if not os.path.exists(path) or not (len(path) >= 3 and path[-3:] == '.py'):
continue
print file,
sys.stdout.flush()
py_compile.compile(path)
print" || exit $?
# this will fail for python < 1.5, but that doesn't matter ...
$PYTHON -O -c "
import sys, os, string, py_compile
files = '''$*'''
print 'Byte-compiling python modules (optimised versions) ...'
for file in string.split(files):
$trans
if not os.path.exists(path) or not (len(path) >= 3 and path[-3:] == '.py'):
continue
print file,
sys.stdout.flush()
py_compile.compile(path)
print" 2>/dev/null || :

143
gramps/src/AbiWordDoc.py Normal file
View File

@@ -0,0 +1,143 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import os
import tempfile
from TextDoc import *
from latin_utf8 import latin_to_utf8
import const
class AbiWordDoc(TextDoc):
def __init__(self,type,orientation):
TextDoc.__init__(self,type,orientation)
self.f = None
self.level = 0
def open(self,filename):
if filename[-4:] != ".abw":
self.filename = filename + ".abw"
else:
self.filename = filename
self.f = open(filename,"w")
self.f.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
self.f.write('<abiword version="0.7.13" fileformat="1.0">\n')
self.f.write('<pagesize ')
if self.orientation == PAPER_US_LETTER:
self.f.write('pagetype="Letter" ')
else:
self.f.write('pagetype="A4" ')
if self.orientation == PAPER_PORTRAIT:
self.f.write('orientation="portrait" ')
else:
self.f.write('orientation="landscape" ')
self.f.write('width="%.4f" ' % (self.width/2.54))
self.f.write('height="%.4f" ' % (self.height/2.54))
self.f.write('units="inch" page-scale="1.000000"/>\n')
self.f.write('<section ')
rmargin = float(self.rmargin)/2.54
lmargin = float(self.lmargin)/2.54
self.f.write('props="page-margin-right:%.4fin; ' % rmargin)
self.f.write('page-margin-left:%.4fin"' % lmargin)
self.f.write('>\n')
def close(self):
self.f.write('</section>\n')
self.f.write('</abiword>\n')
self.f.close()
def start_paragraph(self,style_name):
style = self.style_list[style_name]
self.f.write('<p props="')
if style.get_alignment() == PARA_ALIGN_RIGHT:
self.f.write('text-align:right;')
elif style.get_alignment() == PARA_ALIGN_LEFT:
self.f.write('text-align:left;')
elif style.get_alignment() == PARA_ALIGN_CENTER:
self.f.write('text-align:center;')
else:
self.f.write('text-align:justify;')
rmargin = float(style.get_right_margin())/2.54
lmargin = float(style.get_left_margin())/2.54
indent = float(style.get_first_indent())/2.54
self.f.write(' margin-right:%.4fin;' % rmargin)
self.f.write(' margin-left:%.4fin;' % lmargin)
self.f.write(' text-indent:%.4fin' % indent)
self.f.write('">')
font = style.get_font()
self.f.write('<c props="font-family:')
if font.get_type_face() == FONT_SANS_SERIF:
self.f.write('Arial;')
else:
self.f.write('Times New Roman;')
self.f.write('font-size:' + str(font.get_size()) + 'pt')
if font.get_bold():
self.f.write('; font-weight:bold')
if font.get_italic():
self.f.write('; font-style:italic')
color = font.get_color()
if color != (0,0,0):
self.f.write('; color:%2x%2x%2x' % color)
if font.get_underline():
self.f.write('; text-decoration:underline' % color)
self.f.write('">')
def end_paragraph(self):
self.f.write('</c></p>\n')
def write_text(self,text):
self.f.write(text)
if __name__ == "__main__":
doc = AbiWordDoc(PAPER_US_LETTER,PAPER_PORTRAIT)
foo = FontStyle()
foo.set_type_face(FONT_SANS_SERIF)
foo.set_color((255,0,0))
foo.set_size(24)
para = ParagraphStyle()
para.set_font(foo)
para.set_alignment(PARA_ALIGN_RIGHT)
doc.add_style("MyTitle",para)
para = ParagraphStyle()
para.set_left_margin(1)
para.set_right_margin(1)
para.set_alignment(PARA_ALIGN_JUSTIFY)
doc.add_style("Normal",para)
doc.open("/home/dona/oo_test.abw")
doc.start_paragraph("MyTitle")
doc.write_text("This is my Title")
doc.end_paragraph()
doc.start_paragraph("Normal")
doc.write_text("This is a test of the emergency broadcast system. ")
doc.write_text("This is a only a test. Repeat. This is only a test. ")
doc.write_text("Had this been an actual emergency, we would not be here ")
doc.write_text("to give you this message.")
doc.end_paragraph()
doc.close()

222
gramps/src/Bookmarks.py Normal file
View File

@@ -0,0 +1,222 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Handle bookmarks for the gramps interface"
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
import libglade
#-------------------------------------------------------------------------
#
# Local modules
#
#-------------------------------------------------------------------------
import const
import utils
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
OBJECT = "o"
ROWS = "r"
INDEX = "i"
TOPINST = "top"
NAMEINST = "namelist"
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Bookmarks :
"Handle the bookmarks interface for Gramps"
#---------------------------------------------------------------------
#
# __init__ - Creates a the bookmark editor
#
#---------------------------------------------------------------------
def __init__(self,bookmarks,map,menu,callback):
self.map = map
self.menu = menu
self.bookmarks = bookmarks
self.callback = callback
self.redraw()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def redraw(self):
if len(self.bookmarks) > 0:
self.myMenu = gtk.GtkMenu()
for person in self.bookmarks:
item = gtk.GtkMenuItem(person.getPrimaryName().getName())
item.show()
item.connect("activate", self.callback , person)
self.myMenu.append(item)
self.menu.set_submenu(self.myMenu)
self.menu.set_sensitive(1)
else:
self.menu.remove_submenu()
self.menu.set_sensitive(0)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def add(self,person):
if person not in self.bookmarks:
utils.modified()
self.bookmarks.append(person)
item = gtk.GtkMenuItem(person.getPrimaryName().getName())
item.show()
item.connect("activate", self.callback, person)
self.redraw()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def edit(self):
top = libglade.GladeXML(const.bookFile,TOPINST)
namelist = top.get_widget(NAMEINST)
namelist.clear()
self.index = 0
for val in self.bookmarks:
namelist.append([val.getPrimaryName().getName()])
namelist.set_row_data(self.index,val)
self.index = self.index + 1
if self.index > 0:
namelist.select_row(0,0)
namelist.set_data(INDEX,0)
else:
namelist.set_data(INDEX,-1)
namelist.set_data(ROWS,self.index)
top.signal_autoconnect({
"on_ok_clicked" : on_ok_clicked,
"on_down_clicked" : on_down_clicked,
"on_up_clicked" : on_up_clicked,
"on_namelist_select_row" : on_namelist_select_row,
"on_delete_clicked" : on_delete_clicked,
"on_cancel_clicked" : on_cancel_clicked
})
topBox = top.get_widget(TOPINST)
topBox.set_data(OBJECT,self)
topBox.set_data(NAMEINST,namelist)
topBox.show()
self.redraw()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_namelist_select_row(obj,row,junk,junk2):
obj.set_data(INDEX,row)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_delete_clicked(obj):
index = obj.get_data(INDEX)
rows = obj.get_data(ROWS)
if index >= 0:
obj.remove(index)
obj.set_data(ROWS,rows-1)
if index != 0:
obj.select_row(0,0)
else:
obj.unselect_all()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_up_clicked(obj):
index = obj.get_data(INDEX)
if index > 0:
obj.swap_rows(index-1,index)
obj.set_data(INDEX,index-1)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_down_clicked(obj):
index = obj.get_data(INDEX)
rows = obj.get_data(ROWS)
if index != rows-1:
obj.swap_rows(index+1,index)
obj.set_data(INDEX,index+1)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
bmobj = obj.get_data(OBJECT)
namelist = obj.get_data(NAMEINST)
del bmobj.bookmarks[0:]
bmobj.myMenu = gtk.GtkMenu()
for index in range(0,bmobj.index):
person = namelist.get_row_data(index)
if person == None:
break
bmobj.bookmarks.append(person)
item = gtk.GtkMenuItem(person.getPrimaryName().getName())
item.show()
item.connect("activate", bmobj.callback , person)
bmobj.myMenu.append(item)
bmobj.menu.set_submenu(bmobj.myMenu)
bmobj.redraw()
obj.destroy()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_cancel_clicked(obj):
obj.destroy()

494
gramps/src/Config.py Normal file
View File

@@ -0,0 +1,494 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
import sys
import string
import re
import os
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gtk import *
from gnome.ui import *
import GTK
import gnome.config
import gnome.help
import libglade
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
from RelLib import *
import Researcher
import const
import utils
import ListColors
import intl
_ = intl.gettext
_date_format_list = [
"Month Day, Year",
"MON Day, Year",
"Day MON Year",
"MM/DD/YY",
"MM-DD-YY",
"DD/MM/YY",
"DD-MM-YY"
]
_date_entry_list = [
"MM/DD/YY",
"DD/MM/YY"
]
_name_format_list = [
(_("Firstname Surname"), utils.normal_name),
(_("Surname, Firstname"), utils.phonebook_name),
]
#-------------------------------------------------------------------------
#
# Visible globals
#
#-------------------------------------------------------------------------
owner = Researcher.Researcher()
autoload = 0
usetabs = 0
hide_altnames = 0
lastfile = None
nameof = utils.normal_name
#-------------------------------------------------------------------------
#
# Globals
#
#-------------------------------------------------------------------------
_name_format = 0
_callback = None
_druid = None
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
ODDFGCOLOR = "oddForeground"
ODDBGCOLOR = "oddBackground"
EVENFGCOLOR = "evenForeground"
EVENBGCOLOR = "evenBackground"
#-------------------------------------------------------------------------
#
# make_path -
# Creates a directory if it does not already exist. Assumes that the
# parent directory already exits
#
#-------------------------------------------------------------------------
def make_path(path):
if not os.path.isdir(path):
os.mkdir(path)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def loadConfig(call):
global autoload
global owner
global usetabs
global hide_altnames
global lastfile
global nameof
global _druid
global _name_format
global _callback
_callback = call
lastfile = gnome.config.get_string("/gramps/data/LastFile")
usetabs = gnome.config.get_bool("/gramps/config/UseTabs")
hide_altnames = gnome.config.get_bool("/gramps/config/DisplayAltNames")
autoload = gnome.config.get_bool("/gramps/config/autoLoad")
dateFormat = gnome.config.get_int("/gramps/config/dateFormat")
dateEntry = gnome.config.get_int("/gramps/config/dateEntry")
_name_format = gnome.config.get_int("/gramps/config/nameFormat")
name = gnome.config.get_string("/gramps/researcher/name")
addr = gnome.config.get_string("/gramps/researcher/addr")
city = gnome.config.get_string("/gramps/researcher/city")
state = gnome.config.get_string("/gramps/researcher/state")
country = gnome.config.get_string("/gramps/researcher/country")
postal = gnome.config.get_string("/gramps/researcher/postal")
phone = gnome.config.get_string("/gramps/researcher/phone")
email = gnome.config.get_string("/gramps/researcher/email")
ListColors.enable = gnome.config.get_bool("/gramps/color/enableColors")
if ListColors.enable == None:
ListColors.enable = 0
ListColors.oddfg = get_config_color(ODDFGCOLOR,(0,0,0))
ListColors.oddbg = get_config_color(ODDBGCOLOR,(0xffff,0xffff,0xffff))
ListColors.evenfg = get_config_color(EVENFGCOLOR,(0,0,0))
ListColors.evenbg = get_config_color(EVENBGCOLOR,(0xffff,0xffff,0xffff))
if autoload == None:
autoload = 1
if usetabs == None:
usetabs = 0
if hide_altnames == None:
hide_altnames = 0
if dateFormat == None:
dateFormat = 0
if dateEntry == None:
dateEntry = 0
Date.formatCode = dateFormat
Date.entryCode = dateEntry
if _name_format == None or _name_format == 0:
_name_format = 0
nameof = utils.normal_name
else:
nameof = utils.phonebook_name
if name == None:
_druid = libglade.GladeXML(const.configFile,"initDruid")
_druid.signal_autoconnect({
"destroy_passed_object" : druid_cancel_clicked,
"on_initDruid_finish" : on_initDruid_finish
})
else:
owner.set(name,addr,city,state,country,postal,phone,email)
make_path(os.path.expanduser("~/.gramps"))
make_path(os.path.expanduser("~/.gramps/filters"))
make_path(os.path.expanduser("~/.gramps/plugins"))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def save_last_file(file):
gnome.config.set_string("/gramps/data/LastFile",file)
gnome.config.sync()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_initDruid_finish(obj,b):
global owner
name = _druid.get_widget("dresname").get_text()
addr = _druid.get_widget("dresaddr").get_text()
city = _druid.get_widget("drescity").get_text()
state = _druid.get_widget("dresstate").get_text()
country = _druid.get_widget("drescountry").get_text()
postal = _druid.get_widget("drespostal").get_text()
phone = _druid.get_widget("dresphone").get_text()
email = _druid.get_widget("dresemail").get_text()
owner.set(name,addr,city,state,country,postal,phone,email)
store_researcher(owner)
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def store_researcher(res):
gnome.config.set_string("/gramps/researcher/name",res.name)
gnome.config.set_string("/gramps/researcher/addr",res.addr)
gnome.config.set_string("/gramps/researcher/city",res.city)
gnome.config.set_string("/gramps/researcher/state",res.state)
gnome.config.set_string("/gramps/researcher/country",res.country)
gnome.config.set_string("/gramps/researcher/postal",res.postal)
gnome.config.set_string("/gramps/researcher/phone",res.phone)
gnome.config.set_string("/gramps/researcher/email",res.email)
gnome.config.sync()
#-------------------------------------------------------------------------
#
# Apply values set in the property box. For simplicity, only apply the
# values when the page is -1 (the box has been closed).
#
#-------------------------------------------------------------------------
def on_propertybox_apply(obj,page):
global nameof
global owner
global usetabs
global hide_altnames
if page != -1:
return
autoload = prefsTop.get_widget("autoload").get_active()
usetabs = prefsTop.get_widget("usetabs").get_active()
hide_altnames = prefsTop.get_widget("display_altnames").get_active()
gnome.config.set_bool("/gramps/config/UseTabs",usetabs)
gnome.config.set_bool("/gramps/config/autoLoad",autoload)
gnome.config.set_bool("/gramps/config/DisplayAltNames",hide_altnames)
# search for the active date format selection
format_menu = prefsTop.get_widget("date_format").get_menu()
active = format_menu.get_active().get_data("i")
Date.formatCode = active
gnome.config.set_int("/gramps/config/dateFormat",active)
format_menu = prefsTop.get_widget("date_entry_format").get_menu()
entry_active = format_menu.get_active().get_data("i")
Date.entryCode = entry_active
gnome.config.set_int("/gramps/config/dateEntry",entry_active)
# get the name format
format_menu = prefsTop.get_widget("name_format").get_menu()
active_name = format_menu.get_active().get_data("i")
name_tuple = _name_format_list[active_name]
nameof = name_tuple[1]
gnome.config.set_int("/gramps/config/nameFormat",active_name)
name = prefsTop.get_widget("resname").get_text()
addr = prefsTop.get_widget("resaddr").get_text()
city = prefsTop.get_widget("rescity").get_text()
state = prefsTop.get_widget("resstate").get_text()
country = prefsTop.get_widget("rescountry").get_text()
postal = prefsTop.get_widget("respostal").get_text()
phone = prefsTop.get_widget("resphone").get_text()
email = prefsTop.get_widget("resemail").get_text()
ListColors.enable = prefsTop.get_widget("enableColors").get_active()
gnome.config.set_bool("/gramps/color/enableColors",ListColors.enable)
ListColors.oddfg = prefsTop.get_widget(ODDFGCOLOR).get_i16()
ListColors.oddbg = prefsTop.get_widget(ODDBGCOLOR).get_i16()
ListColors.evenfg = prefsTop.get_widget(EVENFGCOLOR).get_i16()
ListColors.evenbg = prefsTop.get_widget(EVENBGCOLOR).get_i16()
save_config_color(ODDFGCOLOR,ListColors.oddfg)
save_config_color(ODDBGCOLOR,ListColors.oddbg)
save_config_color(EVENFGCOLOR,ListColors.evenfg)
save_config_color(EVENBGCOLOR,ListColors.evenbg)
owner.set(name,addr,city,state,country,postal,phone,email)
store_researcher(owner)
# update the config file
gnome.config.sync()
_callback()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def save_config_color(name,color):
gnome.config.set_int("/gramps/color/" + name + ".r",color[0])
gnome.config.set_int("/gramps/color/" + name + ".g",color[1])
gnome.config.set_int("/gramps/color/" + name + ".b",color[2])
#-------------------------------------------------------------------------
#
# Called by the elements on the property box to set the changed flag,
# so that the property box knows to set the Apply button
#
#-------------------------------------------------------------------------
def on_object_toggled(obj):
obj.changed()
#-------------------------------------------------------------------------
#
# Called by the elements on the property box to set the changed flag,
# so that the property box knows to set the Apply button
#
#-------------------------------------------------------------------------
def on_format_toggled(obj):
obj.get_data("o").changed()
#-------------------------------------------------------------------------
#
# Called by the elements on the property box to set the changed flag,
# so that the property box knows to set the Apply button
#
#-------------------------------------------------------------------------
def on_color_toggled(obj):
active = prefsTop.get_widget("enableColors").get_active()
prefsTop.get_widget(ODDFGCOLOR).set_sensitive(active)
prefsTop.get_widget(ODDBGCOLOR).set_sensitive(active)
prefsTop.get_widget(EVENFGCOLOR).set_sensitive(active)
prefsTop.get_widget(EVENBGCOLOR).set_sensitive(active)
obj.changed()
#-------------------------------------------------------------------------
#
# Called by the elements on the property box to set the changed flag,
# so that the property box knows to set the Apply button
#
#-------------------------------------------------------------------------
def on_color_set(obj,r,g,b,a):
obj.changed()
#-------------------------------------------------------------------------
#
# Create the property box, and set the elements off the current values
#
#-------------------------------------------------------------------------
def display_preferences_box():
global prefsTop
prefsTop = libglade.GladeXML(const.configFile,"propertybox")
prefsTop.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_propertybox_apply" : on_propertybox_apply,
"on_color_toggled" : on_color_toggled,
"on_color_set" : on_color_set,
"on_object_toggled" : on_object_toggled
})
pbox = prefsTop.get_widget("propertybox")
auto = prefsTop.get_widget("autoload")
tabs = prefsTop.get_widget("usetabs")
display_altnames = prefsTop.get_widget("display_altnames")
auto.set_active(autoload)
tabs.set_active(usetabs)
display_altnames.set_active(hide_altnames)
date_option = prefsTop.get_widget("date_format")
date_menu = GtkMenu()
for index in range(0,len(_date_format_list)):
item = GtkMenuItem(_date_format_list[index])
item.set_data("i",index)
item.set_data("o",pbox)
item.connect("activate", on_format_toggled)
item.show()
date_menu.append(item)
date_menu.set_active(Date.formatCode)
date_option.set_menu(date_menu)
date_entry = prefsTop.get_widget("date_entry_format")
date_menu = GtkMenu()
for index in range(0,len(_date_entry_list)):
item = GtkMenuItem(_date_entry_list[index])
item.set_data("i",index)
item.set_data("o",pbox)
item.connect("activate", on_format_toggled)
item.show()
date_menu.append(item)
date_menu.set_active(Date.entryCode)
date_entry.set_menu(date_menu)
name_option = prefsTop.get_widget("name_format")
name_menu = GtkMenu()
for index in range(0,len(_name_format_list)):
name_tuple = _name_format_list[index]
item = GtkMenuItem(name_tuple[0])
item.set_data("i",index)
item.set_data("o",pbox)
item.connect("activate", on_format_toggled)
item.show()
name_menu.append(item)
name_menu.set_active(_name_format)
name_option.set_menu(name_menu)
prefsTop.get_widget("resname").set_text(owner.getName())
prefsTop.get_widget("resaddr").set_text(owner.getAddress())
prefsTop.get_widget("rescity").set_text(owner.getCity())
prefsTop.get_widget("resstate").set_text(owner.getState())
prefsTop.get_widget("rescountry").set_text(owner.getCountry())
prefsTop.get_widget("respostal").set_text(owner.getPostalCode())
prefsTop.get_widget("resphone").set_text(owner.getPhone())
prefsTop.get_widget("resemail").set_text(owner.getEmail())
if ListColors.enable == None:
ListColors.enable = 0
cwidget = prefsTop.get_widget(ODDFGCOLOR)
cwidget.set_i16(ListColors.oddfg[0],ListColors.oddfg[1],\
ListColors.oddfg[2],0xffff)
cwidget = prefsTop.get_widget(ODDBGCOLOR)
cwidget.set_i16(ListColors.oddbg[0],ListColors.oddbg[1],\
ListColors.oddbg[2],0xffff)
cwidget = prefsTop.get_widget(EVENFGCOLOR)
cwidget.set_i16(ListColors.evenfg[0],ListColors.evenfg[1],\
ListColors.evenfg[2],0xffff)
cwidget = prefsTop.get_widget(EVENBGCOLOR)
cwidget.set_i16(ListColors.evenbg[0],ListColors.evenbg[1],\
ListColors.evenbg[2],0xffff)
prefsTop.get_widget("enableColors").set_active(ListColors.enable)
prefsTop.get_widget(ODDFGCOLOR).set_sensitive(ListColors.enable)
prefsTop.get_widget(ODDBGCOLOR).set_sensitive(ListColors.enable)
prefsTop.get_widget(EVENBGCOLOR).set_sensitive(ListColors.enable)
prefsTop.get_widget(EVENFGCOLOR).set_sensitive(ListColors.enable)
pbox.set_modified(0)
pbox.show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_config_color(name,defval):
r = gnome.config.get_int("/gramps/color/" + name + ".r")
g = gnome.config.get_int("/gramps/color/" + name + ".g")
b = gnome.config.get_int("/gramps/color/" + name + ".b")
if not r:
return defval
else:
return (r,g,b)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def druid_cancel_clicked(obj,a):
utils.destroy_passed_object(obj)

685
gramps/src/Date.py Normal file
View File

@@ -0,0 +1,685 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Support for the dates"
import re
import string
import intl
_ = intl.gettext
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Date:
formatCode = 0
BadFormat = _("Unknown Format")
fmt = re.compile("\s*(from|between|bet)(.+)(and|to)(.+)\s*$",
re.IGNORECASE)
def __init__(self):
self.start = SingleDate()
self.stop = SingleDate()
self.range = 0
def get_start_date(self):
return self.start
def get_stop_date(self):
return self.stop
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def set(self,text):
match = Date.fmt.match(text)
if match:
matches = match.groups()
self.start.set(matches[1])
self.stop.set(matches[3])
self.range = 1
else:
self.start.set(text)
self.range = 0
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getDate(self):
function = SingleDate.fmtFunc[Date.formatCode]
if self.range:
return "from " + function(self.start) + " to " + function(self.stop)
else:
return function(self.start)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getSaveDate(self):
if self.range:
return "FROM " + self.start.getFmt3() + " TO " + self.stop.getFmt3()
else:
return self.start.getFmt3()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def quick_set(self,text):
match = Date.fmt.match(text)
if match:
matches = match.groups()
self.start.set(matches[1])
self.stop.set(matches[3])
self.range = 1
else:
self.start.quick_set(text)
self.range = 0
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class SingleDate:
"Date handling"
exact = 0
about = 1
before = 2
after = 3
entryCode = 0
mname = [ "January", "February", "March", "April",
"May", "June", "July", "August", "September",
"October", "November", "December" ]
m2num = { "jan" : 0, "feb" : 1, "mar" : 2, "apr" : 3,
"may" : 4, "jun" : 5, "jul" : 6, "aug" : 7,
"sep" : 8, "oct" : 9, "nov" : 10,"dec" : 11 }
m2v = { "abt" : about , "about" : about, "est" : about ,
"circa" : about, "around": about, "before": before,
"bef" : before, "after" : after, "aft" : after }
modifiers = "(abt|about|est|circa|around|before|after|aft|bef)"
start = "^\s*" + modifiers + "?\s*"
fmt1 = re.compile(start + "(\S+)(\s+\d+\s*,)?\s*(\d+)?\s*$",
re.IGNORECASE)
fmt2 = re.compile(start + "(\d+)\s+(\S+)(\s+\d+)?\s*$",
re.IGNORECASE)
quick= re.compile(start + "(\d+)\s(\S\S\S)\s(\d+)",
re.IGNORECASE)
fmt3 = re.compile(start + "(\d+)\s*[./-]\s*(\d+)\s*[./-]\s*(\d+)\s*$",
re.IGNORECASE)
fmt4 = re.compile(start + "(\S+)\s+(\d+)\s*$",
re.IGNORECASE)
fmt5 = re.compile(start + "(\d+)\s*$",
re.IGNORECASE)
fmt6 = re.compile(start + "(\S+)\s*$",
re.IGNORECASE)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self):
self.month = -1
self.day = -1
self.year = -1
self.mode = SingleDate.exact
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __cmp__(self,other):
if self.year != other.year:
return cmp(self.year,other.year)
elif self.month != other.month:
return cmp(self.month,other.month)
elif self.day != other.day:
return cmp(self.day,other.day)
elif self.mode != other.mode:
if self.mode == SingleDate.exact:
return -1
else:
return 1
else:
return 0
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setMode(self,val):
if val == None:
self.mode = SingleDate.exact
else:
val = string.lower(val)
self.mode = SingleDate.m2v[val]
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setMonth(self,val):
if val > 0 and val < 13:
self.month = val - 1
else:
self.month = -1
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getMonth(self):
return self.month + 1
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setDay(self,val):
if val > 0 or val < 32:
self.day = val
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getDay(self):
return self.day
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setYear(self,val):
self.year = val
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getYear(self):
return self.year
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setMonthStr(self,text):
if SingleDate.m2num.has_key(string.lower(text[0:3])):
self.month = SingleDate.m2num[string.lower(text[0:3])]
else:
self.month = -1
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getMonthStr(self):
return SingleDate.mname[self.month]
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getSaveDate(self):
return self.getFmt3()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt1(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.year == -1:
retval = SingleDate.mname[self.month]
else:
retval = "%s %d" % (SingleDate.mname[self.month],self.year)
elif self.month == -1:
retval = "%d" % self.year
elif self.mode == SingleDate.exact:
month = SingleDate.mname[self.month]
if self.year == -1:
retval = "%s %d, ????" % (month,self.day)
else:
retval = "%s %d, %d" % (month,self.day,self.year)
elif self.mode == SingleDate.about:
month = SingleDate.mname[self.month]
if self.year == -1:
retval = "about %s %d, ????" % (month,self.day)
else:
retval = "about %s %d, %d" % (month,self.day,self.year)
if self.mode == SingleDate.before:
retval = "before " + retval
elif self.mode == SingleDate.after:
retval = "after " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt2(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.year == -1:
month = SingleDate.mname[self.month]
retval = string.upper(month[0:3])
else:
month = SingleDate.mname[self.month]
retval = "%s %d" % (string.upper(month[0:3]),self.year)
elif self.month == -1:
retval = "%d" % self.year
elif self.mode == SingleDate.exact:
month = SingleDate.mname[self.month]
if self.year == -1:
retval = "%s %d, ????" % (string.upper(month[0:3]),self.day)
else:
retval = "%s %d, %d" % (string.upper(month[0:3]),self.day,self.year)
elif self.mode == SingleDate.about:
month = SingleDate.mname[self.month]
if self.year == -1:
retval = "ABT %s %s, ????" % (string.upper(month[0:3]),self.day)
else:
retval = "ABT %s %s, ????" % (string.upper(month[0:3]),self.day,self.year)
if self.mode == SingleDate.before:
retval = "BEFORE " + retval
elif self.mode == SingleDate.after:
retval = "AFTER " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt3(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.year == -1:
month = SingleDate.mname[self.month]
retval = string.upper(month[0:3])
else:
month = SingleDate.mname[self.month]
retval = "%s %d" % (string.upper(month[0:3]),self.year)
elif self.month == -1:
retval = "%d" % self.year
else:
month = SingleDate.mname[self.month]
if self.year == -1:
retval = "%d %s ????" % (self.day,string.upper(month[0:3]))
else:
retval = "%d %s %d" % (self.day,string.upper(month[0:3]),self.year)
if self.mode == SingleDate.about:
retval = "ABT " + retval
elif self.mode == SingleDate.before:
retval = "BEFORE " + retval
elif self.mode == SingleDate.after:
retval = "AFTER " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt4(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.month == -1:
retval = "%d" % self.year
elif self.mode == SingleDate.exact:
if year == -1:
retval = "%d/%d/????" % (self.month+1,self.day)
else:
retval = "%d/%d/%d" % (self.month+1,self.day,self.year)
elif self.mode == SingleDate.about:
if year == -1:
retval = "ABT %d/%d/????" % (self.month+1,self.day,self.year)
else:
retval = "ABT %d/%d/%d" % (self.month+1,self.day,self.year)
if self.mode == SingleDate.before:
retval = "BEFORE " + retval
elif self.mode == SingleDate.after:
retval = "AFTER " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt5(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.month == -1:
retval = "%d" % self.year
elif self.mode == SingleDate.exact:
if self.year == -1:
retval = "%d-%d-????" % (self.month+1,self.day)
else:
retval = "%d-%d-%d" % (self.month+1,self.day,self.year)
elif self.mode == SingleDate.about:
if self.year == -1:
retval = "ABT %d-%d-????" % (self.month+1,self.day,self.year)
else:
retval = "ABT %d-%d-%d" % (self.month+1,self.day,self.year)
if self.mode == SingleDate.before:
retval = "BEFORE " + retval
elif self.mode == SingleDate.after:
retval = "AFTER " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt6(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.month == -1:
retval = "%d" % self.year
elif self.mode == SingleDate.exact:
if self.year == -1:
retval = "%d/%d/????" % (self.day,self.month+1)
else:
retval = "%d/%d/%d" % (self.day,self.month+1,self.year)
elif self.mode == SingleDate.about:
if self.year == -1:
retval = "ABT %d/%d/????" % (self.day,self.month+1)
else:
retval = "ABT %d/%d/%d" % (self.day,self.month+1,self.year)
if self.mode == SingleDate.before:
retval = "BEFORE " + retval
elif self.mode == SingleDate.after:
retval = "AFTER " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getFmt7(self):
retval = ""
if self.month == -1 and self.day == -1 and self.year == -1 :
pass
elif self.day == -1:
if self.month == -1:
retval = "%d" % self.year
elif self.month == -1:
retval = "%d" % self.year
elif self.mode == SingleDate.exact:
if self.year == -1:
retval = "%d-%d-????" % (self.day,self.month+1)
else:
retval = "%d-%d-%d" % (self.day,self.month+1,self.year)
elif self.mode == SingleDate.about:
if self.year == -1:
retval = "ABT %d-%d-????" % (self.day,self.month+1)
else:
retval = "ABT %d-%d-%d" % (self.day,self.month+1,self.year)
if self.mode == SingleDate.before:
retval = "BEFORE " + retval
elif self.mode == SingleDate.after:
retval = "AFTER " + retval
return retval
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
fmtFunc = [ getFmt1, getFmt2, getFmt3, getFmt4, getFmt5, getFmt6, getFmt7 ]
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getDate(self):
function = SingleDate.fmtFunc[Date.formatCode]
return function(self)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def getMode(self,val):
if val == None:
self.mode = SingleDate.exact
elif string.lower(val)[0:3] == "bef":
self.mode = SingleDate.before
elif string.lower(val)[0:3] == "aft":
self.mode = SingleDate.after
else:
self.mode = SingleDate.about
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def set(self,text):
match = SingleDate.fmt2.match(text)
if match != None:
matches = match.groups()
self.getMode(matches[0])
self.setMonthStr(matches[2])
self.setDay(string.atoi(matches[1]))
if len(matches) == 4:
val = matches[3]
if val == None or val[0] == '?':
self.setYear(-1)
else:
self.setYear(string.atoi(val))
else:
self.setYear(-1)
return 1
match = SingleDate.fmt1.match(text)
if match != None:
matches = match.groups()
self.getMode(matches[0])
self.setMonthStr(matches[1])
val = matches[2]
if val:
self.setDay(string.atoi(string.replace(val,',','')))
else:
self.setDay(-1)
if len(matches) == 4:
val = matches[3]
if val == None or val[0] == '?':
self.setYear(-1)
else:
self.setYear(string.atoi(val))
else:
self.setYear(-1)
return 1
match = SingleDate.fmt3.match(text)
if match != None:
matches = match.groups()
self.getMode(matches[0])
if SingleDate.entryCode == 0:
self.setMonth(string.atoi(matches[1]))
self.setDay(string.atoi(matches[2]))
else:
self.setMonth(string.atoi(matches[2]))
self.setDay(string.atoi(matches[1]))
if len(matches) == 3:
val = matches[3]
if val == None or val[0] == '?':
self.setYear(-1)
else:
self.setYear(string.atoi(val))
else:
self.setYear(-1)
return 1
match = SingleDate.fmt5.match(text)
if match != None:
matches = match.groups()
self.getMode(matches[0])
self.setMonth(-1)
self.setDay(-1)
self.setYear(string.atoi(matches[1]))
return 1
match = SingleDate.fmt4.match(text)
if match != None:
matches = match.groups()
self.getMode(matches[0])
self.setMonthStr(matches[1])
self.setDay(-1)
if len(matches) == 4:
val = matches[3]
if val == None or val[0] == '?' :
self.setYear(-1)
else:
self.setYear(string.atoi(val))
return 1
match = SingleDate.fmt6.match(text)
if match != None:
matches = match.groups()
self.getMode(matches[0])
self.setMonth(matches[1])
self.setDay(-1)
self.setYear(-1)
return 1
raise Date.BadFormat,text
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def quick_set(self,text):
match = SingleDate.quick.match(text)
if match != None:
matches = match.groups()
self.setMode(matches[0])
self.setMonthStr(matches[2])
self.setDay(string.atoi(matches[1]))
if len(matches) == 4:
val = matches[3]
if val == None or val[0] == '?':
self.setYear(-1)
else:
self.setYear(string.atoi(val))
else:
self.setYear(-1)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def compare_dates(f,s):
first = f.get_start_date()
second = s.get_start_date()
if first.year != second.year:
return cmp(first.year,second.year)
elif first.month != second.month:
return cmp(first.month,second.month)
else:
return cmp(first.day,second.day)

2850
gramps/src/EditPerson.glade Normal file

File diff suppressed because it is too large Load Diff

1246
gramps/src/EditPerson.py Normal file

File diff suppressed because it is too large Load Diff

143
gramps/src/Filter.py Normal file
View File

@@ -0,0 +1,143 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------
#
# Documentation String - used to describe the filter
#
#-------------------------------------------------------------------------
"All people"
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
import re
import os
import sys
#-------------------------------------------------------------------------
#
# Base filter class
#
#-------------------------------------------------------------------------
class Filter:
"All people"
#-------------------------------------------------------------------------
#
# Initializes the class
#
#-------------------------------------------------------------------------
def __init__(self,text):
self.text = text
self.invert = 0
#-------------------------------------------------------------------------
#
# compare
#
#-------------------------------------------------------------------------
def set_invert(self,invert):
self.invert = invert
#-------------------------------------------------------------------------
#
# compare
#
#-------------------------------------------------------------------------
def compare(self,person):
val = self.match(person)
if self.invert:
return not val
else:
return val
#-------------------------------------------------------------------------
#
# __repr__ - print representation
#
#-------------------------------------------------------------------------
def __repr__(self):
return str(self.__class__)
#-------------------------------------------------------------------------
#
# match - returns true if a match is made. The base class matches
# everything.
#
#-------------------------------------------------------------------------
def match(self,person):
return 1
#-------------------------------------------------------------------------
#
# create - creates a new filter object from the passed data. Eliminates
# the need to know the name of the class.
#
#-------------------------------------------------------------------------
def create(text):
return Filter(text)
#-------------------------------------------------------------------------
#
# need_qualifier - indicates if another parameter is needed. Used to
# enable or disable the qualifier field on the display
#
#-------------------------------------------------------------------------
def need_qualifier():
return 0
filterList = [ "All people" ]
filterMap = { "All people" : create }
filterEnb = { "All people" : need_qualifier }
#-------------------------------------------------------------------------
#
# load_filters - loads all filters in the specfied directory. Looks for
# a task named "create". The create and need_qualifer tasks are loaded in
# hash tables so that the filter description can be used to retrieve the
# create and need_qualifier functions
#
#-------------------------------------------------------------------------
def load_filters(dir):
pymod = re.compile(r"^(.*)\.py$")
if not os.path.isdir(dir):
return
sys.path.append(dir)
for file in os.listdir(dir):
name = os.path.split(file)
match = pymod.match(name[1])
if match == None:
continue
groups = match.groups()
try:
plugin = __import__(groups[0])
except:
continue
for task in plugin.__dict__.keys():
if task == "create":
filterMap[plugin.__doc__] = plugin.__dict__[task]
filterList.append(plugin.__doc__)
if task == "need_qualifier" :
filterEnb[plugin.__doc__] = plugin.__dict__[task]

781
gramps/src/GrampsParser.py Normal file
View File

@@ -0,0 +1,781 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from RelLib import *
from Researcher import Researcher
import string
import os
from xml.sax import handler
#-------------------------------------------------------------------------
#
# Remove extraneous spaces
#
#-------------------------------------------------------------------------
def fix_spaces(text_list):
val = ""
for text in text_list:
val = val + string.join(string.split(text),' ') + "\n"
return val
#-------------------------------------------------------------------------
#
# Gramps database parsing class. Derived from SAX XML parser
#
#-------------------------------------------------------------------------
class GrampsParser(handler.ContentHandler):
researchTag = "researcher"
resnameTag = "resname"
resaddrTag = "resaddr"
rescityTag = "rescity"
resstateTag = "resstate"
resconTag = "rescountry"
resposTag = "respostal"
resphoneTag = "resphone"
resemailTag = "resemail"
attrTag = "attribute"
addressTag = "address"
startTag = "date_start"
stopTag = "date_stop"
cityTag = "city"
stateTag = "state"
streetTag = "street"
countryTag = "country"
postalTag = "postal"
noteTag = "note"
uidTag = "uid"
urlTag = "url"
pTag = "p"
personTag = "person"
peopleTag = "people"
sourcesTag = "sources"
sourcerefTag= "sourceref"
photoTag = "img"
nameTag = "name"
akaTag = "aka"
firstTag = "first"
lastTag = "last"
nickTag = "nick"
genderTag = "gender"
titleTag = "title"
suffixTag = "suffix"
placeTag = "place"
descriptionTag = "description"
dateTag = "date"
familyTag = "family"
fatherTag = "father"
childTag = "child"
createdTag = "created"
childofTag = "childof"
parentinTag = "parentin"
motherTag = "mother"
familiesTag = "families"
eventTag = "event"
sourceTag = "source"
sdateTag = "sdate"
spageTag = "spage"
stitleTag = "stitle"
sauthorTag = "sauthor"
spubinfoTag = "spubinfo"
scallnoTag = "scallno"
stextTag = "stext"
bmarksTag = "bookmarks"
bmarkTag = "bookmark"
scommentsTag= "scomments"
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def __init__(self,database,callback,base,is_import):
self.call = None
self.stext_list = []
self.scomments_list = []
self.note_list = []
self.in_note = 0
self.in_stext = 0
self.in_scomments = 0
self.in_people = 0
self.database = database
self.base = base
self.in_family = 0
self.in_sources = 0
self.person = None
self.family = None
self.source = None
self.sourceRef = None
self.is_import = is_import
self.pmap = {}
self.fmap = {}
self.smap = {}
self.callback = callback
self.entries = 0
self.count = 0
self.increment = 50
self.event = None
self.name = None
self.tempDefault = None
self.owner = Researcher()
self.active = ""
self.data = {}
handler.ContentHandler.__init__(self)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def setDocumentLocator(self,locator):
self.locator = locator
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def endDocument(self):
self.database.setResearcher(self.owner)
if self.tempDefault != None:
id = self.tempDefault
if self.database.personMap.has_key(id):
person = self.database.personMap[id]
self.database.setDefaultPerson(person)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_event(self,attrs):
self.event = Event()
self.event_type = string.capwords(attrs["type"])
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_attribute(self,attrs):
self.attribute = Attribute()
self.attribute.setType(string.capwords(attrs["type"]))
self.person.addAttribute(self.attribute)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_address(self,attrs):
self.address = Address()
self.person.addAddress(self.address)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_bmark(self,attrs):
if self.is_import:
person = self.database.findPerson("x" + attrs["ref"],self.pmap)
else:
person = self.database.findPersonNoMap(attrs["ref"])
self.database.bookmarks.append(person)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_person(self,attrs):
if self.count % self.increment == 0:
self.callback(float(self.count)/float(self.entries))
self.count = self.count + 1
if self.is_import:
self.person = self.database.findPerson("x" + attrs["id"],self.pmap)
else:
self.person = self.database.findPersonNoMap(attrs["id"])
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_people(self,attrs):
self.in_family = 0
self.in_people = 1
self.in_sources = 0
if self.is_import == 0 and attrs.has_key("default"):
self.tempDefault = int(attrs["default"])
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_father(self,attrs):
if self.is_import:
father = self.database.findPerson("x" + attrs["ref"],self.pmap)
else:
father = self.database.findPersonNoMap(attrs["ref"])
self.family.setFather(father)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_mother(self,attrs):
if self.is_import:
mother = self.database.findPerson("x" + attrs["ref"],self.pmap)
else:
mother = self.database.findPersonNoMap(attrs["ref"])
self.family.setMother(mother)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_child(self,attrs):
if self.is_import:
child = self.database.findPerson("x" + attrs["ref"],self.pmap)
else:
child = self.database.findPersonNoMap(attrs["ref"])
self.family.addChild(child)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_url(self,attrs):
if not attrs.has_key("href"):
return
if attrs.has_key("description"):
desc = attrs["description"]
else:
desc = ""
url = Url(attrs["href"],desc)
self.person.addUrl(url)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_family(self,attrs):
if self.count % self.increment == 0:
self.callback(float(self.count)/float(self.entries))
self.count = self.count + 1
if self.is_import:
self.family = self.database.findFamily(attrs["id"],self.fmap)
else:
self.family = self.database.findFamilyNoMap(attrs["id"])
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_childof(self,attrs):
if self.is_import:
family = self.database.findFamily(attrs["ref"],self.fmap)
else:
family = self.database.findFamilyNoMap(attrs["ref"])
if attrs.has_key("type"):
type = attrs["type"]
self.person.addAltFamily(family,type)
else:
self.person.setMainFamily(family)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_parentin(self,attrs):
if self.is_import:
family = self.database.findFamily(attrs["ref"],self.fmap)
else:
family = self.database.findFamilyNoMap(attrs["ref"])
self.person.addFamily(family)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_name(self,attrs):
self.name = Name()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_note(self,attrs):
self.in_note = 1
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_families(self,attrs):
self.in_family = 1
self.in_people = 0
self.in_sources = 0
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_sources(self,attrs):
self.in_family = 0
self.in_people = 0
self.in_sources = 1
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_sourceref(self,attrs):
self.source = Source()
if self.is_import:
self.sourceRef = self.database.findSource(attrs["ref"],self.smap)
else:
self.sourceRef = self.database.findSourceNoMap(attrs["ref"])
self.source.setBase(self.sourceRef)
self.event.setSource(self.source)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_source(self,attrs):
if self.is_import:
self.sourceRef = self.database.findSource(attrs["id"],self.smap)
else:
self.sourceRef = self.database.findSourceNoMap(attrs["id"])
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_photo(self,attrs):
photo = Photo()
if attrs.has_key("descrip"):
photo.setDescription(attrs["descrip"])
src = attrs["src"]
if src[0] != os.sep:
photo.setPath(self.base + os.sep + attrs["src"])
photo.setPrivate(1)
else:
photo.setPath(src)
photo.setPrivate(0)
if self.in_family == 1:
self.family.addPhoto(photo)
else:
self.person.addPhoto(photo)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def start_created(self,attrs):
self.entries = string.atoi(attrs["people"]) + \
string.atoi(attrs["families"])
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_attribute(self,tag):
self.attribute.setValue(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_event(self,tag):
self.event.setName(self.event_type)
if self.event_type == "Birth":
self.person.setBirth(self.event)
elif self.event_type == "Death":
self.person.setDeath(self.event)
elif self.event_type == "Marriage":
self.family.setMarriage(self.event)
elif self.event_type == "Divorce":
self.family.setDivorce(self.event)
elif self.in_people == 1:
self.person.addEvent(self.event)
else:
self.family.addEvent(self.event)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_name(self,tag):
self.person.setPrimaryName(self.name)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_place(self,tag):
self.event.setPlace(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_uid(self,tag):
self.person.setPafUid(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_date(self,tag):
if tag != "":
self.event.getDateObj().quick_set(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_first(self,tag):
self.name.setFirstName(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_description(self,tag):
self.event.setDescription(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_gender(self,tag):
if tag == "M":
self.person.setGender(Person.male)
else:
self.person.setGender(Person.female)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_stitle(self,tag):
self.sourceRef.setTitle(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_sauthor(self,tag):
self.sourceRef.setAuthor(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_sdate(self,tag):
date = Date()
date.quick_set(tag)
self.source.setDate(date)
def stop_date_start(self,tag):
date = self.address.getStartDateObj()
date.quick_set(tag)
def stop_date_stop(self,tag):
date = self.address.getStopDateObj()
date.quick_set(tag)
def stop_street(self,tag):
self.address.setStreet(tag)
def stop_city(self,tag):
self.address.setCity(tag)
def stop_state(self,tag):
self.address.setState(tag)
def stop_country(self,tag):
self.address.setCountry(tag)
def stop_postal(self,tag):
self.address.setPostal(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_spage(self,tag):
self.source.setPage(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_spubinfo(self,tag):
self.sourceRef.setPubInfo(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_scallno(self,tag):
self.sourceRef.setCallNumber(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_stext(self,tag):
self.source.setText(fix_spaces(tag))
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_scomments(self,tag):
self.source.setComments(fix_spaces(self.scomments_list))
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_last(self,tag):
self.name.setSurname(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_suffix(self,tag):
self.name.setSuffix(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_title(self,tag):
self.name.setTitle(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_nick(self,tag):
self.person.setNickName(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_note(self,tag):
self.in_note = 0
if self.in_people == 1:
self.person.setNote(fix_spaces(self.note_list))
elif self.in_family == 1:
self.family.setNote(fix_spaces(self.note_list))
self.note_list = []
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def get_val(self,tag):
if self.data.has_key(tag):
return self.data[tag]
else:
return ""
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_research(self,tag):
self.owner.set(self.get_val(GrampsParser.resnameTag), \
self.get_val(GrampsParser.resaddrTag), \
self.get_val(GrampsParser.rescityTag), \
self.get_val(GrampsParser.resstateTag), \
self.get_val(GrampsParser.resconTag), \
self.get_val(GrampsParser.resposTag),\
self.get_val(GrampsParser.resphoneTag),\
self.get_val(GrampsParser.resemailTag))
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_ptag(self,tag):
if self.in_note:
self.note_list.append(tag)
elif self.in_stext:
self.stext_list.append(tag)
elif self.in_scomments:
self.scomments_list.append(tag)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def stop_aka(self,tag):
self.person.addAlternateName(self.name)
stop = { eventTag : stop_event,
attrTag : stop_attribute,
nameTag : stop_name,
placeTag : stop_place,
dateTag : stop_date,
firstTag : stop_first,
lastTag : stop_last,
titleTag : stop_title,
nickTag : stop_nick,
suffixTag : stop_suffix,
noteTag : stop_note,
uidTag : stop_uid,
stopTag : stop_date_stop,
startTag : stop_date_start,
streetTag : stop_street,
cityTag : stop_city,
stateTag : stop_state,
countryTag : stop_country,
postalTag : stop_postal,
researchTag : stop_research,
descriptionTag : stop_description,
genderTag : stop_gender,
stitleTag : stop_stitle,
sauthorTag : stop_sauthor,
sdateTag: stop_sdate,
spageTag : stop_spage,
spubinfoTag : stop_spubinfo,
scallnoTag : stop_scallno,
stextTag : stop_stext,
pTag : stop_ptag,
akaTag : stop_aka,
scommentsTag : stop_scomments
}
start = { eventTag : start_event ,
attrTag : start_attribute,
bmarkTag : start_bmark,
urlTag : start_url,
personTag : start_person,
addressTag : start_address,
peopleTag : start_people,
fatherTag : start_father,
noteTag : start_note,
motherTag : start_mother,
childTag : start_child,
familyTag : start_family,
childofTag : start_childof,
parentinTag : start_parentin,\
nameTag : start_name,
familiesTag : start_families,
sourcesTag : start_sources,
sourcerefTag : start_sourceref,
sourceTag : start_source,
photoTag : start_photo,
akaTag : start_name,
createdTag : start_created }
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def startElement(self,tag,attrs):
self.data[tag] = ""
self.active = tag
if GrampsParser.start.has_key(tag):
GrampsParser.start[tag](self,attrs)
return
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def endElement(self,tag):
import latin_utf8
if GrampsParser.stop.has_key(tag):
data = latin_utf8.utf8_to_latin(self.data[tag])
GrampsParser.stop[tag](self,data)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def characters(self, data, offset, length):
self.data[self.active] = self.data[self.active] + data

53
gramps/src/ListColors.py Normal file
View File

@@ -0,0 +1,53 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from gtk import *
enable = 0
oddbg = (0xffff,0xffff,0xffff)
evenbg = (0xffff,0xffff,0xffff)
oddfg = (0,0,0)
evenfg = (0,0,0)
class ColorList:
def __init__(self,clist,increment):
self.index = 0
self.modval = 2*increment
self.increment = increment
self.clist = clist
self.oddbg = GdkColor(oddbg[0],oddbg[1],oddbg[2])
self.oddfg = GdkColor(oddfg[0],oddfg[1],oddfg[2])
self.evenbg = GdkColor(evenbg[0],evenbg[1],evenbg[2])
self.evenfg = GdkColor(evenfg[0],evenfg[1],evenfg[2])
def add(self,list):
self.clist.append(list)
if enable:
if self.index % self.modval < self.increment:
self.clist.set_background(self.index,self.oddbg)
self.clist.set_foreground(self.index,self.oddfg)
else:
self.clist.set_background(self.index,self.evenbg)
self.clist.set_foreground(self.index,self.evenfg)
self.index = self.index + 1
def add_with_data(self,list,data):
self.add(list)
self.clist.set_row_data(self.index-1,data)

39
gramps/src/Makefile.in Normal file
View File

@@ -0,0 +1,39 @@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
datadir = @datadir@/@PACKAGE@
INSTALL = @INSTALL@
srcdir = @top_srcdir@
pycomp = ${srcdir}/py-compile
CFLAGS = -fPIC -shared -O -I/usr/include/python1.5 -I/usr/lib/python1.5/config
@SET_MAKE@
all: intl.so
chmod +x ${pycomp}
${pycomp} *.py
intl.so: intl.c
$(CC) $(CFLAGS) -o intl.so intl.c
install:
${INSTALL} -d ${datadir}
${INSTALL} -c *.py *.jpg *.pyo *.glade *.xpm *.so ${datadir}
${INSTALL} -d ${prefix}/share/pixmaps
${INSTALL} -c gramps.png ${prefix}/share/pixmaps
${INSTALL} -d ${prefix}/share/gnome/apps/Applications
${INSTALL} -c gramps.desktop ${prefix}/share/gnome/apps/Applications
for i in locale/*; do\
base=`basename $$i`;\
${INSTALL} -d ${prefix}/share/locale/$$base; \
${INSTALL} -d ${prefix}/share/locale/$$base/LC_MESSAGES; \
${INSTALL} $$i/LC_MESSAGES/gramps.mo ${prefix}/share/locale/$$base/LC_MESSAGES; \
done
uninstall:
rm -f ${datadir}/*.py ${datadir}/*.pyo ${datadir}/*.glade ${datadir}/*.xpm
-rmdir ${datadir}
clean:
-rm -f core *.pyo *.pyc *.bak *~

549
gramps/src/Marriage.py Normal file
View File

@@ -0,0 +1,549 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gtk import *
from gnome.ui import *
import libglade
import os
import intl
_ = intl.gettext
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import Config
import utils
from RelLib import *
import RelImage
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
INDEX = "i"
MARRIAGE = "m"
#-------------------------------------------------------------------------
#
# Marriage class
#
#-------------------------------------------------------------------------
class Marriage:
#-------------------------------------------------------------------------
#
# Initializes the class, and displays the window
#
#-------------------------------------------------------------------------
def __init__(self,family,db):
self.family = family
self.db = db
self.path = db.getSavePath()
self.selectedIcon = 0
self.currentImages = []
self.top = libglade.GladeXML(const.marriageFile,"marriageEditor")
self.top.signal_autoconnect({
"on_marriageAddBtn_clicked" : on_add_clicked,
"on_marriageUpdateBtn_clicked" : on_update_clicked,
"on_marriageDeleteBtn_clicked" : on_delete_clicked,
"on_marriageEventList_select_row" : on_select_row,
"on_showsource_clicked" : on_showsource_clicked,
"on_makeprimary_clicked" : on_primary_photo_clicked,
"on_photolist_select_icon" : on_photo_select_icon,
"on_photolist_button_press_event" : on_photolist_button_press_event,
"on_addphoto_clicked" : on_add_photo_clicked,
"on_deletephoto_clicked" : on_delete_photo_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
top_window = self.get_widget("marriageEditor")
text_win = self.get_widget("marriageTitle")
text_win.set_text(Config.nameof(family.getFather()) + " and " + \
Config.nameof(family.getMother()))
self.event_list = self.get_widget("marriageEventList")
self.photo_list = self.get_widget("photolist")
# widgets
self.date_field = self.get_widget("marriageDate")
self.place_field = self.get_widget("marriagePlace")
self.name_field = self.get_widget("marriageEventName")
self.descr_field = self.get_widget("marriageDescription")
# set initial data
mevent_list = self.get_widget("marriageEvent")
mevent_list.set_popdown_strings(const.marriageEvents)
self.name_field.set_text("")
self.load_images()
# stored object data
top_window.set_data(MARRIAGE,self)
self.event_list.set_data(MARRIAGE,self)
self.event_list.set_data(INDEX,-1)
self.redraw_events()
top_window.show()
#-------------------------------------------------------------------------
#
# add_event - adds the event to the window, attaching the event structure
# to each row.
#
#-------------------------------------------------------------------------
def add_event(self,text,event):
if not event:
return
self.event_list.append([text,event.getDate(),event.getPlace()])
self.event_list.set_row_data(self.lines,event)
self.lines = self.lines + 1
#-------------------------------------------------------------------------
#
# add_thumbnail - Scale the image and add it to the IconList. Currently,
# there seems to be a problem with either GdkImlib. A reference has to be
# kept to the image, or it gets lost. This is supposed to be a known
# imlib problem
#
#-------------------------------------------------------------------------
def add_thumbnail(self,photo):
image2 = RelImage.scale_image(photo.getPath(),const.thumbScale)
self.currentImages.append(image2)
self.photo_list.append_imlib(image2,photo.getDescription())
#-------------------------------------------------------------------------
#
# load_images - clears the currentImages list to free up any cached
# Imlibs. Then add each photo in the person's list of photos to the
# photolist window.
#
#-------------------------------------------------------------------------
def load_images(self):
if len(self.family.getPhotoList()) == 0:
return
self.currentImages = []
self.photo_list.freeze()
self.photo_list.clear()
for photo in self.family.getPhotoList():
self.add_thumbnail(photo)
self.photo_list.thaw()
#-------------------------------------------------------------------------
#
# redraw_events - redraws the event list by deleting all the entries and
# reconstructing the list
#
#-------------------------------------------------------------------------
def redraw_events(self):
self.lines = 0
self.event_list.freeze()
self.event_list.clear()
self.add_event("Marriage",self.family.getMarriage())
self.add_event("Divorce",self.family.getDivorce())
for event in self.family.getEventList():
self.add_event(event.getName(),event)
current_row = self.event_list.get_data(INDEX)
if current_row == None:
current_row = -1
if self.lines >= 0:
if current_row < 0:
current_row = 0
elif self.lines < current_row:
current_row = current_row - 1
self.event_list.select_row(current_row,0)
self.event_list.moveto(current_row,0)
self.event_list.set_data(INDEX,current_row)
self.event_list.thaw()
#-------------------------------------------------------------------------
#
# get_widget - returns the widget associated with the specified name
#
#-------------------------------------------------------------------------
def get_widget(self,name):
return self.top.get_widget(name)
#-------------------------------------------------------------------------
#
# on_add_clicked - creates a new event from the data displayed in the
# window. Special care has to be take for the marriage and divorce
# events, since they are not stored in the event list.
#
#-------------------------------------------------------------------------
def on_add_clicked(obj):
family_obj = obj.get_data(MARRIAGE)
date = family_obj.date_field.get_text()
place= family_obj.place_field.get_text()
name = family_obj.name_field.get_text()
desc = family_obj.descr_field.get_text()
if name == "Marriage":
if family_obj.family.getMarriage() == None:
event = Event()
family_obj.family.setMarriage(event)
else:
event = family_obj.family.getMarriage()
elif name == "Divorce":
if family_obj.family.getDivorce() == None:
event = Event()
family_obj.family.setDivorce(event)
else:
event = family_obj.family.getDivorce()
else:
event = Event()
family_obj.family.addEvent(event)
event.set(name,date,place,desc)
family_obj.redraw_events()
utils.modified()
#-------------------------------------------------------------------------
#
# on_update_clicked - updates the selected event with the values in the
# current display
#
#-------------------------------------------------------------------------
def on_update_clicked(obj):
row = obj.get_data(INDEX)
if row < 0:
return
family_obj = obj.get_data(MARRIAGE)
event = obj.get_row_data(row)
date = family_obj.date_field.get_text()
place= family_obj.place_field.get_text()
name = family_obj.name_field.get_text()
desc = family_obj.descr_field.get_text()
update_event(event,name,date,place,desc)
family_obj.redraw_events()
#-------------------------------------------------------------------------
#
# on_delete_clicked - deletes the currently displayed event from the
# marriage event list. Special care needs to be taken for the Marriage
# and Divorce events, since they are not stored in the event list
#
#-------------------------------------------------------------------------
def on_delete_clicked(obj):
family_obj = obj.get_data(MARRIAGE)
row = obj.get_data(INDEX)
if row < 0:
return
active_event = obj.get_row_data(row)
if active_event == family_obj.family.getMarriage():
family_obj.family.setMarriage(None)
elif active_event == family_obj.family.getDivorce():
family_obj.family.setDivorce(None)
else:
count = 0
list = family_obj.family.getEventList()
for event in list:
if event == active_event:
del list[count]
break
count = count + 1
if family_obj.lines == 1:
obj.set_data(INDEX,None)
elif row > family_obj.lines-1:
obj.set_data(INDEX,row-1)
family_obj.redraw_events()
utils.modified()
#-------------------------------------------------------------------------
#
# on_select_row - updates the internal data attached to the passed object,
# then updates the display.
#
#-------------------------------------------------------------------------
def on_select_row(obj,row,b,c):
obj.set_data(INDEX,row)
family_obj = obj.get_data(MARRIAGE)
event = obj.get_row_data(row)
family_obj.date_field.set_text(event.getDate())
family_obj.place_field.set_text(event.getPlace())
family_obj.name_field.set_text(event.getName())
family_obj.descr_field.set_text(event.getDescription())
#-------------------------------------------------------------------------
#
# update_event
#
# Updates the specified event with the specified date. Compares against
# the previous value, so the that modified flag is not set if nothing has
# actually changed.
#
#-------------------------------------------------------------------------
def update_event(event,name,date,place,desc):
if event.getPlace() != place:
event.setPlace(place)
utils.modified()
if event.getName() != name:
event.setName(name)
utils.modified()
if event.getDescription() != desc:
event.setDescription(desc)
utils.modified()
if event.getDate() != date:
event.setDate(date)
utils.modified()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_showsource_clicked(obj):
import Sources
row = obj.get_data(INDEX)
family_obj = obj.get_data(MARRIAGE)
if row >= 0:
Sources.SourceEditor(obj.get_row_data(row),family_obj.db)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_primary_photo_clicked(obj):
marriage_obj = obj.get_data(MARRIAGE)
if marriage_obj.selectedIcon == None or \
marriage_obj.selectedIcon == 0:
return
photolist = marriage.family.getPhotoList()
savePhoto = photolist[selectedIcon]
for i in range(0,selectedIcon):
photolist[selectedIcon-i] = photolist[selectedIcon-i-1]
photolist[0] = savePhoto
marriage_obj.load_images()
utils.modified()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_photolist_button_press_event(obj,event):
if event.button == 3:
myobj = obj.get_data(MARRIAGE)
menu = GtkMenu()
item = GtkTearoffMenuItem()
item.show()
view = GtkMenuItem(_("View Photo"))
view.set_data("m",myobj)
view.connect("activate",on_view_photo)
view.show()
edit = GtkMenuItem(_("Edit Photo"))
edit.set_data("m",myobj)
edit.connect("activate",on_edit_photo)
edit.show()
change = GtkMenuItem(_("Edit Description"))
change.set_data("m",myobj)
change.connect("activate",on_change_description)
change.show()
menu.append(item)
menu.append(view)
menu.append(edit)
menu.append(change)
menu.popup(None,None,None,0,0)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_view_photo(obj):
myobj = obj.get_data("m")
photo = myobj.person.getPhotoList()[myobj.selectedIcon]
type = gnome.mime.type(photo.getPath())
prog = string.split(gnome.mime.get_value(type,'view'))
args = []
for val in prog:
if val == "%f":
args.append(photo.getPath())
else:
args.append(val)
if os.fork() == 0:
os.execvp(args[0],args)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_edit_photo(obj):
myobj = obj.get_data("m")
photo = myobj.person.getPhotoList()[myobj.selectedIcon]
if os.fork() == 0:
os.execvp(const.editor,[const.editor, photo.getPath()])
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_photo_select_icon(obj,iconNumber,event):
obj.get_data(MARRIAGE).selectedIcon = iconNumber
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_delete_photo_clicked(obj):
marriage_obj = obj.get_data(MARRIAGE)
photolist = marriage_obj.family.getPhotoList()
marriage_obj.photo_list.remove(marriage_obj.selectedIcon)
del photolist[marriage_obj.selectedIcon]
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_add_photo_clicked(obj):
marriage_obj = obj.get_data(MARRIAGE)
imageSelect = libglade.GladeXML(const.imageselFile,"imageSelect")
imageSelect.signal_autoconnect({
"on_savephoto_clicked" : on_savephoto_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
imageSelect.get_widget("imageSelect").set_data(MARRIAGE,marriage_obj)
imageSelect.get_widget("imageSelect").show()
marriage_obj.imageSelect = imageSelect
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_savephoto_clicked(obj):
marriage_obj = obj.get_data(MARRIAGE)
photo_name_obj = marriage_obj.imageSelect.get_widget("photosel")
description_obj = marriage_obj.imageSelect.get_widget("photoDescription")
filename = photo_name_obj.get_full_path(0)
description = description_obj.get_text()
if os.path.exists(filename) == 0:
return
prefix = "f" + str(marriage_obj.family.getId())
name = RelImage.import_photo(filename,marriage_obj.path,prefix)
if name == None:
return
photo = Photo()
photo.setPath(name)
photo.setDescription(description)
marriage_obj.family.addPhoto(photo)
marriage_obj.add_thumbnail(photo)
utils.modified()
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_change_description(obj):
myobj = obj.get_data("m")
photo = myobj.person.getPhotoList()[myobj.selectedIcon]
window = libglade.GladeXML(const.imageselFile,"dialog1")
text = window.get_widget("text")
text.set_text(photo.getDescription())
image2 = RelImage.scale_image(photo.getPath(),200.0)
window.get_widget("photo").load_imlib(image2)
window.get_widget("dialog1").set_data("p",photo)
window.get_widget("dialog1").set_data("t",text)
window.get_widget("dialog1").set_data("m",obj.get_data("m"))
window.signal_autoconnect({
"on_cancel_clicked" : utils.destroy_passed_object,
"on_ok_clicked" : on_ok_clicked,
"on_apply_clicked" : on_apply_clicked
})
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_apply_clicked(obj):
photo = obj.get_data("p")
text = obj.get_data("t").get_text()
if text != photo.getDescription():
photo.setDescription(text)
edit_window = obj.get_data("m")
edit_window.load_images()
utils.modified()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
on_apply_clicked(obj)
utils.destroy_passed_object(obj)

136
gramps/src/OpenOffice.py Normal file
View File

@@ -0,0 +1,136 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import os
import re
import time
import tempfile
import const
meta_creator = re.compile(r"""\s*<meta:initial-creator>""")
dc_creator = re.compile(r"""\s*<dc:creator>""")
meta_date = re.compile(r"""\s*<meta:creation-date>""")
dc_date = re.compile(r"""\s*<dc:date>""")
class OpenOfficeCore:
def __init__(self,filename,template,ext,owner=""):
self.template = template
self.owner = owner
if filename[-4:] != ext:
self.filename = filename + ext
else:
self.filename = filename
self.first = []
self.last = []
self.file = None
self.image_list = []
self.tempdir = ""
def setup(self):
templateFile = open(self.template,"r")
lines = templateFile.readlines()
templateFile.close()
in_last = 0
t = time.localtime(time.time())
time_str="%04d-%02d-%02dT%02d:%02d:%02d" % \
(t[0],t[1],t[2],t[3],t[4],t[5])
for line in lines:
if line[1:15] == "</office:body>":
in_last = 1
self.last.append(line);
elif in_last == 0:
if meta_creator.match(line):
self.first.append("<meta:initial-creator>" + self.owner + \
"</meta:initial-creator>")
elif dc_creator.match(line):
self.first.append("<dc:creator>" + self.owner + \
"</dc:creator>")
elif dc_date.match(line):
self.first.append("<dc:date>" + time_str + \
"</dc:date>")
elif meta_date.match(line):
self.first.append("<meta:creation-date>" + time_str + \
"</meta:creation-date>")
else:
self.first.append(line)
else:
self.last.append(line);
tempfile.tempdir = "/tmp"
self.tempdir = tempfile.mktemp()
os.mkdir(self.tempdir,0700)
os.mkdir(self.tempdir + os.sep + "Pictures")
os.mkdir(self.tempdir + os.sep + "META-INF")
self.file = open(self.tempdir + os.sep + "Content.xml","w")
for line in self.first:
self.file.write(line)
return self.file
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def add_image(self,name):
self.image_list.append(name)
return self.tempdir + os.sep + "Pictures" + os.sep + name
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
import shutil
for line in self.last:
self.file.write(line)
self.file.close()
tmpname = tempfile.mktemp()
file = open(self.tempdir + os.sep + "META-INF" + os.sep + \
"manifest.xml","w")
file.write('<?xml version="1.0" encoding="UTF-8"?>\n')
file.write('<manifest><file-entry media-type="" ')
file.write('full-path="Pictures/"/>')
for image in self.image_list:
file.write('<file-entry media-type="" full-path="Pictures/')
file.write(image + '"/>')
file.write('<file-entry media-type="" full-path="Content.xml"/>')
file.write('</manifest>\n')
file.close()
os.system("cd " + self.tempdir + "; " + const.zipcmd + " " \
+ tmpname + " .")
if os.path.isfile(self.filename):
os.unlink(self.filename)
shutil.copy(tmpname,self.filename)
os.unlink(tmpname)
os.unlink(self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml")
os.unlink(self.tempdir + os.sep + "Content.xml")
for image in self.image_list:
os.unlink(self.tempdir + os.sep + "Pictures" + os.sep + image)
os.rmdir(self.tempdir + os.sep + "Pictures")
os.rmdir(self.tempdir + os.sep + "META-INF")
os.rmdir(self.tempdir)

480
gramps/src/OpenOfficeDoc.py Normal file
View File

@@ -0,0 +1,480 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import os
import tempfile
import string
from TextDoc import *
from latin_utf8 import latin_to_utf8
import const
class OpenOfficeDoc(TextDoc):
def __init__(self,type,orientation):
TextDoc.__init__(self,type,orientation)
self.f = None
self.filename = None
self.level = 0
self.time = "0000-00-00T00:00:00"
def open(self,filename):
import time
t = time.localtime(time.time())
self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % \
(t[0],t[1],t[2],t[3],t[4],t[5])
if filename[-4:] != ".sxw":
self.filename = filename + ".sxw"
else:
self.filename = filename
tempfile.tempdir = "/tmp"
self.tempdir = tempfile.mktemp()
os.mkdir(self.tempdir,0700)
os.mkdir(self.tempdir + os.sep + "Pictures")
os.mkdir(self.tempdir + os.sep + "META-INF")
self.f = open(self.tempdir + os.sep + "content.xml","w")
self.f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
self.f.write('<office:document-content ')
self.f.write('xmlns:office="http://openoffice.org/2000/office" ')
self.f.write('xmlns:style="http://openoffice.org/2000/style" ')
self.f.write('xmlns:text="http://openoffice.org/2000/text" ')
self.f.write('xmlns:table="http://openoffice.org/2000/table" ')
self.f.write('xmlns:draw="http://openoffice.org/2000/drawing" ')
self.f.write('xmlns:fo="http://www.w3.org/1999/XSL/Format" ')
self.f.write('xmlns:xlink="http://www.w3.org/1999/xlink" ')
self.f.write('xmlns:number="http://openoffice.org/2000/datastyle" ')
self.f.write('xmlns:svg="http://www.w3.org/2000/svg" ')
self.f.write('xmlns:chart="http://openoffice.org/2000/chart" ')
self.f.write('xmlns:dr3d="http://openoffice.org/2000/dr3d" ')
self.f.write('xmlns:math="http://www.w3.org/1998/Math/MathML" ')
self.f.write('xmlns:form="http://openoffice.org/2000/form" ')
self.f.write('xmlns:script="http://openoffice.org/2000/script" ')
self.f.write('office:class="text" office:version="0.9">\n')
self.f.write('<office:script/>\n')
self.f.write('<office:font-decls>\n')
self.f.write('<style:font-decl style:name="Times New Roman" ')
self.f.write('fo:font-family="&apos;Times New Roman&apos;" ')
self.f.write('style:font-family-generic="roman" ')
self.f.write('style:font-pitch="variable"/>\n')
self.f.write('<style:font-decl style:name="Arial" ')
self.f.write('fo:font-family="Arial" ')
self.f.write('style:font-family-generic="swiss" ')
self.f.write('style:font-pitch="variable"/>\n')
self.f.write('</office:font-decls>\n')
self.f.write('<office:automatic-styles>\n')
for style_name in self.table_styles.keys():
style = self.table_styles[style_name]
self.f.write('<style:style style:name="' + style_name + '" ')
self.f.write('style:family="table">\n')
table_width = float(self.get_usable_width())
self.f.write('<style:properties style:width="%.3fcm" ' % table_width)
self.f.write('/>\n')
self.f.write('</style:style>\n')
for col in range(0,style.get_columns()):
self.f.write('<style:style style:name="')
self.f.write(style_name + '.' + str(chr(ord('A')+col)) +'" ')
self.f.write('style:family="table-column">')
width = table_width * float(style.get_column_width(col)/100.0)
self.f.write('<style:properties style:column-width="%.3fcm"/>' % width)
self.f.write('</style:style>\n')
for cell in self.cell_styles.keys():
cell_style = self.cell_styles[cell]
self.f.write('<style:style style:name="')
self.f.write(cell)
self.f.write('" style:family="table-cell">\n')
self.f.write('<style:properties')
self.f.write(' fo:padding="%.3fcm"' % cell_style.get_padding())
if cell_style.get_top_border():
self.f.write(' fo:border-top="0.002cm solid #000000"')
else:
self.f.write(' fo:border-top="none"')
if cell_style.get_bottom_border():
self.f.write(' fo:border-bottom="0.002cm solid #000000"')
else:
self.f.write(' fo:border-bottom="none"')
if cell_style.get_left_border():
self.f.write(' fo:border-left="0.002cm solid #000000"')
else:
self.f.write(' fo:border-left="none"')
if cell_style.get_right_border():
self.f.write(' fo:border-right="0.002cm solid #000000"')
else:
self.f.write(' fo:border-right="none"')
self.f.write('/>\n')
self.f.write('</style:style>\n')
self.f.write('<style:style style:name="T1" style:family="text">\n')
self.f.write('<style:properties fo:font-weight="bold"/>\n')
self.f.write('</style:style>\n')
self.f.write('</office:automatic-styles>\n')
self.f.write('<office:body>\n')
def close(self):
self.f.write('</office:body>\n')
self.f.write('</office:document-content>\n')
self.f.close()
self._write_styles_file()
self._write_manifest()
self._write_meta_file()
self._write_zip()
def start_table(self,name,style_name):
self.f.write('<table:table table:name="')
self.f.write(name)
self.f.write('" table:style-name="' + style_name + '">\n')
table = self.table_styles[style_name]
for col in range(0,table.get_columns()):
self.f.write('<table:table-column table:style-name="')
self.f.write(style_name + '.' + str(chr(ord('A')+col)) +'"/>\n')
def end_table(self):
self.f.write('</table:table>\n')
def start_row(self):
self.f.write('<table:table-row>\n')
def end_row(self):
self.f.write('</table:table-row>\n')
def start_cell(self,style_name,span=1):
self.span = span
self.f.write('<table:table-cell table:style-name="')
self.f.write(style_name)
self.f.write('" table:value-type="string"')
if span > 1:
self.f.write(' table:number-columns-spanned="' + str(span) + '">\n')
else:
self.f.write('>\n')
def end_cell(self):
self.f.write('</table:table-cell>\n')
for col in range(1,self.span):
self.f.write('<table:covered-table-cell/>\n')
def _write_zip(self):
if os.path.isfile(self.filename):
os.unlink(self.filename)
os.system("cd " + self.tempdir + "; " + const.zipcmd + " " \
+ self.filename + " .")
os.unlink(self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml")
os.unlink(self.tempdir + os.sep + "content.xml")
os.unlink(self.tempdir + os.sep + "meta.xml")
os.unlink(self.tempdir + os.sep + "styles.xml")
# for image in self.image_list:
# os.unlink(self.tempdir + os.sep + "Pictures" + os.sep + image)
os.rmdir(self.tempdir + os.sep + "Pictures")
os.rmdir(self.tempdir + os.sep + "META-INF")
os.rmdir(self.tempdir)
def _write_styles_file(self):
file = self.tempdir + os.sep + "styles.xml"
self.f = open(file,"w")
self.f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
self.f.write('<office:document-styles ')
self.f.write('xmlns:office="http://openoffice.org/2000/office" ')
self.f.write('xmlns:style="http://openoffice.org/2000/style" ')
self.f.write('xmlns:text="http://openoffice.org/2000/text" ')
self.f.write('xmlns:table="http://openoffice.org/2000/table" ')
self.f.write('xmlns:draw="http://openoffice.org/2000/drawing" ')
self.f.write('xmlns:fo="http://www.w3.org/1999/XSL/Format" ')
self.f.write('xmlns:xlink="http://www.w3.org/1999/xlink" ')
self.f.write('xmlns:number="http://openoffice.org/2000/datastyle" ')
self.f.write('xmlns:svg="http://www.w3.org/2000/svg" ')
self.f.write('xmlns:chart="http://openoffice.org/2000/chart" ')
self.f.write('xmlns:dr3d="http://openoffice.org/2000/dr3d" ')
self.f.write('xmlns:math="http://www.w3.org/1998/Math/MathML" ')
self.f.write('xmlns:form="http://openoffice.org/2000/form" ')
self.f.write('xmlns:script="http://openoffice.org/2000/script" ')
self.f.write('office:class="text" office:version="0.9">\n')
self.f.write('<office:font-decls>\n')
self.f.write('<style:font-decl style:name="Times New Roman" ')
self.f.write('fo:font-family="&apos;Times New Roman&apos;" ')
self.f.write('style:font-family-generic="roman" ')
self.f.write('style:font-pitch="variable"/>\n')
self.f.write('<style:font-decl style:name="Arial" ')
self.f.write('fo:font-family="Arial" ')
self.f.write('style:font-family-generic="swiss" ')
self.f.write('style:font-pitch="variable"/>\n')
self.f.write('</office:font-decls>\n')
self.f.write('<office:styles>\n')
self.f.write('<style:default-style style:family="paragraph">\n')
self.f.write('<style:properties style:font-name="Times New Roman" ')
self.f.write('style:font-pitch-asian="fixed" ')
self.f.write('style:font-pitch-complex="fixed" ')
self.f.write('style:tab-stop-distance="2.205cm"/>\n')
self.f.write('</style:default-style>\n')
self.f.write('<style:style style:name="Standard" ')
self.f.write('style:family="paragraph" style:class="text"/>\n')
for key in self.style_list.keys():
style = self.style_list[key]
self.f.write('<style:style style:name="' + key + '" ')
self.f.write('style:family="paragraph" ')
self.f.write('style:parent-style-name="Standard" ')
self.f.write('style:class="text">\n')
self.f.write('<style:properties ')
if style.get_padding() != 0.0:
self.f.write('fo:padding="%.3fcm" ' % style.get_padding())
align = style.get_alignment()
if align == PARA_ALIGN_LEFT:
self.f.write('fo:text-align="left" ')
elif align == PARA_ALIGN_RIGHT:
self.f.write('fo:text-align="right" ')
elif align == PARA_ALIGN_CENTER:
self.f.write('fo:text-align="center" ')
self.f.write('style:justify-single-word="false" ')
else:
self.f.write('fo:text-align="justify" ')
self.f.write('style:justify-single-word="false" ')
font = style.get_font()
if font.get_type_face() == FONT_SANS_SERIF:
self.f.write('style:font-name="Arial" ')
else:
self.f.write('style:font-name="Times New Roman" ')
self.f.write('fo:font-size="' + str(font.get_size()) + 'pt" ')
color = font.get_color()
self.f.write('fo:color="#%02x%02x%02x" ' % color)
if font.get_bold():
self.f.write('fo:font-weight="bold" ')
if font.get_italic():
self.f.write('fo:font-style="italic" ')
if font.get_underline():
self.f.write('style:text-underline="single" ')
self.f.write('style:text-underline-color="font-color" ')
self.f.write('fo:text-indent="%.2fcm" ' % style.get_first_indent())
self.f.write('fo:margin-right="%.2fcm" ' % style.get_right_margin())
self.f.write('fo:margin-left="%.2fcm" ' % style.get_left_margin())
self.f.write('fo:margin-top="0cm" ')
self.f.write('fo:margin-bottom="0.212cm"')
self.f.write('/>\n')
self.f.write('</style:style>\n')
# Current no leading number format for headers
self.f.write('<text:outline-style>\n')
self.f.write('<text:outline-level-style text:level="1" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="2" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="3" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="4" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="5" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="6" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="7" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="8" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="9" style:num-format=""/>\n')
self.f.write('<text:outline-level-style text:level="10" style:num-format=""/>\n')
self.f.write('</text:outline-style>\n')
self.f.write('</office:styles>\n')
self.f.write('<office:automatic-styles>\n')
self.f.write('<style:page-master style:name="pm1">\n')
self.f.write('<style:properties fo:page-width="%.2fcm" ' % self.width)
self.f.write('fo:page-height="%.2fcm" ' % self.height)
self.f.write('style:num-format="1" ')
if self.orientation == PAPER_PORTRAIT:
self.f.write('style:print-orientation="portrait" ')
else:
self.f.write('style:print-orientation="landscape" ')
self.f.write('fo:margin-top="%.2fcm" ' % self.tmargin)
self.f.write('fo:margin-bottom="%.2fcm" ' % self.bmargin)
self.f.write('fo:margin-left="%.2fcm" ' % self.lmargin)
self.f.write('fo:margin-right="%.2fcm" ' % self.rmargin)
self.f.write('style:footnote-max-height="0cm">\n')
self.f.write('<style:footnote-sep style:width="0.018cm" ')
self.f.write('style:distance-before-sep="0.101cm" ')
self.f.write('style:distance-after-sep="0.101cm" ')
self.f.write('style:adjustment="left" style:rel-width="25%" ')
self.f.write('style:color="#000000"/>\n')
self.f.write('</style:properties>\n')
self.f.write('<style:header-style/>\n')
self.f.write('<style:footer-style/>\n')
self.f.write('</style:page-master>\n')
self.f.write('</office:automatic-styles>\n')
self.f.write('<office:master-styles>\n')
self.f.write('<style:master-page style:name="Standard" ')
self.f.write('style:page-master-name="pm1"/>\n')
self.f.write('</office:master-styles>\n')
self.f.write('</office:document-styles>\n')
self.f.close()
def start_paragraph(self,style_name):
style = self.style_list[style_name]
self.level = style.get_header_level()
if self.level == 0:
self.f.write('<text:p text:style-name="' + style_name + '">')
else:
self.f.write('<text:h text:style-name="' + style_name)
self.f.write('" text:level="' + str(self.level) + '">')
def end_paragraph(self):
if self.level == 0:
self.f.write('</text:p>\n')
else:
self.f.write('</text:h>\n')
def write_text(self,text):
text = string.replace(text,'\t','<text:tab-stop/>')
text = string.replace(text,'\n','<text:line-break/>')
self.f.write(latin_to_utf8(text))
def _write_manifest(self):
file = self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml"
self.f = open(file,"w")
self.f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
self.f.write('<manifest:manifest ')
self.f.write('xmlns:manifest="http://openoffice.org/2001/manifest">')
self.f.write('<manifest:file-entry ')
self.f.write('manifest:media-type="application/vnd.sun.xml.writer" ')
self.f.write('manifest:full-path="/"/>')
self.f.write('<manifest:file-entry manifest:media-type="" ')
self.f.write('manifest:full-path="Pictures/"/>')
self.f.write('<manifest:file-entry manifest:media-type="text/xml" ')
self.f.write('manifest:full-path="content.xml"/>')
self.f.write('<manifest:file-entry manifest:media-type="text/xml" ')
self.f.write('manifest:full-path="styles.xml"/>')
self.f.write('<manifest:file-entry manifest:media-type="text/xml" ')
self.f.write('manifest:full-path="meta.xml"/>')
#self.f.write('<manifest:file-entry manifest:media-type="text/xml" ')
#self.f.write('manifest:full-path="settings.xml"/>')
self.f.write('</manifest:manifest>\n')
self.f.close()
def _write_meta_file(self):
file = self.tempdir + os.sep + "meta.xml"
name = latin_to_utf8(self.name)
self.f = open(file,"w")
self.f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
self.f.write('<office:document-meta ')
self.f.write('xmlns:office="http://openoffice.org/2000/office" ')
self.f.write('xmlns:xlink="http://www.w3.org/1999/xlink" ')
self.f.write('xmlns:dc="http://purl.org/dc/elements/1.1/" ')
self.f.write('xmlns:meta="http://openoffice.org/2000/meta" ')
self.f.write('office:class="text" office:version="0.9">\n');
self.f.write('<office:meta>\n')
self.f.write('<meta:generator>')
self.f.write(const.progName + ' ' + const.version)
self.f.write('</meta:generator>\n')
self.f.write('<meta:initial-creator>')
self.f.write(name)
self.f.write('</meta:initial-creator>\n')
self.f.write('<meta:creation-date>')
self.f.write(self.time)
self.f.write('</meta:creation-date>\n')
self.f.write('<dc:creator>')
self.f.write(name)
self.f.write('</dc:creator>\n')
self.f.write('<dc:date>')
self.f.write(self.time)
self.f.write('</dc:date>\n')
self.f.write('<meta:print-date>0-00-00T00:00:00</meta:print-date>\n')
self.f.write('<dc:language>en-US</dc:language>\n')
self.f.write('<meta:editing-cycles>1</meta:editing-cycles>\n')
self.f.write('<meta:editing-duration>PT0S</meta:editing-duration>\n')
self.f.write('<meta:user-defined meta:name="Info 0"/>\n')
self.f.write('<meta:user-defined meta:name="Info 1"/>\n')
self.f.write('<meta:user-defined meta:name="Info 2"/>\n')
self.f.write('<meta:user-defined meta:name="Info 3"/>\n')
self.f.write('</office:meta>\n')
self.f.write('</office:document-meta>\n')
self.f.close()
if __name__ == "__main__":
doc = OpenOfficeDoc(PAPER_US_LETTER,PAPER_PORTRAIT)
foo = FontStyle()
foo.set_type_face(FONT_SANS_SERIF)
foo.set_color((255,0,0))
foo.set_size(24)
para = ParagraphStyle()
para.set_font(foo)
para.set_alignment(PARA_ALIGN_RIGHT)
doc.add_style("MyTitle",para)
para = ParagraphStyle()
para.set_left_margin(1)
para.set_right_margin(1)
para.set_alignment(PARA_ALIGN_JUSTIFY)
doc.add_style("Normal",para)
table = TableStyle()
table.set_width(10)
table.set_columns(2)
table.set_column_width(0,2)
table.set_column_width(1,8)
doc.add_table_style("Table1",table)
para = ParagraphStyle()
font = FontStyle()
font.set_type_face(FONT_SANS_SERIF)
font.set_bold(1)
font.set_size(16)
para.set_font(font)
doc.add_style("TableEntry",para)
cell = TableCellStyle()
cell.set_bottom_border(1)
cell.set_top_border(1)
doc.add_cell_style("TableHeader",cell)
cell = TableCellStyle()
doc.add_cell_style("TableContents",cell)
doc.open("/home/dona/oo_test.sxw")
doc.start_paragraph("MyTitle")
doc.write_text("This is my Title")
doc.end_paragraph()
doc.start_paragraph("Normal")
doc.write_text("This is a test of the emergency broadcast system. ")
doc.write_text("This is a only a test. Repeat. This is only a test. ")
doc.write_text("Had this been an actual emergency, we would not be here ")
doc.write_text("to give you this message.")
doc.end_paragraph()
doc.start_table("MyTable","Table1")
doc.start_row()
doc.start_cell("TableHeader",2)
doc.start_paragraph("TableEntry")
doc.write_text("This is my Title")
doc.end_paragraph()
doc.end_cell()
doc.end_row()
doc.start_row()
doc.start_cell("TableContents")
doc.write_text("Hello")
doc.end_cell()
doc.start_cell("TableContents")
doc.write_text("Goodbye")
doc.end_cell()
doc.end_row()
doc.end_table()
doc.close()

64
gramps/src/PaperMenu.py Normal file
View File

@@ -0,0 +1,64 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import TextDoc
import gtk
import intl
_ = intl.gettext
paper_sizes = [
TextDoc.PaperStyle("US Letter",27.94,21.59),
TextDoc.PaperStyle("US Legal",35.56,21.59),
TextDoc.PaperStyle("A3",42.0,29.7),
TextDoc.PaperStyle("A4",29.7,21.0),
TextDoc.PaperStyle("A5",21.0,14.8),
TextDoc.PaperStyle("B4",35.3,25.0),
TextDoc.PaperStyle("B6",17.6,12.5),
TextDoc.PaperStyle("C4",32.4,22.9),
TextDoc.PaperStyle("C5",22.9,16.2),
TextDoc.PaperStyle("C6",16.2,11.4)
]
def make_paper_menu(main_menu):
myMenu = gtk.GtkMenu()
for paper in paper_sizes:
menuitem = gtk.GtkMenuItem(paper.get_name())
menuitem.set_data("i",paper)
menuitem.show()
myMenu.append(menuitem)
main_menu.set_menu(myMenu)
def make_orientation_menu(main_menu):
myMenu = gtk.GtkMenu()
menuitem = gtk.GtkMenuItem(_("Portrait"))
menuitem.set_data("i",TextDoc.PAPER_PORTRAIT)
menuitem.show()
myMenu.append(menuitem)
menuitem = gtk.GtkMenuItem(_("Landscape"))
menuitem.set_data("i",TextDoc.PAPER_LANDSCAPE)
menuitem.show()
myMenu.append(menuitem)
main_menu.set_menu(myMenu)

400
gramps/src/Plugins.py Normal file
View File

@@ -0,0 +1,400 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
from gtk import *
from gnome.ui import *
import GTK
import gnome.config
import gnome.help
import libglade
import intl
_ = intl.gettext
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
import os
import sys
import string
import re
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
import const
import utils
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
reports = []
imports = []
exports = []
tools = []
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class ReportPlugins:
def __init__(self,db,active):
self.db = db
self.active = active
self.plugins_dialog = libglade.GladeXML(const.pluginsFile,"report")
self.plugins_dialog.signal_autoconnect({
"on_report_apply_clicked" : on_report_apply_clicked,
"on_report_ok_clicked" : on_report_ok_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
top = self.plugins_dialog.get_widget("report")
top.set_data("o",self)
tree = self.plugins_dialog.get_widget("tree1")
self.run_tool = None
item_hash = {}
for report in reports:
info = string.split(report.__doc__,"/")
if len(info) == 1:
category = "Uncategorized"
name = info[0]
else:
category = info[0]
name = info[1]
item = GtkTreeItem(name)
item.set_data("o",self)
item.set_data("c",report.report)
if "get_description" in report.__dict__.keys():
item.set_data("d",report.get_description)
else:
item.set_data("d",no_description)
if "get_xpm_image" in report.__dict__.keys():
item.set_data("i",report.get_xpm_image)
else:
item.set_data("i",no_image)
item.set_data("t",report.__doc__)
item.connect("select",on_report_node_selected)
if item_hash.has_key(category):
item_hash[category].append(item)
else:
item_hash[category] = [item]
key_list = item_hash.keys()
key_list.sort()
for key in key_list:
top_item = GtkTreeItem(key)
top_item.show()
tree.append(top_item)
subtree = GtkTree()
subtree.show()
top_item.set_subtree(subtree)
subtree.show()
for item in item_hash[key]:
item.show()
subtree.append(item)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class ToolPlugins:
def __init__(self,db,active,update):
self.db = db
self.active = active
self.update = update
self.plugins_dialog = libglade.GladeXML(const.pluginsFile,"pluginsel")
self.plugins_dialog.signal_autoconnect({
"on_apply_clicked" : on_apply_clicked,
"on_ok_clicked" : on_ok_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
top = self.plugins_dialog.get_widget("pluginsel")
top.set_data("o",self)
tree = self.plugins_dialog.get_widget("tree")
self.run_tool = None
item_hash = {}
for report in tools:
info = string.split(report.__doc__,"/")
item = GtkTreeItem(info[1])
item.set_data("o",self)
item.set_data("c",report.runTool)
item.set_data("d",report.get_description)
item.set_data("t",report.__doc__)
item.connect("select",on_node_selected)
if item_hash.has_key(info[0]):
item_hash[info[0]].append(item)
else:
item_hash[info[0]] = [item]
key_list = item_hash.keys()
key_list.sort()
for key in key_list:
top_item = GtkTreeItem(key)
top_item.show()
tree.append(top_item)
subtree = GtkTree()
subtree.show()
top_item.set_subtree(subtree)
subtree.show()
for item in item_hash[key]:
item.show()
subtree.append(item)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_node_selected(obj):
myobj = obj.get_data("o")
doc = obj.get_data("d")
title = string.split(obj.get_data("t"),"/")
myobj.plugins_dialog.get_widget("description").set_text(doc())
myobj.plugins_dialog.get_widget("pluginTitle").set_text(title[1])
myobj.run_tool = obj.get_data("c")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_report_node_selected(obj):
myobj = obj.get_data("o")
doc = obj.get_data("d")
xpm_func = obj.get_data("i")
title = string.split(obj.get_data("t"),"/")
img = myobj.plugins_dialog.get_widget("image")
myobj.plugins_dialog.get_widget("description").set_text(doc())
i,m = create_pixmap_from_xpm_d(GtkWindow(),None,xpm_func())
img.set(i,m)
if len(title) == 1:
myobj.plugins_dialog.get_widget("report_title").set_text(title[0])
else:
myobj.plugins_dialog.get_widget("report_title").set_text(title[1])
myobj.run_tool = obj.get_data("c")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def by_doc(a,b):
return cmp(a.__doc__,b.__doc__)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_apply_clicked(obj):
myobj = obj.get_data("o")
utils.destroy_passed_object(obj)
if myobj.run_tool != None:
myobj.run_tool(myobj.db,myobj.active,myobj.update)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_report_apply_clicked(obj):
myobj = obj.get_data("o")
utils.destroy_passed_object(obj)
if myobj.run_tool != None:
myobj.run_tool(myobj.db,myobj.active)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
on_apply_clicked(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_report_ok_clicked(obj):
on_report_apply_clicked(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def load_plugins(dir):
pymod = re.compile(r"^(.*)\.py$")
if not os.path.isdir(dir):
return
sys.path.append(dir)
for file in os.listdir(dir):
name = os.path.split(file)
match = pymod.match(name[1])
if not match:
continue
groups = match.groups()
try:
plugin = __import__(groups[0])
except:
print groups[0]
continue
for task in plugin.__dict__.keys():
if task == "report":
reports.append(plugin)
elif task == "writeData":
exports.append(plugin)
elif task == "runTool":
tools.append(plugin)
elif task == "readData":
imports.append(plugin)
tools.sort(by_doc)
imports.sort(by_doc)
exports.sort(by_doc)
reports.sort(by_doc)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def export_menu(callback):
myMenu = GtkMenu()
for report in exports:
item = GtkMenuItem(report.__doc__)
item.show()
item.connect("activate", callback ,report.writeData)
myMenu.append(item)
return myMenu
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def import_menu(callback):
myMenu = GtkMenu()
for report in imports:
item = GtkMenuItem(report.__doc__)
item.show()
item.connect("activate", callback ,report.readData)
myMenu.append(item)
return myMenu
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def no_description():
return _("No description was provided")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def no_image():
return [
"48 48 5 1",
" c None",
". c #999999",
"+ c #FFFFCC",
"@ c #000000",
"# c #CCCCCC",
" ",
" ",
" ",
" ",
" ",
" ",
" .......... ",
" .++++++++. ",
" .++++++++. ",
" @@@.++++++++. ",
" @##.++++++++. ",
" @# .++++++++. ",
" .......... @# .......... ",
" .++++++++. @# ",
" .++++++++. @# ",
" @@@.++++++++.@@@@# ",
" @##.++++++++.###@# .......... ",
" @# .++++++++. @# .++++++++. ",
" @# .......... @# .++++++++. ",
" @# @@@.++++++++. ",
" @# ##.++++++++. ",
" @# .++++++++. ",
" .......... @# .......... ",
" .++++++++. @# ",
" .++++++++. @# ",
" .++++++++.@@@@# ",
" .++++++++.###@# ",
" .++++++++. @# .......... ",
" .......... @# .++++++++. ",
" @# .++++++++. ",
" @# @@@.++++++++. ",
" @# @##.++++++++. ",
" @# .......... @# .++++++++. ",
" @# .++++++++. @# .......... ",
" @# .++++++++. @# ",
" @@@.++++++++.@@@@# ",
" ##.++++++++.###@# ",
" .++++++++. @# .......... ",
" .......... @# .++++++++. ",
" @# .++++++++. ",
" @@@.++++++++. ",
" ##.++++++++. ",
" .++++++++. ",
" .......... ",
" ",
" ",
" ",
" "]

117
gramps/src/ReadXML.py Normal file
View File

@@ -0,0 +1,117 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from RelLib import *
from GrampsParser import *
import intl
import string
import time
import gzip
import os
from gnome.ui import *
import xml.sax
import xml.sax.saxexts
import xml.sax.saxutils
import xml.parsers.expat
_ = intl.gettext
#-------------------------------------------------------------------------
#
# Initialization function for the module. Called to start the reading
# of data.
#
#-------------------------------------------------------------------------
def importData(database, filename, callback):
parser = xml.sax.saxexts.make_parser()
basefile = os.path.dirname(filename)
database.smap = {}
database.pmap = {}
database.fmap = {}
parser.setDocumentHandler(GrampsParser(database,callback,basefile,1))
xml_file = gzip.open(filename,"rb")
parser.parseFile(xml_file)
xml_file.close()
#-------------------------------------------------------------------------
#
# Initialization function for the module. Called to start the reading
# of data.
#
#-------------------------------------------------------------------------
def loadData(database, filename, callback):
parser = xml.sax.saxexts.make_parser()
basefile = os.path.dirname(filename)
database.smap = {}
database.pmap = {}
database.fmap = {}
parser.setErrorHandler(xml.sax.saxutils.ErrorRaiser())
parser.setDocumentHandler(GrampsParser(database,callback,basefile,0))
filename = os.path.normpath(filename)
try:
xml_file = gzip.open(filename,"rb")
except IOError,msg:
GnomeErrorDialog(filename + _(" could not be opened\n") + str(msg))
return 0
except:
GnomeErrorDialog(filename + _(" could not be opened\n"))
return 0
try:
parser.parseFile(xml_file)
except xml.sax.SAXParseException:
GnomeErrorDialog(filename + _(" is a corrupt file"))
return 0
except xml.parsers.expat.ExpatError:
GnomeErrorDialog(filename + _(" is a corrupt file"))
return 0
except IOError,msg:
GnomeErrorDialog(filename + _(" is not a valid gramps file\n") + \
str(msg))
return 0
except:
GnomeErrorDialog(_("Could not read ") + filename)
return 0
xml_file.close()
return 1

77
gramps/src/RelImage.py Normal file
View File

@@ -0,0 +1,77 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import os
import const
import intl
_ = intl.gettext
#-------------------------------------------------------------------------
#
# import_photo
#
#-------------------------------------------------------------------------
def import_photo(filename,path,prefix):
import gnome.mime
import shutil
type = gnome.mime.type_of_file(filename)
if type[0:6] != "image/":
GnomeErrorDialog(_("Currently only JPEG files are supported"))
return None
for index in range(0,1000):
base = "%s_%d.jpg" % (prefix,index)
name = path + os.sep + base
if os.path.exists(name) == 0:
break
try:
if type == "image/jpeg":
shutil.copy(filename,name)
else:
cmd = const.convert + " " + filename + " " + name
os.system(cmd)
except:
return None
return name
#-------------------------------------------------------------------------
#
# scale_image
#
#-------------------------------------------------------------------------
def scale_image(path,size):
import GdkImlib
image1 = GdkImlib.Image(path)
width = image1.rgb_width
height = image1.rgb_height
scale = size / float(max(width,height))
image2 = image1.clone_scaled_image(int(scale*width), int(scale*height))
return image2

798
gramps/src/RelLib.py Normal file
View File

@@ -0,0 +1,798 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from Date import *
from Researcher import *
#-------------------------------------------------------------------------
#
# Photo class. Contains information about a photo stored in the database
#
#-------------------------------------------------------------------------
class Photo:
def __init__(self):
self.path = ""
self.desc = ""
self.private = 0
def setPath(self,path):
self.path = path
def getPath(self):
return self.path
def setPrivate(self,val):
self.private = val
def getPrivate(self):
return self.private
def setDescription(self,text):
self.desc = text
def getDescription(self):
return self.desc
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Attribute:
def __init__(self):
self.type = ""
self.value = ""
def setType(self,val):
self.type = val
def getType(self):
return self.type
def setValue(self,val):
self.value = val
def getValue(self):
return self.value
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Address:
def __init__(self):
self.street = ""
self.city = ""
self.state = ""
self.country = ""
self.postal = ""
self.start = Date()
self.stop = Date()
def setStartDate(self,date):
self.start.set(date)
def getStartDate(self):
return self.start.getDate()
def getStartDateObj(self):
return self.start
def setStopDate(self,date):
self.stop.set(date)
def getStopDate(self):
return self.stop.getDate()
def getStopDateObj(self):
return self.stop
def setStreet(self,val):
self.street = val
def getStreet(self):
return self.street
def setCity(self,val):
self.city = val
def getCity(self):
return self.city
def setState(self,val):
self.state = val
def getState(self):
return self.state
def setCountry(self,val):
self.country = val
def getCountry(self):
return self.country
def setPostal(self,val):
self.postal = val
def getPostal(self):
return self.postal
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Name:
def __init__(self):
self.FirstName = ""
self.Surname = ""
self.Suffix = ""
self.Title = ""
def setName(self,first,last,suffix):
self.FirstName = first
self.Surname = last
self.Suffix = suffix
def setFirstName(self,name):
self.FirstName = name
def setSurname(self,name):
self.Surname = name
def setSuffix(self,name):
self.Suffix = name
def getFirstName(self):
return self.FirstName
def getSurname(self):
return self.Surname
def getSuffix(self):
return self.Suffix
def setTitle(self,title):
self.Title = title
def getTitle(self):
return self.Title
def getName(self):
if (self.Suffix == ""):
return "%s, %s" % (self.Surname, self.FirstName)
else:
return "%s, %s %s" % (self.Surname, self.FirstName, self.Suffix)
def getRegularName(self):
if (self.Suffix == ""):
return "%s %s" % (self.FirstName, self.Surname)
else:
return "%s %s, %s" % (self.FirstName, self.Surname, self.Suffix)
def getNote(self):
return self.note
def setNote(self,text):
self.note = text
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Url:
def __init__(self,path="",desc=""):
self.path = path
self.desc = desc
def set_path(self,path):
self.path = path
def get_path(self):
return self.path
def set_description(self,description):
self.desc = description
def get_description(self):
return self.desc
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Person:
male = 1
female = 0
def __init__(self):
self.id = -1
self.PrimaryName = Name()
self.EventList = []
self.FamilyList = []
self.AltFamilyList = []
self.MainFamily = None
self.photoList = []
self.nickname = ""
self.alternateNames = []
self.gender = Person.female
self.death = Event()
self.birth = Event()
self.addressList = []
self.attributeList = []
self.urls = []
self.note = ""
self.paf_uid = ""
def setPrimaryName(self,name) :
self.PrimaryName = name
def getPrimaryName(self) :
return self.PrimaryName
def setPafUid(self,val) :
self.paf_uid = val
def getPafUid(self) :
return self.paf_uid
def getAlternateNames(self):
return self.alternateNames
def addAlternateName(self,name):
self.alternateNames.append(name)
def getUrlList(self):
return self.urls
def addUrl(self,url):
self.urls.append(url)
def setId(self,id) :
self.id = id
def getId(self) :
return self.id
def setNickName(self,name) :
self.nickname = name
def getNickName(self) :
return self.nickname
def setGender(self,val) :
self.gender = val
def getGender(self) :
return self.gender
def setBirth(self,event) :
self.birth = event
def setDeath(self,event) :
self.death = event
def getBirth(self) :
return self.birth
def getDeath(self) :
return self.death
def addPhoto(self,photo):
self.photoList.append(photo)
def getPhotoList(self):
return self.photoList
def addEvent(self,event) :
self.EventList.append(event)
def getEventList(self) :
return self.EventList
def addFamily(self,family) :
self.FamilyList.append(family)
def getFamilyList(self) :
return self.FamilyList
def removeFamily(self,family):
index = 0
for fam in self.FamilyList:
if fam == family:
del self.FamilyList[index]
return
index = index + 1
def addAddress(self,address) :
self.addressList.append(address)
def removeAddress(self,address):
index = 0
for addr in self.addressList:
if addr == address:
del self.addressList[index]
return
index = index + 1
def getAddressList(self) :
return self.addressList
def addAttribute(self,attribute) :
self.attributeList.append(attribute)
def removeAttribute(self,attribute):
index = 0
for attr in self.attributeList:
if attr == attribute:
del self.attributeList[index]
return
index = index + 1
def getAttributeList(self) :
return self.attributeList
def getAltFamilyList(self) :
return self.AltFamilyList
def addAltFamily(self,family,type) :
self.AltFamilyList.append((family,type))
def removeAltFamily(self,family):
index = 0
for fam in self.AltFamilyList:
if fam[0] == family:
del self.AltFamilyList[index]
return
index = index + 1
def getFamilyIndex(self,index) :
return self.FamilyList[index]
def setMainFamily(self,family) :
self.MainFamily = family
def getMainFamily(self) :
return self.MainFamily
def setNote(self,text):
self.note = text
def getNote(self):
return self.note
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Event:
def __init__(self):
self.place = ""
self.date = Date()
self.description = ""
self.name = ""
self.source = None
def set(self,name,date,place,description):
self.name = name
self.place = place
self.description = description
self.setDate(date)
def compare(self,other):
if other == None:
return 1
c = cmp(self.name,other.name)
if c == 0:
c = cmp(self.place,other.place)
if c == 0:
c = compare_dates(self.date,other.date)
if c == 0:
return cmp(self.description,other.description)
return c
def setName(self,name) :
self.name = name
def getName(self) :
return self.name
def setSource(self,id) :
self.source = id
def getSource(self) :
return self.source
def setPlace(self,place) :
self.place = place
def getPlace(self) :
return self.place
def setDescription(self,description) :
self.description = description
def getDescription(self) :
return self.description
def setDate(self, date) :
self.date.set(date)
def getDate(self) :
return self.date.getDate()
def getDateObj(self) :
return self.date
def getSaveDate(self) :
return self.date.getSaveDate()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Family:
def __init__(self):
self.Father = None
self.Mother = None
self.Children = []
self.Marriage = None
self.Divorce = None
self.EventList = []
self.id = -1
self.photoList = []
def setId(self,id) :
self.id = id
def getId(self) :
return self.id
def setFather(self,person):
self.Father = person
def getFather(self):
return self.Father
def setMother(self,person):
self.Mother = person
def getMother(self):
return self.Mother
def addChild(self,person):
if person not in self.Children:
self.Children.append(person)
def removeChild(self,person):
index = 0
for child in self.Children:
if child == person:
del self.Children[index]
return
index = index + 1
def getChildList(self):
return self.Children
def setMarriage(self,event):
self.Marriage = event
def getMarriage(self):
return self.Marriage
def setDivorce(self,event):
self.Divorce = event
def getDivorce(self):
return self.Divorce
def addEvent(self,event) :
self.EventList.append(event)
def getEventList(self) :
return self.EventList
def addPhoto(self,photo):
self.photoList.append(photo)
def getPhotoList(self):
return self.photoList
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class SourceBase:
def __init__(self):
self.title = ""
self.author = ""
self.pubinfo = ""
self.callno = ""
def setId(self,newId):
self.id = newId
def getId(self):
return self.id
def setTitle(self,title):
self.title = title
def getTitle(self):
return self.title
def setAuthor(self,author):
self.author = author
def getAuthor(self):
return self.author
def setPubInfo(self,text):
self.pubinfo = text
def getPubInfo(self):
return self.pubinfo
def setCallNumber(self,val):
self.callno = val
def getCallNumber(self):
return self.callno
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Source:
def __init__(self):
self.ref = None
self.page = ""
self.date = Date()
self.comments = ""
self.text = ""
def setBase(self,ref):
self.ref = ref
def getBase(self):
return self.ref
def setDate(self,date):
self.date = date
def getDate(self):
return self.date
def setPage(self,page):
self.page = page
def getPage(self):
return self.page
def getDate(self):
return self.date
def setText(self,text):
self.text = text
def getText(self):
return self.text
def setComments(self,comments):
self.comments = comments
def getComments(self):
return self.comments
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class RelDataBase:
def __init__(self):
self.new()
def new(self):
self.personMap = {}
self.familyMap = {}
self.sourceMap = {}
self.smapIndex = 0
self.pmapIndex = 0
self.fmapIndex = 0
self.default = None
self.owner = Researcher()
self.bookmarks = []
self.path = ""
def clean_bookmarks(self):
new_bookmarks = []
for person in self.bookmarks:
new_bookmarks.append(person)
self.bookmarks = new_bookmarks
def setResearcher(self,owner):
self.owner.set(owner.getName(),owner.getAddress(),owner.getCity(),\
owner.getState(),owner.getCountry(),\
owner.getPostalCode(),owner.getPhone(),owner.getEmail())
def getResearcher(self):
return self.owner
def setDefaultPerson(self,person):
self.default = person
def getDefaultPerson(self):
return self.default
def getPersonMap(self):
return self.personMap
def setPersonMap(self,map):
self.personMap = map
def getFamilyMap(self):
return self.familyMap
def setFamilyMap(self,map):
self.familyMap = map
def getSavePath(self):
return self.path
def setSavePath(self,path):
self.path = path
def getSourceMap(self):
return self.sourceMap
def addPerson(self,person):
index = self.pmapIndex
person.setId(index)
self.personMap[index] = person
self.pmapIndex = self.pmapIndex + 1
return index
def getPersonEventTypes(self):
map = {}
for person in self.personMap.values():
for event in person.getEventList():
map[event.getName()] = 1
return map.keys()
def getPersonAttributeTypes(self):
map = {}
for person in self.personMap.values():
for attr in person.getAttributeList():
map[attr.getType()] = 1
return map.keys()
def findPerson(self,idVal,map):
if map.has_key(idVal):
person = self.personMap[map[idVal]]
else:
person = Person()
map[idVal] = self.addPerson(person)
return person
def addPersonNoMap(self,person,id):
person.setId(id)
self.personMap[id] = person
self.pmapIndex = max(self.pmapIndex,id)+1
return id
def findPersonNoMap(self,idVal):
val = int(idVal)
if self.personMap.has_key(val):
person = self.personMap[val]
else:
person = Person()
self.addPersonNoMap(person,val)
return person
def getNextPersonId(self):
return self.pmapIndex
def getNextFamilyId(self):
return self.fmapIndex
def getNextSourceId(self):
return self.smapIndex
def addSource(self,source):
index = self.smapIndex
source.setId(index)
self.sourceMap[index] = source
self.smapIndex = self.smapIndex + 1
return index
def findSource(self,idVal,map):
if map.has_key(idVal):
source = self.sourceMap[map[idVal]]
else:
source = SourceBase()
map[idVal] = self.addSource(source)
return source
def addSourceNoMap(self,source,index):
source.setId(index)
self.sourceMap[index] = source
self.smapIndex = max(self.smapIndex,index) + 1
return index
def findSourceNoMap(self,idVal):
val = int(idVal)
if self.sourceMap.has_key(val):
source = self.sourceMap[val]
else:
source = SourceBase()
self.addSourceNoMap(source,val)
return source
def newFamily(self):
id = self.fmapIndex
self.fmapIndex = self.fmapIndex + 1
family = Family()
family.setId(id)
self.familyMap[id] = family
return family
def newFamilyNoMap(self,id):
self.fmapIndex = max(self.fmapIndex,id) + 1
family = Family()
family.setId(id)
self.familyMap[id] = family
return family
def findFamily(self,idVal,map):
if map.has_key(idVal):
family = self.familyMap[map[idVal]]
else:
family = self.newFamily()
map[idVal] = family.getId()
return family
def findFamilyNoMap(self,idVal):
val = int(idVal)
if self.familyMap.has_key(val):
family = self.familyMap[val]
else:
family = self.newFamilyNoMap(val)
return family
def deleteFamily(self,family):
if self.familyMap.has_key(family.getId()):
del self.familyMap[family.getId()]

69
gramps/src/Researcher.py Normal file
View File

@@ -0,0 +1,69 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import string
class Researcher:
def __init__(self):
self.name = ""
self.addr = ""
self.city = ""
self.state = ""
self.country = ""
self.postal = ""
self.phone = ""
self.email = ""
def getName(self):
return self.name
def getAddress(self):
return self.addr
def getCity(self):
return self.city
def getState(self):
return self.state
def getCountry(self):
return self.country
def getPostalCode(self):
return self.postal
def getPhone(self):
return self.phone
def getEmail(self):
return self.email
def set(self,name,addr,city,state,country,postal,phone,email):
self.name = string.strip(name)
self.addr = string.strip(addr)
self.city = string.strip(city)
self.state = string.strip(state)
self.country = string.strip(country)
self.postal = string.strip(postal)
self.phone = string.strip(phone)
self.email = string.strip(email)

331
gramps/src/Sources.py Normal file
View File

@@ -0,0 +1,331 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
import os
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gtk import *
from gnome.ui import *
import libglade
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import utils
from RelLib import *
#-------------------------------------------------------------------------
#
# constants
#
#-------------------------------------------------------------------------
SOURCEDISP = "s"
ACTIVESRC = "a"
INDEX = "i"
#-------------------------------------------------------------------------
#
# SourceEditor
#
#-------------------------------------------------------------------------
class SourceEditor:
#---------------------------------------------------------------------
#
# __init__ - Creates a source editor window associated with an event
#
#---------------------------------------------------------------------
def __init__(self,active_event,database):
self.db = database
self.active_event = active_event
self.showSource = libglade.GladeXML(const.gladeFile, "sourceDisplay")
self.showSource.signal_autoconnect({
"on_sourceok_clicked" : on_sourceok_clicked,
"on_selectsource_clicked" : on_selectsource_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
self.sourceDisplay = self.get_widget("sourceDisplay")
self.source_field = self.get_widget("sourceList")
self.title_field = self.get_widget("stitle")
self.author_field = self.get_widget("sauthor")
self.pub_field = self.get_widget("spubinfo")
self.callno_field = self.get_widget("scallno")
self.source = active_event.getSource()
self.active_source = None
self.draw()
self.sourceDisplay.set_data(SOURCEDISP,self)
self.sourceDisplay.show()
#---------------------------------------------------------------------
#
# get_widget - returns the widget associated with the specified name
#
#---------------------------------------------------------------------
def get_widget(self,name):
return self.showSource.get_widget(name)
def draw(self):
if self.source:
self.get_widget("spage").set_text(self.source.getPage())
date = self.source.getDate()
if date:
self.get_widget("sdate").set_text(date.getDate())
text = self.get_widget("stext")
text.set_point(0)
text.insert_defaults(self.source.getText())
text.set_word_wrap(1)
scom = self.get_widget("scomment")
scom.set_point(0)
scom.insert_defaults(self.source.getComments())
scom.set_word_wrap(1)
srcRef = self.source.getBase()
self.active_source = srcRef
if srcRef:
self.title_field.set_text(srcRef.getTitle())
self.author_field.set_text(srcRef.getAuthor())
self.pub_field.set_text(srcRef.getPubInfo())
self.callno_field.set_text(srcRef.getCallNumber())
else:
self.title_field.set_text("")
self.author_field.set_text("")
self.pub_field.set_text("")
self.callno_field.set_text("")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_sourceok_clicked(obj):
src_edit = obj.get_data(SOURCEDISP)
if src_edit.active_event:
current_source = src_edit.active_event.getSource()
if current_source == None:
if src_edit.active_source:
current_source = Source()
src_edit.active_event.setSource(current_source)
else:
return
if src_edit.active_source != current_source.getBase():
src_edit.active_event.getSource().setBase(src_edit.active_source)
utils.modified()
if current_source.getBase() != src_edit.active_source:
current_source.setBase(src_edit.active_source)
utils.modified()
page = src_edit.get_widget("spage").get_text()
date = src_edit.get_widget("sdate").get_text()
text = src_edit.get_widget("stext").get_chars(0,-1)
comments = src_edit.get_widget("scomment").get_chars(0,-1)
current_source.setPage(page)
current_source.getDate().set(date)
current_source.setText(text)
current_source.setComments(comments)
utils.modified()
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_selectsource_clicked(obj):
src_edit = obj.get_data(SOURCEDISP)
SourceChoose(src_edit)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class SourceChoose:
def __init__(self,source_info):
self.db = source_info.db
self.source_info = source_info
self.active_source = source_info.active_source
self.selSrc = libglade.GladeXML(const.gladeFile, "sourceEditor")
self.selSrc.signal_autoconnect({
"on_addsource_clicked" : on_addsource_clicked,
"on_updatesource_clicked" : on_updatesource_clicked,
"on_deletesource_clicked" : on_deletesource_clicked,
"on_sourceapply_clicked" : on_sourceapply_clicked,
"on_sourceList_select_row" : on_sourceList_select_row,
"destroy_passed_object" : utils.destroy_passed_object
})
self.title_field = self.selSrc.get_widget("source_title")
self.author_field = self.selSrc.get_widget("author")
self.pub_field = self.selSrc.get_widget("pubinfo")
self.callno_field = self.selSrc.get_widget("callno")
self.src_list = self.selSrc.get_widget("sourceList")
if source_info.active_source:
actsrc = source_info.active_source
self.title_field.set_text(actsrc.getTitle())
self.author_field.set_text(actsrc.getAuthor())
self.pub_field.set_text(actsrc.getPubInfo())
self.callno_field.set_text(actsrc.getCallNumber())
self.active_source = source_info.active_source
self.src_list.set_data(ACTIVESRC,self)
self.src_list.set_data(INDEX,-1)
self.redraw_sources()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def redraw_sources(self):
self.src_list.clear()
self.src_list.freeze()
current_row = -1
self.index = 0
for src in self.db.getSourceMap().values():
self.src_list.append([src.getTitle(),src.getAuthor()])
self.src_list.set_row_data(self.index,src)
if self.active_source == src:
current_row = self.index
self.index = self.index + 1
self.src_list.select_row(current_row,0)
self.src_list.moveto(current_row,0)
self.src_list.set_data(INDEX,current_row)
self.src_list.thaw()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_addsource_clicked(obj):
src_obj = obj.get_data(ACTIVESRC)
src_obj.active_source = SourceBase()
title = src_obj.title_field.get_text()
author = src_obj.author_field.get_text()
src_obj.src_list.append([title,author])
src_obj.db.addSource(src_obj.active_source)
src_obj.active_source.setTitle(title)
src_obj.active_source.setAuthor(author)
src_obj.active_source.setCallNumber(src_obj.callno_field.get_text())
src_obj.active_source.setPubInfo(src_obj.pub_field.get_text())
src_obj.redraw_sources()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_deletesource_clicked(obj):
src_obj = obj.get_data(ACTIVESRC)
src_obj.active_source = None
obj.set_data(INDEX,-1)
src_obj.redraw_sources()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_updatesource_clicked(obj):
src_obj = obj.get_data(ACTIVESRC)
if src_obj.active_source:
src_obj.active_source.setTitle(src_obj.title_field.get_text())
src_obj.active_source.setAuthor(src_obj.author_field.get_text())
src_obj.active_source.setCallNumber(src_obj.callno_field.get_text())
src_obj.active_source.setPubInfo(src_obj.pub_field.get_text())
src_obj.redraw_sources()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_sourceList_select_row(obj,row,b,c):
obj.set_data(INDEX,row)
src_obj = obj.get_data(ACTIVESRC)
src_obj.active_source = obj.get_row_data(row)
select_source = src_obj.active_source
if select_source:
src_obj.title_field.set_text(select_source.getTitle())
src_obj.author_field.set_text(select_source.getAuthor())
src_obj.pub_field.set_text(select_source.getPubInfo())
src_obj.callno_field.set_text(select_source.getCallNumber())
else:
src_obj.title_field.set_text("")
src_obj.author_field.set_text("")
src_obj.pub_field.set_text("")
src_obj.callno_field.set_text("")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_sourceapply_clicked(obj):
row = obj.get_data(INDEX)
src_obj = obj.get_data(ACTIVESRC)
src_obj.active_source = obj.get_row_data(row)
if row == -1:
src_obj.active_source = None
elif not src_obj.active_source:
src_obj.active_source = Source()
if not src_obj.source_info.source:
src_obj.source_info.source = Source()
src_obj.source_info.source.setBase(src_obj.active_source)
src_obj.source_info.draw()
utils.destroy_passed_object(src_obj.selSrc.get_widget("sourceEditor"))

426
gramps/src/TextDoc.py Normal file
View File

@@ -0,0 +1,426 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
FONT_SANS_SERIF = 0
FONT_SERIF = 1
PAPER_US_LETTER = 0
PAPER_A4 = 1
PAPER_PORTRAIT = 0
PAPER_LANDSCAPE = 1
PARA_ALIGN_CENTER = 0
PARA_ALIGN_LEFT = 1
PARA_ALIGN_RIGHT = 2
PARA_ALIGN_JUSTIFY= 3
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class PaperStyle:
def __init__(self,name,height,width):
self.name = name
self.orientation = PAPER_PORTRAIT
self.height = height
self.width = width
def get_name(self):
return self.name
def get_orientation(self):
return self.orientation
def set_orientation(self,val):
self.orientation = val
def get_height(self):
return self.height
def get_width(self):
return self.width
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class FontStyle:
def __init__(self, style=None):
if style:
self.face = style.face
self.size = style.size
self.italic = style.italic
self.bold = style.bold
self.color = style.color
self.under = style.under
else:
self.face = FONT_SERIF
self.size = 12
self.italic = 0
self.bold = 0
self.color = (0,0,0)
self.under = 0
def set_italic(self,val):
"0 disables italics, 1 enables italics"
self.italic = val
def get_italic(self):
"1 indicates use italics"
return self.italic
def set_bold(self,val):
"0 disables bold face, 1 enables bold face"
self.bold = val
def get_bold(self):
"1 indicates use bold face"
return self.bold
def set_color(self,val):
"sets the color using an RGB color tuple"
self.color = val
def get_color(self):
"Returns an RGB color tuple"
return self.color
def set_size(self,val):
"sets font size in points"
self.size = val
def get_size(self):
"returns font size in points"
return self.size
def set_type_face(self,val):
"sets the font face type"
self.face = val
def get_type_face(self):
"returns the font face type"
return self.face
def set_underline(self,val):
"1 enables underlining"
self.under = val
def get_underline(self):
"1 indicates underlining"
return self.under
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class TableStyle:
def __init__(self,obj=None):
if obj:
self.width = obj.width
self.columns = obj.columns
self.colwid = obj.colwid[:]
else:
self.width = 0
self.columns = 0
self.colwid = [ 0 ] * 10
# self.cells = {}
# def add_cell_style(self,name,style):
# self.cells[name] = style
# def get_cell_styles(self,name,style):
# return self.cells
def set_width(self,width):
self.width = width
def get_width(self):
return self.width
def set_columns(self,columns):
self.columns = columns
def get_columns(self):
return self.columns
def set_column_width(self,index,width):
self.colwid[index] = width
def get_column_width(self,index):
return self.colwid[index]
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class TableCellStyle:
def __init__(self,obj=None):
if obj:
self.rborder = obj.rborder
self.lborder = obj.lborder
self.tborder = obj.tborder
self.bborder = obj.bborder
self.padding = obj.padding
else:
self.rborder = 0
self.lborder = 0
self.tborder = 0
self.bborder = 0
self.padding = 0
def set_padding(self,val):
self.padding = val
def set_right_border(self,val):
self.rborder = val
def set_left_border(self,val):
self.lborder = val
def set_top_border(self,val):
self.tborder = val
def set_bottom_border(self,val):
self.bborder = val
def get_padding(self):
return self.padding
def get_right_border(self):
return self.rborder
def get_left_border(self):
return self.lborder
def get_top_border(self):
return self.tborder
def get_bottom_border(self):
return self.bborder
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class ParagraphStyle:
def __init__(self,p=None):
if p:
self.font = FontStyle(p.font)
self.rmargin = p.rmargin
self.lmargin = p.lmargin
self.first_indent = p.first_indent
self.align = p.align
self.level = p.level
self.top_border = p.top_border
self.bottom_border = p.bottom_border
self.right_border = p.right_border
self.left_border = p.left_border
self.pad = p.pad
else:
self.font = FontStyle()
self.rmargin = 0
self.lmargin = 0
self.first_indent = 0
self.align = PARA_ALIGN_LEFT
self.level = 0
self.top_border = 0
self.bottom_border = 0
self.right_border = 0
self.left_border = 0
self.pad = 0
self.actfont = self.font
def set_header_level(self,level):
self.level = level
def get_header_level(self):
return self.level
def set_font(self,font):
self.font = FontStyle(font)
def get_font(self):
return FontStyle(self.font)
def set_padding(self,val):
self.pad = val
def get_padding(self):
return self.pad
def set_top_border(self,val):
self.top_border = val
def get_top_border(self):
return self.top_border
def set_bottom_border(self,val):
self.bottom_border = val
def get_bottom_border(self):
return self.bottom_border
def set_left_border(self,val):
self.left_border = val
def get_left_border(self):
return self.left_border
def set_right_border(self,val):
self.right_border = val
def get_right_border(self):
return self.right_border
def set_alignment(self,align):
self.align = align
def get_alignment(self):
return self.align
def set_left_margin(self,value):
"sets the left paragraph margin in centimeters"
self.lmargin = value
def set_right_margin(self,value):
"sets the right paragraph margin in centimeters"
self.rmargin = value
def set_first_indent(self,value):
"sets the first indent margin in centimeters"
self.first_indent = value
def get_left_margin(self):
"returns the left margin in centimeters"
return self.lmargin
def get_right_margin(self):
"returns the right margin in centimeters"
return self.rmargin
def get_first_indent(self):
"returns the first indent margin in centimeters"
return self.first_indent
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class TextDoc:
def __init__(self,type,orientation=PAPER_PORTRAIT):
self.orientation = orientation
if orientation == PAPER_PORTRAIT:
self.width = type.get_width()
self.height = type.get_height()
else:
self.width = type.get_height()
self.height = type.get_width()
self.tmargin = 2.54
self.bmargin = 2.54
self.lmargin = 2.54
self.rmargin = 2.54
self.font = FontStyle()
self.actfont = self.font
self.style_list = {}
self.table_styles = {}
self.cell_styles = {}
self.name = ""
def get_usable_width(self):
return self.width - (self.rmargin + self.lmargin)
def get_usable_height(self):
return self.height - (self.tmargin + self.bmargin)
def creator(self,name):
self.name = name
def add_style(self,name,style):
self.style_list[name] = ParagraphStyle(style)
def add_table_style(self,name,style):
self.table_styles[name] = TableStyle(style)
def add_cell_style(self,name,style):
self.cell_styles[name] = TableCellStyle(style)
def change_font(self,font):
self.actfont = FontStyle(font)
def restore_font(self):
self.actfont = self.font
def get_default_font(self):
return self.font
def get_active_font(self):
return self.actfont
def open(self,filename):
pass
def close(self):
pass
def start_page(self,orientation=None):
pass
def end_page(self):
pass
def start_paragraph(self,style_name):
pass
def end_paragraph(self):
pass
def start_table(self,name,style_name):
pass
def end_table(self):
pass
def start_row(self):
pass
def end_row(self):
pass
def start_cell(self,style_name,span=1):
pass
def end_cell(self):
pass
def horizontal_line(self):
pass
def write_text(self,text):
pass

339
gramps/src/WriteXML.py Normal file
View File

@@ -0,0 +1,339 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from RelLib import *
from Researcher import *
import const
import string
import time
import gzip
import shutil
import os
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def sortById(first,second):
fid = first.getId()
sid = second.getId()
if fid < sid:
return -1
else:
return fid != sid
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def fix(line):
l = string.strip(line)
l = string.replace(l,'&','&amp;')
l = string.replace(l,'>','&gt;')
l = string.replace(l,'<','&lt;')
return string.replace(l,'"','&quot;')
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def writeNote(g,val,note):
if not note:
return
g.write("<" + val + ">\n")
textlines = string.split(note[:-1],'\n')
for line in textlines:
g.write("<p>" + fix(line) + "</p>\n")
g.write("</" + val + ">\n")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def dump_event(g,event):
if event:
dump_my_event(g,event.getName(),event)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def dump_my_event(g,name,event):
if not event:
return
date = event.getSaveDate()
place = event.getPlace()
description = event.getDescription()
if not date and not place and not description:
return
g.write("<event type=\"" + fix(name) + "\">\n")
write_line(g,"date",date)
write_line(g,"place",place)
write_line(g,"description",description)
source = event.getSource()
if source:
sourceRef = source.getBase()
if sourceRef:
g.write("<sourceref ref=\"%d\">\n" % sourceRef.getId())
write_line(g,"spage",source.getPage())
writeNote(g,"scomments",source.getComments())
writeNote(g,"stext",source.getText())
write_line(g,"sdate",source.getDate().getSaveDate())
g.write("</sourceref>\n")
g.write("</event>\n")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def write_ref(g,label,person):
if person:
g.write("<" + label + " ref=\"" + str(person.getId()) + "\"/>\n")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def write_id(g,label,person):
if person:
g.write("<" + label + " id=\"" + str(person.getId()) + "\">\n")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def write_line(g,label,value):
if value:
g.write("<" + label + ">" + fix(value) + "</" + label + ">\n")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def dump_name(g,label,name):
g.write("<" + label + ">\n")
write_line(g,"first",name.getFirstName())
write_line(g,"last",name.getSurname())
write_line(g,"suffix",name.getSuffix())
write_line(g,"title",name.getTitle())
g.write("</" + label + ">\n")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def exportData(database, filename, callback):
global db
db = database
date = string.split(time.ctime(time.time()))
fileroot = os.path.dirname(filename)
owner = database.getResearcher()
personList = database.getPersonMap().values()
personList.sort(sortById)
familyList = database.getFamilyMap().values()
familyList.sort(sortById)
sourceList = database.getSourceMap().values()
sourceList.sort(sortById)
total = len(personList) + len(familyList)
if os.path.isfile(filename):
shutil.copy(filename, filename + ".bak")
g = gzip.open(filename,"wb")
g.write("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n")
g.write("<database>\n")
g.write("<header>\n")
g.write("<created date=\"%s %s %s\"" % (date[2],string.upper(date[1]),date[4]))
g.write(" version=\"" + const.version + "\"")
g.write(" people=\"%d\"" % (len(database.getPersonMap().values())))
g.write(" families=\"%d\"/>\n" % len(database.getFamilyMap().values()))
g.write("<researcher>\n")
write_line(g,"resname",owner.getName())
write_line(g,"resaddr",owner.getAddress())
write_line(g,"rescity",owner.getCity())
write_line(g,"resstate",owner.getState())
write_line(g,"rescountry",owner.getCountry())
write_line(g,"respostal",owner.getPostalCode())
write_line(g,"resphone",owner.getPhone())
write_line(g,"resemail",owner.getEmail())
g.write("</researcher>\n")
g.write("</header>\n")
g.write("<people")
person = database.getDefaultPerson()
if person:
g.write(" default=\"" + str(person.getId()) + "\"")
g.write(">\n")
total = len(personList) + len(familyList)
delta = max(int(total/50),1)
count = 0
for person in personList:
if count % delta == 0:
callback(float(count)/float(total))
count = count + 1
write_id(g,"person",person)
if person.getGender() == Person.male:
write_line(g,"gender","M")
else:
write_line(g,"gender","F")
dump_name(g,"name",person.getPrimaryName())
for name in person.getAlternateNames():
dump_name(g,"aka",name)
write_line(g,"uid",person.getPafUid())
write_line(g,"nick",person.getNickName())
dump_my_event(g,"Birth",person.getBirth())
dump_my_event(g,"Death",person.getDeath())
for event in person.getEventList():
dump_event(g,event)
for photo in person.getPhotoList():
path = photo.getPath()
if os.path.dirname(path) == fileroot:
path = os.path.basename(path)
g.write("<img src=\"" + fix(path) + "\"")
g.write(" descrip=\"" + fix(photo.getDescription()) + "\"/>\n")
if len(person.getAddressList()) > 0:
g.write("<addresses>\n")
for address in person.getAddressList():
g.write('<address>\n')
g.write('<date_start>')
g.write(address.getStartDateObj().getSaveDate())
g.write('<date_start>\n')
g.write('<date_stop>')
g.write(address.getStopDateObj().getSaveDate())
g.write('<date_stop>\n')
write_line(g,"street",address.getStreet())
write_line(g,"city",address.getCity())
write_line(g,"state",address.getState())
write_line(g,"country",address.getCountry())
write_line(g,"postal",address.getPostal())
g.write('</address>\n')
g.write('</addresses>\n')
if len(person.getAttributeList()) > 0:
g.write("<attributes>\n")
for attr in person.getAttributeList():
g.write('<attribute type="%s">' % attr.getType())
g.write(fix(attr.getValue()))
g.write('</attribute>\n')
g.write('</attributes>\n')
if len(person.getUrlList()) > 0:
g.write("<urls>\n")
for url in person.getUrlList():
g.write('<url href="' + url.get_path() + '"')
if url.get_description() != "":
g.write(' description="' + url.get_description() + '"')
g.write('/>\n')
g.write('</urls>\n')
write_ref(g,"childof",person.getMainFamily())
for alt in person.getAltFamilyList():
g.write("<childof ref=\"" + str(alt[0].getId()))
g.write("\" type=\"" + alt[1] + "\"/>\n")
for family in person.getFamilyList():
write_ref(g,"parentin",family)
writeNote(g,"note",person.getNote())
g.write("</person>\n")
g.write("</people>\n")
g.write("<families>\n")
for family in familyList:
if count % delta == 0:
callback(float(count)/float(total))
count = count + 1
write_id(g,"family",family)
write_ref(g,"father",family.getFather())
write_ref(g,"mother",family.getMother())
dump_event(g,family.getMarriage())
dump_event(g,family.getDivorce())
for event in family.getEventList():
dump_event(g,event)
for photo in family.getPhotoList():
path = photo.getPath()
if os.path.dirname(path) == fileroot:
path = os.path.basename(path)
g.write("<img src=\"" + fix(path) + "\"")
g.write(" descrip=\"" + fix(photo.getDescription()) + "\"/>\n")
if len(family.getChildList()) > 0:
g.write("<childlist>\n")
for person in family.getChildList():
write_ref(g,"child",person)
g.write("</childlist>\n")
g.write("</family>\n")
g.write("</families>\n")
if len(sourceList) > 0:
g.write("<sources>\n")
for source in sourceList:
g.write("<source id=\"" + str(source.getId()) + "\">\n")
write_line(g,"stitle",source.getTitle())
write_line(g,"sauthor",source.getAuthor())
write_line(g,"spubinfo",source.getPubInfo())
write_line(g,"scallno",source.getCallNumber())
g.write("</source>\n")
g.write("</sources>\n")
if len(db.bookmarks) > 0:
g.write("<bookmarks>\n")
for person in db.bookmarks:
g.write("<bookmark ref=\"" + str(person.getId()) + "\"/>\n")
g.write("</bookmarks>\n")
g.write("</database>\n")
g.close()

248
gramps/src/bookmarks.glade Normal file
View File

@@ -0,0 +1,248 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>bookmarks</name>
<program_name>bookmarks</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GtkDialog</class>
<name>top</name>
<title>Gramps - Edit Bookmarks</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>True</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
<class>GtkVBox</class>
<child_name>Dialog:vbox</child_name>
<name>dialog-vbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkHBox</class>
<child_name>Dialog:action_area</child_name>
<name>dialog-action_area1</name>
<border_width>10</border_width>
<homogeneous>True</homogeneous>
<spacing>5</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkHButtonBox</class>
<name>hbuttonbox1</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>30</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkButton</class>
<name>ok</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_ok_clicked</handler>
<object>top</object>
<last_modification_time>Wed, 14 Feb 2001 20:10:00 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>cancel</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_cancel_clicked</handler>
<object>top</object>
<last_modification_time>Wed, 14 Feb 2001 20:10:25 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>bookmarksTitle</name>
<label>Edit Bookmarks</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator1</name>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow1</name>
<hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkCList</class>
<name>namelist</name>
<width>250</width>
<height>150</height>
<can_focus>True</can_focus>
<signal>
<name>select_row</name>
<handler>on_namelist_select_row</handler>
<last_modification_time>Wed, 14 Feb 2001 20:08:50 GMT</last_modification_time>
</signal>
<columns>1</columns>
<column_widths>80</column_widths>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<show_titles>False</show_titles>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label2</name>
<label>label2</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
<widget>
<class>GtkVButtonBox</class>
<name>vbuttonbox1</name>
<layout_style>GTK_BUTTONBOX_START</layout_style>
<spacing>10</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkButton</class>
<name>up</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_up_clicked</handler>
<object>namelist</object>
<last_modification_time>Wed, 14 Feb 2001 20:09:13 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_UP</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>down</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_down_clicked</handler>
<object>namelist</object>
<last_modification_time>Wed, 14 Feb 2001 20:09:23 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_DOWN</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>delete</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_delete_clicked</handler>
<object>namelist</object>
<last_modification_time>Wed, 14 Feb 2001 20:09:35 GMT</last_modification_time>
</signal>
<label>Delete</label>
</widget>
</widget>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

10
gramps/src/build_po Executable file
View File

@@ -0,0 +1,10 @@
#! /bin/sh
mv template.po template.po.bak
echo "Working on the glade files"
libglade-xgettext -c -o glade.c *.glade
echo "Working on python files"
./get_strings *.py >> glade.c
echo "Building template.po"
xgettext -C -s -a -o template.po glade.c
rm glade.c

1694
gramps/src/config.glade Normal file

File diff suppressed because it is too large Load Diff

161
gramps/src/const.py Normal file
View File

@@ -0,0 +1,161 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import os
import intl
_ = intl.gettext
#-------------------------------------------------------------------------
#
# Paths to external programs
#
#-------------------------------------------------------------------------
editor = "gimp"
zipcmd = "/usr/bin/zip -r -q"
convert = "/usr/X11R6/bin/convert"
#-------------------------------------------------------------------------
#
# Exceptions
#
#-------------------------------------------------------------------------
OpenFailed = "Open Failed"
#-------------------------------------------------------------------------
#
# Paths to files - assumes that files reside in the same directory as
# this one, and that the plugins directory is in a directory below this.
#
#-------------------------------------------------------------------------
rootDir = os.path.dirname(__file__)
logo = rootDir + os.sep + "gramps.xpm"
gladeFile = rootDir + os.sep + "gramps.glade"
imageselFile = rootDir + os.sep + "imagesel.glade"
marriageFile = rootDir + os.sep + "marriage.glade"
editPersonFile = rootDir + os.sep + "EditPerson.glade"
bookFile = rootDir + os.sep + "bookmarks.glade"
pluginsFile = rootDir + os.sep + "plugins.glade"
configFile = rootDir + os.sep + "config.glade"
pluginsDir = rootDir + os.sep + "plugins"
filtersDir = rootDir + os.sep + "filters"
dataDir = rootDir + os.sep + "data"
gtkrcFile = rootDir + os.sep + "gtkrc"
#-------------------------------------------------------------------------
#
# About box information
#
#-------------------------------------------------------------------------
progName = "gramps"
version = "0.1.4pre"
copyright = "(C) 2001 Donald N. Allingham"
authors = ["Donald N. Allingham"]
comments = _("Gramps (Genealogical Research and Analysis Management ") +\
_("Programming System) is a personal genealogy program that ") +\
_("can be extended by using the Python programming language.")
#-------------------------------------------------------------------------
#
# Enable/disable exceptions. For debugging purposes
#
#-------------------------------------------------------------------------
useExceptions= 0
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
picWidth = 200.0
thumbScale = 100.0
indexFile = "data.gramps"
male = _("male")
female = _("female")
helpMenu = "contents.html"
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
childRelations = [
"Biological",
"Adopted",
"Other"
]
familyConstantEvents = {
"Annulment" : "ANUL",
"Divorce Filing" : "DIVF",
"Divorce" : "DIV",
"Engagement" : "ENGA",
"Marriage Contract" : "MARC",
"Marriage License" : "MARL",
"Marriage Settlement" : "MARS",
"Marriage" : "MARR"
}
personalConstantEvents = {
"Adopted" : "ADOP",
"Alternate Birth" : "BIRT",
"Alternate Death" : "DEAT",
"Baptism (LDS)" : "BAPL",
"Baptism" : "BAPM",
"Bar Mitzvah" : "BARM",
"Bas Mitzvah" : "BASM",
"Burial" : "BURI",
"Cause Of Death" : "CAUS",
"Census" : "CENS",
"Christening" : "CHR" ,
"Confirmation" : "CONF",
"Cremation" : "CREM",
"Degree" : "_DEG",
"Divorce Filing" : "DIVF",
"Education" : "EDUC",
"Elected" : "_ELEC",
"Emigration" : "EMIG",
"Graduation" : "GRAD",
"Military Service" : "_MILT",
"Naturalization" : "NATU",
"Occupation" : "OCCU",
"Probate" : "PROB",
"Religion" : "RELI",
"Residence" : "RESI",
"Residence" : "RESI",
"Retirement" : "RETI"
}
personalConstantAttributes = {
"Description" : "DSCR",
"Indentification Number": "IDNO",
"Social Security Number": "SSN"
}
personalEvents = personalConstantEvents.keys()
personalEvents.sort()
personalAttributes = personalConstantAttributes.keys()
personalAttributes.sort()
marriageEvents = familyConstantEvents.keys()
marriageEvents.sort()

View File

@@ -0,0 +1,24 @@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
datadir = @datadir@/@PACKAGE@
INSTALL = @INSTALL@
data = ${datadir}
pycomp = ${srcdir}/py-compile
@SET_MAKE@
all:
install:
-mkdir ${data}
${INSTALL} -c *.sxw ${data}
uninstall:
rm ${data}/*.sxw
-rmdir ${data}
clean:
-rm -f core *.pyo *.pyc *.bak *~

96
gramps/src/data/chart.sxd Normal file
View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<office:document office:class="drawing" office:version="0.9" xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:presentation="http://openoffice.org/2000/presentation" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart">
<office:meta>
<meta:generator>Gramps</meta:generator>
<meta:initial-creator>Donald Allingham</meta:initial-creator>
<meta:creation-date>2001-01-26T11:12:22</meta:creation-date>
<dc:creator>Donald Allingham</dc:creator>
<dc:date>2001-01-26T11:34:34</dc:date>
<dc:language>en-US</dc:language>
<meta:editing-cycles>3</meta:editing-cycles>
<meta:editing-duration>PT0S</meta:editing-duration>
<meta:user-defined meta:name="Info 0"></meta:user-defined>
<meta:user-defined meta:name="Info 1"></meta:user-defined>
<meta:user-defined meta:name="Info 2"></meta:user-defined>
<meta:user-defined meta:name="Info 3"></meta:user-defined>
</office:meta>
<office:styles><draw:gradient draw:name="Standard 1" draw:style="linear" draw:start-color="#000000" draw:end-color="#ffffff" draw:start-intensity="100%" draw:end-intensity="100%" draw:angle="0" draw:border="0%"/><draw:hatch draw:name="Standard 1" draw:style="single" draw:color="#000000" draw:distance="0.02cm" draw:rotation="0"/><draw:fill-image draw:name="Standard 1" xlink:href="vnd.sun.star.GraphicObject:10000000000000400000004077CDC8F9" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad"/><draw:marker draw:name="Arrow" svg:viewBox="0 0 200 400" svg:d="100,0 200,400 0,400"/><draw:marker draw:name="Arrow" svg:viewBox="0 0 200 400" svg:d="100,0 200,400 0,400"/><draw:marker draw:name="Arrow" svg:viewBox="0 0 200 400" svg:d="100,0 200,400 0,400"/><draw:marker draw:name="Arrow" svg:viewBox="0 0 200 400" svg:d="100,0 200,400 0,400"/>
<style:style style:name="drawpool" style:family="default"><style:properties draw:stroke="solid" svg:stroke-width="0cm" svg:stroke-color="#000000" draw:marker-start="Standard 1" draw:marker-start-width="0.2cm" draw:marker-start-center="false" draw:marker-end="Standard 1" draw:marker-end-width="0.2cm" draw:marker-end-center="false" svg:stroke-opacity="0%" svg:stroke-linejoin="round" draw:fill="solid" draw:fill-color="#00b8ff" draw:fill-gradient-name="Standard 1" draw:gradient-step-count="0" draw:fill-hatch-name="Standard 1" draw:fill-image-name="Standard 1" draw:shadow="hidden" draw:shadow-offset-x="0cm" draw:shadow-offset-y="0cm" draw:shadow-color="#000000" draw:shadow-transparency="0%" fo:color="#000000" style:text-crossing-out="none" fo:font-size="24pt" fo:font-style="normal" style:text-underline="none" fo:font-weight="normal" fo:line-height="100%" fo:text-align="start" fo:hyphenate="false" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm"/>
</style:style>
<style:style style:name="standard" style:family="graphics" style:parent-style-name="drawpool">
<style:properties draw:stroke="solid" svg:stroke-width="0cm" svg:stroke-color="#000000" draw:marker-start="Standard 1" draw:marker-start-width="0.3cm" draw:marker-start-center="false" draw:marker-end="Standard 1" draw:marker-end-width="0.3cm" draw:marker-end-center="false" draw:fill="solid" draw:fill-color="#00b8ff" draw:fill-gradient-name="Standard 1" draw:fill-hatch-name="Standard 1" draw:fill-image-name="Standard 1" draw:shadow="hidden" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:shadow-color="#808080" fo:color="#000000" style:text-crossing-out="none" fo:font-size="24pt" fo:font-style="normal" style:text-underline="none" fo:font-weight="normal" fo:line-height="100%" fo:text-align="start" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm"/>
</style:style>
<style:style style:name="objectwitharrow" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="solid" svg:stroke-width="0.15cm" svg:stroke-color="#000000" draw:marker-start="Arrow" draw:marker-start-width="0.7cm" draw:marker-start-center="true" draw:marker-end-width="0.3cm"/>
</style:style>
<style:style style:name="objectwithshadow" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/>
</style:style>
<style:style style:name="objectwithoutfill" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:fill="none"/>
</style:style>
<style:style style:name="text" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none"/>
</style:style>
<style:style style:name="textbody" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:font-size="16pt"/>
</style:style>
<style:style style:name="textbodyjustfied" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:text-align="end"/>
</style:style>
<style:style style:name="textbodyindent" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:margin-left="0cm" fo:margin-right="0cm"/>
</style:style>
<style:style style:name="title" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:font-size="43pt"/>
</style:style>
<style:style style:name="title1" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="solid" draw:fill-color="#008080" draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080" fo:font-size="24pt" fo:text-align="justify"/>
</style:style>
<style:style style:name="title2" style:family="graphics" style:parent-style-name="standard">
<style:properties svg:stroke-width="0.05cm" draw:fill-color="#ffcc99" draw:shadow="visible" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080" fo:font-size="36pt" fo:text-align="justify" fo:margin-left="0cm" fo:margin-right="0.2cm" fo:margin-top="0.1cm" fo:margin-bottom="0.1cm"/>
</style:style>
<style:style style:name="headline" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:font-size="24pt" fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
</style:style>
<style:style style:name="headline1" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:font-size="18pt" fo:font-weight="bold" fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
</style:style>
<style:style style:name="headline2" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="none" draw:fill="none" fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" fo:margin-top="0.42cm" fo:margin-bottom="0.21cm"/>
</style:style>
<style:style style:name="measure" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:stroke="solid" draw:marker-start="Arrow" draw:marker-start-width="0.2cm" draw:marker-end="Arrow" draw:marker-end-width="0.2cm" draw:fill="none" fo:font-size="12pt"/>
</style:style>
<style:page-master style:name="PM0">
<style:properties fo:margin-top="0.423cm" fo:margin-bottom="0.623cm" fo:margin-left="0.635cm" fo:margin-right="0.665cm" fo:page-width="21.59cm" fo:page-height="27.94cm" fo:page-orientation="portrait"/>
</style:page-master>
<style:style style:name="P0" style:family="drawing-page"/>
</office:styles>
<office:automatic-styles>
<style:style style:name="gr1" style:family="graphics" style:parent-style-name="objectwithshadow">
<style:properties draw:fill="solid" draw:fill-color="#ffffff" fo:font-size="8pt" fo:margin-left="0cm" fo:margin-right="0cm"/>
</style:style>
<style:style style:name="gr2" style:family="graphics" style:parent-style-name="standard">
<style:properties fo:margin-left="0.6cm" fo:margin-right="0cm"/>
</style:style>
<style:style style:name="gr3" style:family="graphics" style:parent-style-name="standard">
<style:properties draw:marker-start="Standard 2" draw:marker-end="none" draw:marker-end-width="0.25cm" fo:margin-left="0.6cm" fo:margin-right="0cm"/>
</style:style>
<style:style style:name="P1" style:family="paragraph">
<style:properties fo:margin-left="0cm" fo:margin-right="0cm"/>
</style:style>
<style:style style:name="P2" style:family="paragraph">
<style:properties fo:margin-left="0.6cm" fo:margin-right="0cm"/>
</style:style>
<style:style style:name="T1" style:family="text">
<style:properties fo:font-family="Arial" fo:font-size="8pt"/>
</style:style>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Home" style:page-master-name="PM0"/>
</office:master-styles>
<office:body>
</office:body>
</office:document>

132
gramps/src/data/indsum.sxw Normal file
View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<office:document office:class="text" office:version="0.9" xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script">
<office:meta>
<meta:generator>StarOffice/5.2 (Linux)</meta:generator><!--619b(Build:6103)-->
<meta:initial-creator>Don Allingham</meta:initial-creator>
<meta:creation-date>2001-03-26T13:43:47</meta:creation-date>
<dc:creator>Don Allingham</dc:creator>
<dc:date>2001-03-26T13:52:36</dc:date>
<dc:language>en-US</dc:language>
<meta:editing-cycles>2</meta:editing-cycles>
<meta:editing-duration>PT0S</meta:editing-duration>
<meta:user-defined meta:name="Info 0"/>
<meta:user-defined meta:name="Info 1"/>
<meta:user-defined meta:name="Info 2"/>
<meta:user-defined meta:name="Info 3"/>
<meta:document-statistic meta:table-count="3" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="25" meta:word-count="26" meta:character-count="160"/>
</office:meta>
<office:script>
<script:library-embedded script:name="Standard"/>
</office:script>
<office:font-decls>
<style:font-decl style:name="Andale WT UI" fo:font-family="&apos;Andale WT UI&apos;, &apos;MS Mincho&apos;, &apos;HG Mincho L&apos;, &apos;MS PGothic&apos;, &apos;Arial Unicode MS&apos;"/>
<style:font-decl style:name="Simplified Arabic" fo:font-family="&apos;Simplified Arabic&apos;, &apos;Andale WT UI&apos;, &apos;Arial Unicode MS&apos;"/>
<style:font-decl style:name="Arial" fo:font-family="Arial"/>
<style:font-decl style:name="Times New Roman" fo:font-family="&apos;Times New Roman&apos;"/>
</office:font-decls>
<office:styles>
<style:default-style style:family="paragraph">
<style:properties fo:color="#000000" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:font-name-asian="Andale WT UI" style:font-size-asian="12pt" style:language-asian="none" style:country-asian="none" style:font-name-complex="Simplified Arabic" style:font-size-complex="12pt" style:language-complex="none" style:country-complex="none" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict">
<style:tab-stops>
<style:tab-stop style:position="22.05mm" style:type="default"/>
</style:tab-stops>
</style:properties>
</style:default-style>
<style:style style:name="Standard" style:family="paragraph" style:class="text"/>
<style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text body" style:class="text">
<style:properties style:font-name="Arial" fo:font-size="14pt" fo:margin-top="4.23mm" fo:margin-bottom="2.12mm" fo:keep-with-next="true"/>
</style:style>
<style:style style:name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
<style:properties fo:margin-top="0mm" fo:margin-bottom="2.12mm"/>
</style:style>
<style:style style:name="List" style:family="paragraph" style:parent-style-name="Text body" style:class="list">
<style:properties style:font-name="Times New Roman"/>
</style:style>
<style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
<style:properties style:font-name="Times New Roman" fo:font-size="10pt" fo:font-style="italic" fo:margin-top="2.12mm" fo:margin-bottom="2.12mm" text:number-lines="false" text:line-number="0"/>
</style:style>
<style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
<style:properties style:font-name="Times New Roman" text:number-lines="false" text:line-number="0"/>
</style:style>
<style:style style:name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text body" style:class="text">
<style:properties fo:font-size="16pt" fo:font-weight="bold"/>
</style:style>
<style:style style:name="Table Contents" style:family="paragraph" style:parent-style-name="Text body" style:class="extra">
<style:properties text:number-lines="false" text:line-number="0"/>
</style:style>
<style:style style:name="Table Heading" style:family="paragraph" style:parent-style-name="Table Contents" style:class="extra">
<style:properties fo:font-style="italic" fo:font-weight="bold" fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/>
</style:style>
<style:default-style style:family="graphics">
<style:properties svg:width="0mm" svg:height="0mm" text:anchor-type="page" text:anchor-page-number="0" svg:x="0mm" svg:y="0mm" style:run-through="foreground" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="page-content" style:horizontal-pos="from-left" style:horizontal-rel="paragraph-content" fo:background-color="transparent" fo:padding="0mm" style:editable="false"/>
</style:default-style>
<style:style style:name="Graphics" style:family="graphics">
<style:properties text:anchor-type="paragraph" svg:x="0mm" svg:y="0mm" style:wrap="none" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
</style:style>
<style:style style:name="Individual Photo" style:family="graphics">
<style:properties style:wrap="none" style:vertical-pos="from-top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph" style:mirror="none" fo:clip="rect(0mm 0mm 0mm 0mm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="1" draw:color-inversion="false" draw:transparency="-100%" draw:color-mode="standard"/>
</style:style>
<style:style style:name="Frame" style:family="graphics">
<style:properties text:anchor-type="paragraph" svg:x="0mm" svg:y="0mm" fo:margin-left="2.01mm" fo:margin-right="2.01mm" fo:margin-top="2.01mm" fo:margin-bottom="2.01mm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:padding="1.5mm" fo:border="0.02mm solid #000000"/>
</style:style>
<text:outline-style>
<text:outline-level-style text:level="1" style:num-format=""/>
<text:outline-level-style text:level="2" style:num-format=""/>
<text:outline-level-style text:level="3" style:num-format=""/>
<text:outline-level-style text:level="4" style:num-format=""/>
<text:outline-level-style text:level="5" style:num-format=""/>
<text:outline-level-style text:level="6" style:num-format=""/>
<text:outline-level-style text:level="7" style:num-format=""/>
<text:outline-level-style text:level="8" style:num-format=""/>
<text:outline-level-style text:level="9" style:num-format=""/>
<text:outline-level-style text:level="10" style:num-format=""/>
</text:outline-style>
<text:footnotes-configuration style:num-format="1" text:offset="0" text:footnotes-position="page" text:start-numbering-at="document"/>
<text:endnotes-configuration style:num-format="i" text:offset="0"/>
<text:bibliography-configuration text:prefix="[" text:suffix="]"/>
<text:linenumbering-configuration text:style-name="Line numbering" text:number-lines="false" text:offset="4.99mm" style:num-format="1" text:number-position="left" text:increment="5"/>
</office:styles>
<office:automatic-styles>
<style:style style:name="Table1" style:family="table">
<style:properties style:width="146.49mm" table:align="margins"/>
</style:style>
<style:style style:name="Table1.A" style:family="table-column">
<style:properties style:column-width="29.92mm" style:rel-column-width="1696*"/>
</style:style>
<style:style style:name="Table1.B" style:family="table-column">
<style:properties style:column-width="116.56mm" style:rel-column-width="6608*"/>
</style:style>
<style:style style:name="Table2" style:family="table">
<style:properties style:width="146.49mm" table:align="margins"/>
</style:style>
<style:style style:name="Table2.A" style:family="table-column">
<style:properties style:column-width="29.35mm" style:rel-column-width="1664*"/>
</style:style>
<style:style style:name="Table2.B" style:family="table-column">
<style:properties style:column-width="117.12mm" style:rel-column-width="6640*"/>
</style:style>
<style:style style:name="Table3" style:family="table">
<style:properties style:width="146.49mm" table:align="margins"/>
</style:style>
<style:style style:name="Table3.A" style:family="table-column">
<style:properties style:column-width="146.49mm" style:rel-column-width="65535*"/>
</style:style>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Table Heading">
<style:properties fo:text-align="start" style:justify-single-word="false" fo:padding="0.49mm" fo:border-top="0.02mm solid #000000" fo:border-bottom="0.02mm solid #000000"/>
</style:style>
<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard">
<style:properties fo:font-weight="bold"/>
</style:style>
<style:page-master style:name="pm1">
<style:properties fo:page-width="209.99mm" fo:page-height="296.99mm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="25.4mm" fo:margin-bottom="25.4mm" fo:margin-left="31.75mm" fo:margin-right="31.75mm"/>
<style:header-style/>
<style:footer-style/>
</style:page-master>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-master-name="pm1"/>
</office:master-styles>
<office:body>
</office:body>
</office:document>

View File

@@ -0,0 +1,12 @@
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">
<HTML>
<HEAD>
<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=iso-8859-1\">
<TITLE>
</TITLE>
</HEAD>
<BODY>
<!-- START -->
<!-- STOP -->
</BODY>
</HTML>

127
gramps/src/data/table.sxc Normal file
View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<office:document office:class="spreadsheet" office:version="0.9" xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script">
<office:meta>
<meta:generator>StarOffice/5.2 (Linux)</meta:generator><!--619b(Build:6103)-->
<meta:creation-date>2001-03-15T14:44:55</meta:creation-date>
<dc:creator>Don Allingham</dc:creator>
<dc:date>2001-03-15T14:46:49</dc:date>
<dc:language>en-US</dc:language>
<meta:editing-cycles>5</meta:editing-cycles>
<meta:editing-duration>PT0S</meta:editing-duration>
<meta:user-defined meta:name="Info 0"/>
<meta:user-defined meta:name="Info 1"/>
<meta:user-defined meta:name="Info 2"/>
<meta:user-defined meta:name="Info 3"/>
<meta:document-statistic meta:table-count="1" meta:cell-count="344"/>
</office:meta>
<office:script>
<script:library-embedded script:name="Standard"/>
</office:script>
<office:font-decls>
<style:font-decl style:name="Andale WT UI" fo:font-family="&apos;Andale WT UI&apos;, &apos;MS Mincho&apos;, &apos;HG Mincho L&apos;, &apos;MS PGothic&apos;, &apos;Arial Unicode MS&apos;"/>
<style:font-decl style:name="Simplified Arabic" fo:font-family="&apos;Simplified Arabic&apos;, &apos;Andale WT UI&apos;, &apos;Arial Unicode MS&apos;"/>
<style:font-decl style:name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/>
</office:font-decls>
<office:styles>
<number:number-style style:name="N0" style:family="data-style">
<number:number number:min-integer-digits="1"/>
</number:number-style>
<number:currency-style style:name="N104P0" style:family="data-style">
<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>
<number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
</number:currency-style>
<number:currency-style style:name="N104" style:family="data-style">
<style:properties fo:color="#ff0000"/>
<number:text>-</number:text>
<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>
<number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
<style:map style:condition="value()&gt;=0" style:apply-style-name="N104P0"/>
</number:currency-style>
<number:currency-style style:name="N106" style:family="data-style">
<number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>
<number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
</number:currency-style>
<style:style style:name="Default" style:family="table-cell" style:data-style-name="N0"/>
<style:style style:name="Result" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N0">
<style:properties fo:font-style="italic" style:text-underline="single" fo:font-weight="bold"/>
</style:style>
<style:style style:name="Result2" style:family="table-cell" style:parent-style-name="Result" style:data-style-name="N104"/>
<style:style style:name="Heading" style:family="table-cell" style:parent-style-name="Default" style:data-style-name="N0">
<style:properties fo:text-align="center" style:text-align-source="fix" fo:font-size="16pt" fo:font-style="italic" fo:font-weight="bold"/>
</style:style>
<style:style style:name="Heading1" style:family="table-cell" style:parent-style-name="Heading" style:data-style-name="N0">
<style:properties fo:direction="ltr" style:rotation-angle="90"/>
</style:style>
</office:styles>
<office:automatic-styles>
<style:style style:name="co1" style:family="table-column">
<style:properties style:column-width="64.26pt" fo:break-before="auto"/>
</style:style>
<style:style style:name="ro1" style:family="table-row">
<style:properties fo:break-before="auto"/>
</style:style>
<style:style style:name="ta1" style:family="table">
<style:properties table:display="true" table:page-style-name="Default"/>
</style:style>
<number:number-style style:name="N2" style:family="data-style">
<number:number number:decimal-places="2" number:min-integer-digits="1"/>
</number:number-style>
<style:style style:name="ce1" style:family="table-cell" style:parent-style-name="Default">
<style:properties fo:background-color="#99ccff" fo:color="#000000" style:text-outline="false" style:text-crossing-out="none" style:font-name="Arial" fo:font-size="10pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline="none" fo:font-weight="bold" style:font-name-asian="Andale WT UI" style:font-size-asian="10pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Simplified Arabic" style:font-size-complex="10pt" style:font-style-complex="normal" style:font-weight-complex="normal"/>
</style:style>
<style:style style:name="ce2" style:family="table-cell" style:parent-style-name="Default">
<style:properties fo:color="#000000" style:text-outline="false" style:text-crossing-out="none" style:font-name="Arial" fo:font-size="10pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline="none" fo:font-weight="normal" style:font-name-asian="Andale WT UI" style:font-size-asian="10pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Simplified Arabic" style:font-size-complex="10pt" style:font-style-complex="normal" style:font-weight-complex="normal"/>
</style:style>
<style:style style:name="ce3" style:family="table-cell" style:parent-style-name="Default">
<style:properties fo:background-color="#e6e6e6" fo:color="#000000" style:text-outline="false" style:text-crossing-out="none" style:font-name="Arial" fo:font-size="10pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline="none" fo:font-weight="normal" style:font-name-asian="Andale WT UI" style:font-size-asian="10pt" style:font-style-asian="normal" style:font-weight-asian="normal" style:font-name-complex="Simplified Arabic" style:font-size-complex="10pt" style:font-style-complex="normal" style:font-weight-complex="normal"/>
</style:style>
<style:style style:name="ce4" style:family="table-cell" style:parent-style-name="Default">
<style:properties fo:background-color="#99ccff" fo:font-size="10pt" fo:font-weight="bold"/>
</style:style>
<style:style style:name="ce5" style:family="table-cell" style:parent-style-name="Default">
<style:properties fo:background-color="#e6e6e6"/>
</style:style>
<style:page-master style:name="pm1">
<style:header-style>
<style:properties fo:min-height="21.29pt" fo:margin-left="0pt" fo:margin-right="0pt" fo:margin-bottom="7.09pt"/>
</style:header-style>
<style:footer-style>
<style:properties fo:min-height="21.29pt" fo:margin-left="0pt" fo:margin-right="0pt" fo:margin-top="7.09pt"/>
</style:footer-style>
</style:page-master>
<style:page-master style:name="pm2">
<style:header-style>
<style:properties fo:min-height="21.29pt" fo:margin-left="0pt" fo:margin-right="0pt" fo:margin-bottom="7.09pt" fo:border="2.49pt solid #000000" fo:border-top="2.49pt solid #000000" fo:border-bottom="2.49pt solid #000000" fo:border-left="2.49pt solid #000000" fo:border-right="2.49pt solid #000000" fo:padding="0.51pt" fo:padding-top="0.51pt" fo:padding-bottom="0.51pt" fo:padding-left="0.51pt" fo:padding-right="0.51pt" fo:background-color="#c0c0c0"/>
</style:header-style>
<style:footer-style>
<style:properties fo:min-height="21.29pt" fo:margin-left="0pt" fo:margin-right="0pt" fo:margin-top="7.09pt" fo:border="2.49pt solid #000000" fo:border-top="2.49pt solid #000000" fo:border-bottom="2.49pt solid #000000" fo:border-left="2.49pt solid #000000" fo:border-right="2.49pt solid #000000" fo:padding="0.51pt" fo:padding-top="0.51pt" fo:padding-bottom="0.51pt" fo:padding-left="0.51pt" fo:padding-right="0.51pt" fo:background-color="#c0c0c0"/>
</style:footer-style>
</style:page-master>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Default" style:page-master-name="pm1" style:next-style-name="">
<style:header>
<text:p><text:sheet-name>???</text:sheet-name></text:p>
</style:header>
<style:footer>
<text:p>Page <text:page-number>1</text:page-number></text:p>
</style:footer>
</style:master-page>
<style:master-page style:name="Report" style:page-master-name="pm2" style:next-style-name="">
<style:header>
<style:region-left>
<text:p><text:sheet-name>???</text:sheet-name> (<text:file-name text:display="full">???</text:file-name>)</text:p>
</style:region-left>
<style:region-right>
<text:p><text:date text:date-value="0-00-00" style:data-style-name="N2">3/15/01</text:date>, <text:time text:time-value="0-00-00" style:data-style-name="N1101133268">?</text:time></text:p>
</style:region-right>
</style:header>
<style:footer>
<text:p>Page <text:page-number>1</text:page-number> / <text:page-count>99</text:page-count></text:p>
</style:footer>
</style:master-page>
</office:master-styles>
<office:body>
</office:body>
</office:document>

26
gramps/src/fam.xpm Normal file
View File

@@ -0,0 +1,26 @@
/* XPM */
static char * fam_xpm[] = {
"24 20 3 1",
" c None",
". c #8080FF",
"+ c #32029C",
" ",
" ",
" ",
" .+. ",
" +++ .+. ",
" .+. +++ ",
" .+. ",
" .+++. .+. ",
" .+++++. +++ .+++. ",
" +++++++ .+. +++++++ ",
" + +++ + +.+++.+ ",
" + +++ + .+++. + +++ + ",
" + +++ + +++++ + +++ + ",
" +++ +++++ .+++. ",
" + + +++++ .+++++. ",
" + + .+++. +++++++ ",
" + + + + + + ",
" + + + + + + ",
" + + + + + + ",
" "};

View File

@@ -0,0 +1,77 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with an event after ..."
import Filter
import string
import Date
import RelLib
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class EventAfter(Filter.Filter):
"People with an event after ..."
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,text):
self.date = Date.Date()
self.date.set(text)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def match(self,person):
val = 0
list = person.getEventList()[:]
list.append(person.getBirth())
list.append(person.getDeath())
for event in list:
if self.date.getDate() == "" or event.getDate() == "":
continue
if self.date < event.getDateObj():
val = 1
break
return val
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def create(text):
return EventAfter(text)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def need_qualifier():
return 1

View File

@@ -0,0 +1,78 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with an event before ..."
import Filter
import string
import Date
import RelLib
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class EventBefore(Filter.Filter):
"People with an event before ..."
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,text):
self.date = Date.Date()
self.date.set(text)
self.text = text
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def match(self,person):
val = 0
list = person.getEventList()[:]
list.append(person.getBirth())
list.append(person.getDeath())
for event in list:
if self.date.getDate() == "" or event.getDate() == "":
continue
if self.date > event.getDateObj():
val = 1
break
return val
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def create(text):
return EventBefore(text)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def need_qualifier():
return 1

View File

@@ -0,0 +1,36 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Disconnected individuals"
import Filter
import RelLib
class Disconnected(Filter.Filter):
"Disconnected individuals"
def match(self,person):
return person.getMainFamily() == None and len(person.getFamilyList()) == 0
def create(text):
return Disconnected(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,54 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with an event location of ..."
import Filter
import string
import re
import RelLib
class EventPlace(Filter.Filter):
"People with an event location of ..."
def __init__(self,text):
self.ok = 1
try:
self.regexp = re.compile(text,re.IGNORECASE)
except:
self.ok = 0
Filter.Filter.__init__(self,text)
def match(self,person):
val = 0
list = person.getEventList()[:]
list.append(person.getBirth())
list.append(person.getDeath())
for event in list:
if self.regexp.search(event.getPlace()):
val = 1
break
return val
def create(text):
return EventPlace(text)
def need_qualifier():
return 1

View File

@@ -0,0 +1,39 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People who have an event type of ..."
import Filter
import string
class EventType(Filter.Filter):
"People who have photos"
def match(self,person):
for event in person.getEventList():
if event.getName() == self.text:
return 1
return 0
def create(text):
return EventType(text)
def need_qualifier():
return 1

View File

@@ -0,0 +1,39 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Females"
import Filter
import string
import utils
from RelLib import Person
class Females(Filter.Filter):
"Females"
def match(self,person):
return person.getGender() == Person.female
def create(text):
return Females(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People who have photos"
import Filter
import string
import utils
class HavePhotos(Filter.Filter):
"People who have photos"
def match(self,person):
return len(person.getPhotoList()) > 0
def create(text):
return HavePhotos(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,38 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with incomplete names"
import Filter
from RelLib import Person
class IncompleteNames(Filter.Filter):
"People with incomplete names"
def match(self,person):
name = person.getPrimaryName()
return name.getFirstName() == "" or name.getSurname() == ""
def create(text):
return IncompleteNames(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,24 @@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
datadir = @datadir@/@PACKAGE@
INSTALL = @INSTALL@
filters = ${datadir}/filters
srcdir = @top_srcdir@
pycomp = ${srcdir}/py-compile
@SET_MAKE@
all:
${pycomp} *.py
install:
-mkdir ${filters}
${INSTALL} -c *.py *.pyo ${datadir}/filters
uninstall:
rm ${filters}/*.py ${filters}/*.pyo ${filters}/*.glade ${filters}/*.xpm
-rmdir ${filters}
clean:
-rm -f core *.pyo *.pyc *.bak *~

View File

@@ -0,0 +1,41 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Names with same SoundEx code as ..."
import Filter
import soundex
import RelLib
class MatchSndEx(Filter.Filter):
"Names with same SoundEx code as ..."
def __init__(self,text,invert):
self.sndex = soundex.soundex(text)
Filter.Filter.__init__(self,text)
def match(self,person):
return self.sndex == soundex.soundex(person.getPrimaryName().getSurname())
def create(text):
return MatchSndEx(text)
def need_qualifier():
return 1

View File

@@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Names with the specified SoundEx code"
import Filter
import soundex
import RelLib
class MatchSndEx2(Filter.Filter):
"Names with the specified SoundEx code"
def match(self,person):
return self.text == soundex.soundex(person.getPrimaryName().getSurname())
def create(text):
return MatchSndEx2(text)
def need_qualifier():
return 1

View File

@@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with multiple marriage records"
import Filter
import string
import utils
class MultipleMarriages(Filter.Filter):
"People with multiple marriage records"
def match(self,person):
return len(person.getFamilyList()) > 1
def create(text):
return MultipleMarriages(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with no marriage records"
import Filter
import string
import utils
class NeverMarried(Filter.Filter):
"People with no marriage records"
def match(self,person):
return len(person.getFamilyList()) == 0
def create(text):
return NeverMarried(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People no listed birth date"
import Filter
import string
import utils
class NoBirthdate(Filter.Filter):
"People no listed birth date"
def match(self,person):
return person.getBirth().getDate() == ""
def create(text):
return NoBirthdate(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,43 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"People with children"
import Filter
import string
import utils
class HaveChildren(Filter.Filter):
"People with children"
def match(self,person):
val = 0
for family in person.getFamilyList():
if len(family.getChildList()) > 0:
val = 1
break
return val
def create(text):
return HaveChildren(text)
def need_qualifier():
return 0

View File

@@ -0,0 +1,48 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Names that match a regular expression"
import Filter
import re
import utils
class RegExMatch(Filter.Filter):
"Names that match a regular expression"
def __init__(self,text):
self.ok = 1
try:
self.regexp = re.compile(text,re.IGNORECASE)
except:
self.ok = 0
Filter.Filter.__init__(self,text)
def match(self,person):
if self.ok == 0:
return 0
else:
return self.regexp.search(utils.phonebook_name(person))
def create(text):
return RegExMatch(text)
def need_qualifier():
return 1

View File

@@ -0,0 +1,37 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Names that contain a substring"
import Filter
import string
import utils
class SubString(Filter.Filter):
"Names that contain a substring"
def match(self,person):
return string.find(utils.phonebook_name(person),self.text) >= 0
def create(text):
return SubString(text)
def need_qualifier():
return 1

7
gramps/src/get_strings Executable file
View File

@@ -0,0 +1,7 @@
#! /usr/bin/perl
while (<>) {
if (/_\(\"(.*)\"\)/) {
print "gchar *s = N_(\"$1\");\n"
}
}

View File

@@ -0,0 +1,7 @@
[Desktop Entry]
Name=Gramps
Comment=Genealogy Program
Exec=gramps
Icon=gramps.png
Terminal=0
Type=Application

4714
gramps/src/gramps.glade Normal file

File diff suppressed because it is too large Load Diff

BIN
gramps/src/gramps.png Normal file

Binary file not shown.

21
gramps/src/gramps.py Executable file
View File

@@ -0,0 +1,21 @@
#! /usr/bin/python -O
import intl
import os
intl.textdomain("gramps")
if os.environ.has_key("GRAMPSI18N"):
locale = os.environ["GRAMPSI18N"]
else:
locale = "locale"
intl.bindtextdomain("gramps",locale)
import gramps_main
import sys
if len(sys.argv) > 1:
gramps_main.main(sys.argv[1])
else:
gramps_main.main(None)

56
gramps/src/gramps.xpm Normal file
View File

@@ -0,0 +1,56 @@
/* XPM */
static char * gramps_xpm[] = {
"48 48 5 1",
" c None",
". c #999999",
"+ c #FFFFCC",
"@ c #000000",
"# c #CCCCCC",
" ",
" ",
" ",
" ",
" ",
" ",
" .......... ",
" .++++++++. ",
" .++++++++. ",
" @@@.++++++++. ",
" @##.++++++++. ",
" @# .++++++++. ",
" .......... @# .......... ",
" .++++++++. @# ",
" .++++++++. @# ",
" @@@.++++++++.@@@@# ",
" @##.++++++++.###@# .......... ",
" @# .++++++++. @# .++++++++. ",
" @# .......... @# .++++++++. ",
" @# @@@.++++++++. ",
" @# ##.++++++++. ",
" @# .++++++++. ",
" .......... @# .......... ",
" .++++++++. @# ",
" .++++++++. @# ",
" .++++++++.@@@@# ",
" .++++++++.###@# ",
" .++++++++. @# .......... ",
" .......... @# .++++++++. ",
" @# .++++++++. ",
" @# @@@.++++++++. ",
" @# @##.++++++++. ",
" @# .......... @# .++++++++. ",
" @# .++++++++. @# .......... ",
" @# .++++++++. @# ",
" @@@.++++++++.@@@@# ",
" ##.++++++++.###@# ",
" .++++++++. @# .......... ",
" .......... @# .++++++++. ",
" @# .++++++++. ",
" @@@.++++++++. ",
" ##.++++++++. ",
" .++++++++. ",
" .......... ",
" ",
" ",
" ",
" "};

2090
gramps/src/gramps_main.py Executable file

File diff suppressed because it is too large Load Diff

501
gramps/src/imagesel.glade Normal file
View File

@@ -0,0 +1,501 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>Marriage</name>
<program_name>marriage</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory></pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GnomeDialog</class>
<name>imageSelect</name>
<width>300</width>
<title>Gramps - Select a picture</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_CENTER</position>
<modal>False</modal>
<default_width>400</default_width>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox9</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area9</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button79</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_savephoto_clicked</handler>
<object>imageSelect</object>
<last_modification_time>Sat, 09 Dec 2000 22:20:48 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button81</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>imageSelect</object>
<last_modification_time>Sat, 09 Dec 2000 22:18:55 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox21</name>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>picTitle</name>
<label>Select a picture</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator7</name>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label121</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkFrame</class>
<name>frame1</name>
<label>Preview</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GnomePixmap</class>
<name>image</name>
<width>100</width>
<height>100</height>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<name>label122</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkTable</class>
<name>table1</name>
<rows>3</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>0</row_spacing>
<column_spacing>0</column_spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label120</name>
<label>File : </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>10</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label118</name>
<label>Description : </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>5</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>False</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>photoDescription</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>5</xpad>
<ypad>0</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkCheckButton</class>
<name>private</name>
<can_focus>True</can_focus>
<label>Do not make a private copy</label>
<active>False</active>
<draw_indicator>True</draw_indicator>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>5</xpad>
<ypad>10</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GnomeFileEntry</class>
<name>photosel</name>
<history_id>photoselect</history_id>
<max_saved>10</max_saved>
<title>Select a photo</title>
<directory>False</directory>
<modal>False</modal>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>5</xpad>
<ypad>5</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
<widget>
<class>GtkEntry</class>
<child_name>GnomeEntry:entry</child_name>
<name>fname</name>
<can_focus>True</can_focus>
<signal>
<name>changed</name>
<handler>on_name_changed</handler>
<object>imageSelect</object>
<last_modification_time>Thu, 19 Apr 2001 22:16:22 GMT</last_modification_time>
</signal>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
</widget>
</widget>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GnomeDialog</class>
<name>dialog1</name>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>True</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>False</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox10</name>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area10</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button82</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_ok_clicked</handler>
<object>dialog1</object>
<last_modification_time>Thu, 19 Apr 2001 00:00:19 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button83</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_apply_clicked</handler>
<object>dialog1</object>
<last_modification_time>Thu, 19 Apr 2001 00:00:06 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button84</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_cancel_clicked</handler>
<object>dialog1</object>
<last_modification_time>Thu, 19 Apr 2001 00:00:43 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox22</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label119</name>
<label>Change Photo Description</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator9</name>
<child>
<padding>10</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GnomePixmap</class>
<name>photo</name>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>text</name>
<width>300</width>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

141
gramps/src/intl.c Normal file
View File

@@ -0,0 +1,141 @@
/***********************************************************
Copyright (C) 1997 Martin von L<>wis
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies.
This software comes with no warranty. Use at your own risk.
******************************************************************/
#include <stdio.h>
#include <errno.h>
#include <libintl.h>
#include <locale.h>
#include "Python.h"
static PyObject*
PyIntl_gettext(PyObject* self,PyObject *args)
{
char *in;
if (!PyArg_ParseTuple(args,"z",&in))
return 0;
return PyString_FromString(gettext(in));
}
static PyObject*
PyIntl_dgettext(PyObject* self,PyObject *args)
{
char *domain,*in;
if(!PyArg_ParseTuple(args,"zz",&domain,&in))return 0;
return PyString_FromString(dgettext(domain,in));
}
static PyObject*
PyIntl_dcgettext(PyObject *self,PyObject *args)
{
char *domain,*msgid;
int category;
if(!PyArg_ParseTuple(args,"zzi",&domain,&msgid,&category))
return 0;
return PyString_FromString(dcgettext(domain,msgid,category));
}
static PyObject*
PyIntl_textdomain(PyObject* self,PyObject* args)
{
char *domain;
if(!PyArg_ParseTuple(args,"z",&domain))return 0;
return PyString_FromString(textdomain(domain));
}
static PyObject*
PyIntl_bindtextdomain(PyObject* self,PyObject*args)
{
char *domain,*dirname;
if(!PyArg_ParseTuple(args,"zz",&domain,&dirname))return 0;
return PyString_FromString(bindtextdomain(domain,dirname));
}
static PyObject*
PyIntl_setlocale(PyObject* self,PyObject* args)
{
int category;
char *locale=0;
if(!PyArg_ParseTuple(args,"i|z",&category,&locale))return 0;
return Py_BuildValue("z",setlocale(category,locale));
}
static PyObject*
PyIntl_localeconv(PyObject* self,PyObject* args)
{
PyObject* result;
struct lconv *l;
if(!PyArg_NoArgs(args))return 0;
result = PyDict_New();
if(!result)return 0;
l=localeconv();
#define RESULT_STRING(s) \
PyDict_SetItemString(result,#s,PyString_FromString(l->s))
#define RESULT_INT(i) \
PyDict_SetItemString(result,#i,PyInt_FromLong(l->i))
#define RESULT_CHAR(c) {\
char tmp[2]; \
tmp[0]=l->c;tmp[1]='\0';\
PyDict_SetItemString(result,#c,PyString_FromString(tmp)); \
}
/* Numeric information */
RESULT_STRING(decimal_point);
RESULT_STRING(thousands_sep);
RESULT_STRING(grouping);
/* Monetary information */
RESULT_STRING(int_curr_symbol);
RESULT_STRING(currency_symbol);
RESULT_STRING(mon_decimal_point);
RESULT_STRING(mon_thousands_sep);
RESULT_STRING(mon_grouping);
RESULT_STRING(positive_sign);
RESULT_STRING(negative_sign);
RESULT_INT(int_frac_digits);
RESULT_INT(frac_digits);
RESULT_INT(p_cs_precedes);
RESULT_INT(p_sep_by_space);
RESULT_INT(n_cs_precedes);
RESULT_INT(n_sep_by_space);
RESULT_INT(p_sign_posn);
RESULT_INT(n_sign_posn);
return result;
}
static struct PyMethodDef PyIntl_Methods[] = {
{"gettext",(PyCFunction)PyIntl_gettext,1},
{"dgettext",(PyCFunction)PyIntl_dgettext,1},
{"dcgettext",(PyCFunction)PyIntl_dcgettext,1},
{"textdomain",(PyCFunction)PyIntl_textdomain,1},
{"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,1},
{"setlocale",(PyCFunction)PyIntl_setlocale,1},
{"localeconv",(PyCFunction)PyIntl_localeconv,0},
{NULL, NULL}
};
void
initintl()
{
PyObject *m,*d;
m=Py_InitModule("intl",PyIntl_Methods);
d = PyModule_GetDict(m);
PyDict_SetItemString(d,"LC_CTYPE",PyInt_FromLong(LC_CTYPE));
PyDict_SetItemString(d,"LC_NUMERIC",PyInt_FromLong(LC_NUMERIC));
PyDict_SetItemString(d,"LC_TIME",PyInt_FromLong(LC_TIME));
PyDict_SetItemString(d,"LC_COLLATE",PyInt_FromLong(LC_COLLATE));
PyDict_SetItemString(d,"LC_MONETARY",PyInt_FromLong(LC_MONETARY));
PyDict_SetItemString(d,"LC_MESSAGES",PyInt_FromLong(LC_MESSAGES));
PyDict_SetItemString(d,"LC_ALL",PyInt_FromLong(LC_ALL));
if(PyErr_Occurred())
Py_FatalError("Can't initialize module intl");
}

143
gramps/src/latin_ansel.py Normal file
View File

@@ -0,0 +1,143 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import cStringIO
_s1 = {
0xEA : { ord('A') : 0xC5, ord('a') : 0xE5 },
0xE8 : { ord('A') : 0xC4, ord('E') : 0xCB, ord('I') : 0xCF, ord('O') : 0xD6,
ord('U') : 0xDC, ord('a') : 0xE4, ord('e') : 0xEB, ord('i') : 0xEF,
ord('o') : 0xF6, ord('u') : 0xFC, ord('y') : 0xFF },
0xE2 : { ord('A') : 0xC1, ord('E') : 0xC9, ord('I') : 0xCD, ord('O') : 0xD3,
ord('U') : 0xDA, ord('Y') : 0xDD, ord('a') : 0xE1, ord('e') : 0xE9,
ord('i') : 0xED, ord('o') : 0xF3, ord('u') : 0xFA, ord('y') : 0xFD },
0xE1 : { ord('A') : 0xC0, ord('E') : 0xC8, ord('I') : 0xCC, ord('O') : 0xD2,
ord('U') : 0xD9, ord('a') : 0xE0, ord('e') : 0xE8, ord('i') : 0xEC,
ord('o') : 0xF2, ord('u') : 0xF9 },
0xE4 : { ord('A') : 0xC3, ord('N') : 0xD1, ord('O') : 0xD5, ord('a') : 0xE3,
ord('n') : 0xF1, ord('o') : 0xF5 },
0xE3 : { ord('A') : 0xC2, ord('E') : 0xCA, ord('I') : 0xCE, ord('O') : 0xD4,
ord('U') : 0xDB, ord('a') : 0xE3, ord('e') : 0xEA, ord('i') : 0xEE,
ord('o') : 0xF4, ord('u') : 0xFB },
0xF0 : { ord('C') : 0xC7, ord('c') : 0xE7 }
}
_t1 = {
0xC0 : (chr(0xE1), 'A'), 0xC1 : (chr(0xE2), 'A'), 0xC2 : (chr(0xE3), 'A'),
0xC3 : (chr(0xE4), 'A'), 0xC4 : (chr(0xE8), 'A'), 0xC5 : (chr(0xEA), 'A'),
0xC7 : (chr(0xF0), 'C'), 0xC8 : (chr(0xE1), 'E'), 0xC9 : (chr(0xE2), 'E'),
0xCA : (chr(0xE3), 'E'), 0xCB : (chr(0xE8), 'E'), 0xCC : (chr(0xE1), 'I'),
0xCD : (chr(0xE2), 'I'), 0xCE : (chr(0xE3), 'I'), 0xCF : (chr(0xE8), 'I'),
0xD1 : (chr(0xE4), 'N'), 0xD2 : (chr(0xE1), 'O'), 0xD3 : (chr(0xE2), 'O'),
0xD4 : (chr(0xE3), 'O'), 0xD5 : (chr(0xE4), 'O'), 0xD6 : (chr(0xE8), 'O'),
0xD9 : (chr(0xE1), 'U'), 0xDA : (chr(0xE2), 'U'), 0xDB : (chr(0xE3), 'U'),
0xDC : (chr(0xE8), 'U'), 0xDD : (chr(0xE2), 'Y'), 0xE0 : (chr(0xE1), 'a'),
0xE1 : (chr(0xE2), 'a'), 0xE3 : (chr(0xE3), 'a'), 0xE3 : (chr(0xE4), 'a'),
0xE4 : (chr(0xE8), 'a'), 0xE5 : (chr(0xEA), 'a'), 0xE7 : (chr(0xF0), 'c'),
0xE8 : (chr(0xE1), 'e'), 0xE9 : (chr(0xE2), 'e'), 0xEA : (chr(0xE3), 'e'),
0xEB : (chr(0xE8), 'e'), 0xEC : (chr(0xE1), 'i'), 0xED : (chr(0xE2), 'i'),
0xEE : (chr(0xE3), 'i'), 0xEF : (chr(0xE8), 'i'), 0xF1 : (chr(0xE4), 'n'),
0xF2 : (chr(0xE1), 'o'), 0xF3 : (chr(0xE2), 'o'), 0xF4 : (chr(0xE3), 'o'),
0xF5 : (chr(0xE4), 'o'), 0xF6 : (chr(0xE8), 'o'), 0xF9 : (chr(0xE1), 'u'),
0xFA : (chr(0xE2), 'u'), 0xFB : (chr(0xE3), 'u'), 0xFC : (chr(0xE8), 'u'),
0xFD : (chr(0xE2), 'y'), 0xFF : (chr(0xE8), 'y')
}
_s0 = {
0xCF : 0xDF, 0xA4 : 0xDE, 0xB4 : 0xFE, 0xA2 : 0xD8,
0xB3 : 0xF8, 0xA5 : 0xC6, 0xB5 : 0xE6, 0xBA : 0xF0 }
_t0 = {
0xDF : chr(0xCF), 0xDE : chr(0xA4), 0xFE : chr(0xB4), 0xD8 : chr(0xA2),
0xF8 : chr(0xB3), 0xC6 : chr(0xA5), 0xE6 : chr(0xB5), 0xBA : chr(0xF0) }
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
import cStringIO
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ansel_to_latin(s):
buff = cStringIO.StringIO()
while s:
try:
head,s = ansel_to_code(s)
except Exception,e:
from traceback import print_exc
print_exc()
head = ''
s = s[1:0]
buff.write(head)
ans = buff.getvalue()
buff.close()
return ans
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def latin_to_ansel(s):
buff = cStringIO.StringIO()
orig = s
while s:
c = ord(s[0])
if c <= 127:
buff.write(s[0])
else:
if _t0.has_key(c):
buff.write(_t0[c])
else:
try:
ansel = _t1[c]
buff.write(ansel[0])
buff.write(ansel[1])
except Exception,e:
from traceback import print_exc
print_exc()
s = s[1:]
ans = buff.getvalue()
buff.close()
return ans
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ansel_to_code(s):
if s == "":
return ""
if ord(s[0]) < 128:
return s[0],s[1:]
c0 = ord(s[0])
c1 = ord(s[1])
if c0 >= 0xE0:
return chr(_s1[c0][c1]),s[2:]
else:
return chr(_s0[c0]), s[1:]

34
gramps/src/latin_utf8.py Normal file
View File

@@ -0,0 +1,34 @@
from xml.unicode.utf8_iso import utf8_to_code, code_to_utf8
import cStringIO
def utf8_to_latin(s):
buff = cStringIO.StringIO()
while s:
try:
head,s = utf8_to_code(1,s)
except Exception,e:
from traceback import print_exc
print_exc()
head = ''
s = s[1:0]
buff.write(head)
ans = buff.getvalue()
buff.close()
return ans
def latin_to_utf8(s):
buff = cStringIO.StringIO()
for c in s:
try:
cv = code_to_utf8(1,c)
except Exception,e:
from traceback import print_exc
print_exc()
cv = ''
buff.write(cv)
ans = buff.getvalue()
buff.close()
return ans

Binary file not shown.

680
gramps/src/marriage.glade Normal file
View File

@@ -0,0 +1,680 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>Marriage</name>
<program_name>marriage</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory></pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GnomeDialog</class>
<name>marriageEditor</name>
<title>Gramps - Marriage Editor</title>
<type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_CENTER</position>
<modal>True</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>False</allow_grow>
<auto_shrink>False</auto_shrink>
<auto_close>False</auto_close>
<hide_on_close>False</hide_on_close>
<widget>
<class>GtkVBox</class>
<child_name>GnomeDialog:vbox</child_name>
<name>dialog-vbox5</name>
<width>400</width>
<homogeneous>False</homogeneous>
<spacing>8</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkHButtonBox</class>
<child_name>GnomeDialog:action_area</child_name>
<name>dialog-action_area5</name>
<width>400</width>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>8</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<pack>GTK_PACK_END</pack>
</child>
<widget>
<class>GtkButton</class>
<name>button57</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>marriageEditor</object>
<last_modification_time>Sat, 25 Nov 2000 00:55:34 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CLOSE</stock_button>
</widget>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox18</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>marriageTitle</name>
<width>0</width>
<label>Marriage/Family Editor</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>8</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator4</name>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkNotebook</class>
<name>notebook4</name>
<can_focus>True</can_focus>
<show_tabs>True</show_tabs>
<show_border>True</show_border>
<tab_pos>GTK_POS_TOP</tab_pos>
<scrollable>False</scrollable>
<tab_hborder>2</tab_hborder>
<tab_vborder>2</tab_vborder>
<popup_enable>False</popup_enable>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkVBox</class>
<name>vbox18</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkTable</class>
<name>table6</name>
<rows>4</rows>
<columns>2</columns>
<homogeneous>False</homogeneous>
<row_spacing>0</row_spacing>
<column_spacing>0</column_spacing>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label99</name>
<label>Date : </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>5</xpad>
<ypad>8</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>marriageDate</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>1</top_attach>
<bottom_attach>2</bottom_attach>
<xpad>3</xpad>
<ypad>3</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label100</name>
<label>Description : </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>5</xpad>
<ypad>8</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>3</top_attach>
<bottom_attach>4</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label101</name>
<label>Place : </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>5</xpad>
<ypad>8</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>marriagePlace</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>2</top_attach>
<bottom_attach>3</bottom_attach>
<xpad>3</xpad>
<ypad>3</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkEntry</class>
<name>marriageDescription</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>3</top_attach>
<bottom_attach>4</bottom_attach>
<xpad>3</xpad>
<ypad>3</ypad>
<xexpand>True</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox14</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<left_attach>1</left_attach>
<right_attach>2</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>3</xpad>
<ypad>3</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>True</yfill>
</child>
<widget>
<class>GtkCombo</class>
<name>marriageEvent</name>
<value_in_list>False</value_in_list>
<ok_if_empty>True</ok_if_empty>
<case_sensitive>False</case_sensitive>
<use_arrows>True</use_arrows>
<use_arrows_always>False</use_arrows_always>
<items></items>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkEntry</class>
<child_name>GtkCombo:entry</child_name>
<name>marriageEventName</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
</widget>
</widget>
<widget>
<class>GtkButton</class>
<name>marriageSource</name>
<tooltip>Select the source of the information</tooltip>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_showsource_clicked</handler>
<object>marriageEventList</object>
<last_modification_time>Sun, 11 Feb 2001 22:58:04 GMT</last_modification_time>
</signal>
<label>Source</label>
<child>
<padding>3</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<name>label98</name>
<label>Event Type : </label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>1</xalign>
<yalign>0.5</yalign>
<xpad>5</xpad>
<ypad>8</ypad>
<child>
<left_attach>0</left_attach>
<right_attach>1</right_attach>
<top_attach>0</top_attach>
<bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
<xexpand>False</xexpand>
<yexpand>False</yexpand>
<xshrink>False</xshrink>
<yshrink>False</yshrink>
<xfill>True</xfill>
<yfill>False</yfill>
</child>
</widget>
</widget>
<widget>
<class>GtkCList</class>
<name>marriageEventList</name>
<height>140</height>
<can_focus>True</can_focus>
<signal>
<name>select_row</name>
<handler>on_marriageEventList_select_row</handler>
<last_modification_time>Sat, 25 Nov 2000 16:53:14 GMT</last_modification_time>
</signal>
<columns>3</columns>
<column_widths>91,106,80</column_widths>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<show_titles>True</show_titles>
<shadow_type>GTK_SHADOW_IN</shadow_type>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label92</name>
<label>Event</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label93</name>
<label>Date</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>CList:title</child_name>
<name>label94</name>
<label>Place</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
<widget>
<class>GtkHButtonBox</class>
<name>hbuttonbox9</name>
<layout_style>GTK_BUTTONBOX_SPREAD</layout_style>
<spacing>30</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>2</child_ipad_x>
<child_ipad_y>2</child_ipad_y>
<child>
<padding>4</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkButton</class>
<name>marriageAddBtn</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_marriageAddBtn_clicked</handler>
<object>marriageEventList</object>
<last_modification_time>Sat, 25 Nov 2000 16:52:41 GMT</last_modification_time>
</signal>
<label>Add</label>
</widget>
<widget>
<class>GtkButton</class>
<name>marriageUpdateBtn</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_marriageUpdateBtn_clicked</handler>
<object>marriageEventList</object>
<last_modification_time>Sat, 25 Nov 2000 16:52:46 GMT</last_modification_time>
</signal>
<label>Update</label>
</widget>
<widget>
<class>GtkButton</class>
<name>marriageDeleteBtn</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_marriageDeleteBtn_clicked</handler>
<object>marriageEventList</object>
<last_modification_time>Sat, 25 Nov 2000 16:52:55 GMT</last_modification_time>
</signal>
<label>Delete</label>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label98</name>
<label>Events</label>
<justify>GTK_JUSTIFY_RIGHT</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow15</name>
<hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<widget>
<class>GtkText</class>
<name>marriageNotes</name>
<width>430</width>
<can_focus>True</can_focus>
<editable>True</editable>
<text></text>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label99</name>
<label>Notes</label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox33</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkScrolledWindow</class>
<name>scrolledwindow22</name>
<hscrollbar_policy>GTK_POLICY_AUTOMATIC</hscrollbar_policy>
<vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
<hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
<vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GnomeIconList</class>
<name>photolist</name>
<width>500</width>
<can_focus>True</can_focus>
<signal>
<name>select_icon</name>
<handler>on_photolist_select_icon</handler>
<object>marriageEditor</object>
<last_modification_time>Thu, 29 Mar 2001 13:59:13 GMT</last_modification_time>
</signal>
<signal>
<name>button_press_event</name>
<handler>on_photolist_button_press_event</handler>
<object>marriageEditor</object>
<last_modification_time>Thu, 29 Mar 2001 13:59:27 GMT</last_modification_time>
</signal>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<icon_width>100</icon_width>
<row_spacing>4</row_spacing>
<column_spacing>2</column_spacing>
<text_spacing>2</text_spacing>
<text_editable>False</text_editable>
<text_static>True</text_static>
</widget>
</widget>
<widget>
<class>GtkHButtonBox</class>
<name>hbuttonbox20</name>
<layout_style>GTK_BUTTONBOX_DEFAULT_STYLE</layout_style>
<spacing>30</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>5</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkButton</class>
<name>button100</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_addphoto_clicked</handler>
<object>marriageEditor</object>
<last_modification_time>Thu, 29 Mar 2001 13:45:03 GMT</last_modification_time>
</signal>
<label>Add Photo</label>
</widget>
<widget>
<class>GtkButton</class>
<name>button101</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_deletephoto_clicked</handler>
<object>marriageEditor</object>
<last_modification_time>Thu, 29 Mar 2001 13:45:15 GMT</last_modification_time>
</signal>
<label>Delete Photo</label>
</widget>
<widget>
<class>GtkButton</class>
<name>button102</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_makeprimary_clicked</handler>
<object>marriageEditor</object>
<last_modification_time>Thu, 29 Mar 2001 13:44:47 GMT</last_modification_time>
</signal>
<label>Make Primary</label>
</widget>
</widget>
</widget>
<widget>
<class>GtkLabel</class>
<child_name>Notebook:tab</child_name>
<name>label201</name>
<label>Photos</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
</widget>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

52
gramps/src/new.strings Normal file
View File

@@ -0,0 +1,52 @@
gchar *s = N_("Firstname Surname");
gchar *s = N_("Surname, Firstname");
gchar *s = N_("Unknown Format");
gchar *s = N_(" is not a valid date format, and has been\n");
gchar *s = N_("ignored as the date of the event.");
gchar *s = N_(" is not a valid date format, and has been\n");
gchar *s = N_("ignored as the date of the event.");
gchar *s = N_(" is not a valid date format, and has been\n");
gchar *s = N_("ignored as the date of the event.");
gchar *s = N_(" is not a valid date format, and has been\n");
gchar *s = N_("ignored as the date of the event.");
gchar *s = N_("Changing the gender caused problems with marriage information.");
gchar *s = N_("Please check the person's marriage relationships");
gchar *s = N_("View Photo");
gchar *s = N_("Edit Photo");
gchar *s = N_("Edit Description");
gchar *s = N_("Convert to private copy");
gchar *s = N_("View Photo");
gchar *s = N_("Edit Photo");
gchar *s = N_("Edit Description");
gchar *s = N_("Portrait");
gchar *s = N_("Landscape");
gchar *s = N_("No description was provided");
gchar *s = N_(" could not be opened\n");
gchar *s = N_(" could not be opened\n");
gchar *s = N_(" is a corrupt file");
gchar *s = N_(" is a corrupt file");
gchar *s = N_(" is not a valid gramps file\n");
gchar *s = N_("Could not read ");
gchar *s = N_("Currently only JPEG files are supported");
gchar *s = N_("Gramps (Genealogical Research and Analysis Management ");
gchar *s = N_("Programming System) is a personal genealogy program that ");
gchar *s = N_("can be extended by using the Python programming language.");
gchar *s = N_("male");
gchar *s = N_("female");
gchar *s = N_("Unsaved changes exist in the current datbase\n");
gchar *s = N_("Do you wish to save the changes?");
gchar *s = N_("Do you wish to delete all entries and create a new database?");
gchar *s = N_(" is not a directory");
gchar *s = N_("Loading ");
gchar *s = N_("Failure reading ");
gchar *s = N_("Saving ");
gchar *s = N_(" is not a directory");
gchar *s = N_("Could not create ");
gchar *s = N_("Could not create ");
gchar *s = N_("Could not create ");
gchar *s = N_("Do you really wish to delete ");
gchar *s = N_("Do you wish to abandon your changes and revert to the last saved database?");
gchar *s = N_("Cannot revert to a previous database, since one does not exist");
gchar *s = N_("No default/home person has been set");
gchar *s = N_("Do you wish to set ");
gchar *s = N_(" as the home person?");

33
gramps/src/pedegree.xpm Normal file
View File

@@ -0,0 +1,33 @@
/* XPM */
static char * pedegree_xpm[] = {
"22 22 8 1",
" c None",
". c #330066",
"+ c #404040",
"@ c #3F3F3F",
"# c #3C3C3C",
"$ c #3E3E3E",
"% c #434343",
"& c #3D3D3D",
" ",
" ",
" ...... ",
" .++++++ ",
" .+ ",
" .......+ ",
" .++++@.@ ",
" .+ .# ",
" .+ ...... ",
" .+ @@@$$@ ",
" ......+ ",
" +++%.+ ",
" .+ ...... ",
" .+ .++++++ ",
" .@ .+ ",
" .......+ ",
" @&$@@.+ ",
" .+ ",
" ...... ",
" ++++++ ",
" ",
" "};

View File

@@ -0,0 +1,26 @@
/* XPM */
static char * fam_xpm[] = {
"24 20 3 1",
" c None",
". c #8080FF",
"+ c #32029C",
" ",
" ",
" ",
" .+. ",
" +++ .+. ",
" .+. +++ ",
" .+. ",
" .+++. .+. ",
" .+++++. +++ .+++. ",
" +++++++ .+. +++++++ ",
" + +++ + +.+++.+ ",
" + +++ + .+++. + +++ + ",
" + +++ + +++++ + +++ + ",
" +++ +++++ .+++. ",
" + + +++++ .+++++. ",
" + + .+++. +++++++ ",
" + + + + + + ",
" + + + + + + ",
" + + + + + + ",
" "};

View File

@@ -0,0 +1,33 @@
/* XPM */
static char * pedegree_xpm[] = {
"22 22 8 1",
" c None",
". c #330066",
"+ c #404040",
"@ c #3F3F3F",
"# c #3C3C3C",
"$ c #3E3E3E",
"% c #434343",
"& c #3D3D3D",
" ",
" ",
" ...... ",
" .++++++ ",
" .+ ",
" .......+ ",
" .++++@.@ ",
" .+ .# ",
" .+ ...... ",
" .+ @@@$$@ ",
" ......+ ",
" +++%.+ ",
" .+ ...... ",
" .+ .++++++ ",
" .@ .+ ",
" .......+ ",
" @&$@@.+ ",
" .+ ",
" ...... ",
" ++++++ ",
" ",
" "};

View File

@@ -0,0 +1,48 @@
/* XPM */
static char * relativity_xpm[] = {
"45 40 5 1",
" c None",
". c #999999",
"+ c #FFFFCC",
"@ c #000000",
"# c #CCCCCC",
" ",
" .......... ",
" .++++++++. ",
" .++++++++. ",
" @@@.++++++++. ",
" @##.++++++++. ",
" @# .++++++++. ",
" .......... @# .......... ",
" .++++++++. @# ",
" .++++++++. @# ",
" @@@.++++++++.@@@@# ",
" @##.++++++++.###@# .......... ",
" @# .++++++++. @# .++++++++. ",
" @# .......... @# .++++++++. ",
" @# @@@.++++++++. ",
" @# ##.++++++++. ",
" @# .++++++++. ",
" .......... @# .......... ",
" .++++++++. @# ",
" .++++++++. @# ",
" .++++++++.@@@@# ",
" .++++++++.###@# ",
" .++++++++. @# .......... ",
" .......... @# .++++++++. ",
" @# .++++++++. ",
" @# @@@.++++++++. ",
" @# @##.++++++++. ",
" @# .......... @# .++++++++. ",
" @# .++++++++. @# .......... ",
" @# .++++++++. @# ",
" @@@.++++++++.@@@@# ",
" ##.++++++++.###@# ",
" .++++++++. @# .......... ",
" .......... @# .++++++++. ",
" @# .++++++++. ",
" @@@.++++++++. ",
" ##.++++++++. ",
" .++++++++. ",
" .......... ",
" "};

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

449
gramps/src/plugins.glade Normal file
View File

@@ -0,0 +1,449 @@
<?xml version="1.0"?>
<GTK-Interface>
<project>
<name>Gramps</name>
<program_name>gramps</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory></pixmaps_directory>
<language>C</language>
<gnome_support>True</gnome_support>
<gettext_support>True</gettext_support>
</project>
<widget>
<class>GtkWindow</class>
<name>pluginsel</name>
<title>Gramps - Plugin Selection</title>
<type>GTK_WINDOW_DIALOG</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
<class>GtkVBox</class>
<name>vbox33</name>
<border_width>10</border_width>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkHPaned</class>
<name>hpaned1</name>
<handle_size>10</handle_size>
<gutter_size>6</gutter_size>
<position>0</position>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkTree</class>
<name>tree</name>
<border_width>5</border_width>
<width>250</width>
<height>300</height>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<view_mode>GTK_TREE_VIEW_ITEM</view_mode>
<view_line>True</view_line>
<child>
<shrink>False</shrink>
<resize>True</resize>
</child>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox34</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<shrink>True</shrink>
<resize>True</resize>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>20</padding>
<expand>False</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkPixmap</class>
<name>pixmap1</name>
<filename>gramps.xpm</filename>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<build_insensitive>True</build_insensitive>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label60</name>
<label>Tool Selection</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>10</xpad>
<ypad>10</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator18</name>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>pluginTitle</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>10</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>description</name>
<width>300</width>
<label>Select a tool from those available on the left.</label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>True</wrap>
<xalign>0</xalign>
<yalign>0</yalign>
<xpad>10</xpad>
<ypad>20</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator17</name>
<child>
<padding>4</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkHButtonBox</class>
<name>hbuttonbox20</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>30</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkButton</class>
<name>button101</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_ok_clicked</handler>
<object>pluginsel</object>
<last_modification_time>Sun, 11 Mar 2001 22:54:53 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button102</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_apply_clicked</handler>
<object>pluginsel</object>
<last_modification_time>Sun, 11 Mar 2001 22:54:34 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button103</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>pluginsel</object>
<last_modification_time>Sun, 11 Mar 2001 22:54:19 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
</widget>
</widget>
<widget>
<class>GtkWindow</class>
<name>report</name>
<title>Gramps - Report Selection</title>
<type>GTK_WINDOW_DIALOG</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
<class>GtkVBox</class>
<name>vbox35</name>
<border_width>10</border_width>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<widget>
<class>GtkHPaned</class>
<name>hpaned2</name>
<handle_size>10</handle_size>
<gutter_size>6</gutter_size>
<position>0</position>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkTree</class>
<name>tree1</name>
<border_width>5</border_width>
<width>250</width>
<height>300</height>
<selection_mode>GTK_SELECTION_SINGLE</selection_mode>
<view_mode>GTK_TREE_VIEW_ITEM</view_mode>
<view_line>True</view_line>
<child>
<shrink>False</shrink>
<resize>True</resize>
</child>
</widget>
<widget>
<class>GtkVBox</class>
<name>vbox36</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<shrink>True</shrink>
<resize>True</resize>
</child>
<widget>
<class>GtkHBox</class>
<name>hbox2</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>20</padding>
<expand>False</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkPixmap</class>
<name>image</name>
<filename>gramps.xpm</filename>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<build_insensitive>True</build_insensitive>
<child>
<padding>10</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>report_title</name>
<label>Report Selection</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>10</xpad>
<ypad>10</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator19</name>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>label62</name>
<label></label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>10</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
<name>description</name>
<width>300</width>
<label>Select a report from those available on the left.</label>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>True</wrap>
<xalign>0</xalign>
<yalign>0</yalign>
<xpad>10</xpad>
<ypad>20</ypad>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
</widget>
</widget>
</widget>
<widget>
<class>GtkHSeparator</class>
<name>hseparator20</name>
<child>
<padding>4</padding>
<expand>False</expand>
<fill>True</fill>
</child>
</widget>
<widget>
<class>GtkHButtonBox</class>
<name>hbuttonbox21</name>
<layout_style>GTK_BUTTONBOX_END</layout_style>
<spacing>30</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkButton</class>
<name>button104</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_report_ok_clicked</handler>
<object>report</object>
<last_modification_time>Thu, 22 Mar 2001 21:28:02 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button105</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>on_report_apply_clicked</handler>
<object>report</object>
<last_modification_time>Thu, 22 Mar 2001 21:28:11 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_APPLY</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>button106</name>
<can_default>True</can_default>
<can_focus>True</can_focus>
<signal>
<name>clicked</name>
<handler>destroy_passed_object</handler>
<object>report</object>
<last_modification_time>Sun, 11 Mar 2001 22:54:19 GMT</last_modification_time>
</signal>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

View File

@@ -0,0 +1,310 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Ancestor Chart"
import RelLib
import const
import os
import re
import sort
import string
import utils
import OpenOffice
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
active_person = None
db = None
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class AncestorChart:
points = [
# X , Y , Xold+3,Yold(+1.4), Y+.7
( "1.5", "13.2700" , "" "", ""),
( "5.5", "6.6600" , "4.5", "13.2700", "7.3600"),
( "5.5", "19.8800" , "4.5", "14.6700", "20.5800"),
( "9.5", "3.3550" , "8.5", "6.6600", "4.0550"),
( "9.5", "9.9650" , "8.5", "8.0600", "10.6650"),
( "9.5", "16.5750" , "8.5", "19.8800", "17.2750"),
( "9.5", "23.1850" , "8.5", "21.2800", "23.8850"),
("13.5", "1.7025" , "12.5", "3.3550", "2.4025"),
("13.5", "5.0075" , "12.5", "4.7550", "5.7075"),
("13.5", "8.3125" , "12.5", "9.9650", "9.0125"),
("13.5", "11.6175" , "12.5", "11.3650", "12.3175"),
("13.5", "14.9225" , "12.5", "16.5750", "15.6225"),
("13.5", "18.2275" , "12.5", "17.9750", "18.9275"),
("13.5", "21.5325" , "12.5", "23.1850", "22.2325"),
("13.5", "24.8375" , "12.5", "24.5850", "25.5375")
]
def __init__(self,database,person,output,template, max):
creator = database.getResearcher().getName()
self.open_office = OpenOffice.OpenOfficeCore(output,template,".sxd",creator)
self.map = {}
self.database = database
self.start = person
self.max_generations = max
def setup(self):
self.file = self.open_office.setup()
def end(self):
self.open_office.end()
def filter(self,person,index):
if person == None or index >= 2**self.max_generations:
return
self.map[index] = person
family = person.getMainFamily()
if family != None:
self.filter(family.getFather(),index*2)
self.filter(family.getMother(),(index*2)+1)
def write_report(self):
self.filter(self.start,1)
generation = 0
need_header = 1
generation = 1
done = 0
page = 1
while done == 0:
done = 1
start = 2**(generation-1)
for index in range(start, (start*2)):
values = []
self.get_numbers(index,1,values)
if len(values) > 1 or generation == 1:
done = 0
self.print_page(index, generation, page)
page = page + 1
generation = generation + 3
def get_numbers(self,start,index,vals):
if index > 4:
return
if self.map.has_key(start):
vals.append(start)
self.get_numbers(start*2,index+1,vals)
self.get_numbers((start*2)+1,index+1,vals)
def print_page(self,start,generation, page):
self.file.write("<draw:page draw:name=\"")
self.file.write("Generation %d, page %d\" " % (generation, page))
self.file.write("draw:style-name=\"P0\" draw:master-page-name=\"Home\">")
self.draw_graph(1,start,0)
self.file.write("</draw:page>\n")
def draw_graph(self,index,start,level):
if self.map.has_key(start) and index <= 15:
person = self.map[start]
myPoints = AncestorChart.points[index-1]
self.file.write("<draw:rect draw:style-name=\"gr1\" svg:x=\"" + myPoints[0])
self.file.write("cm\" svg:y=\"" + myPoints[1] + "cm\" svg:width=\"5.5cm\"")
self.file.write(" svg:height=\"1.4cm\">\n")
self.file.write("<text:p text:style-name=\"P1\">")
self.file.write("<text:span text:style-name=\"T1\">")
self.file.write(person.getPrimaryName().getRegularName())
self.file.write("</text:span></text:p>\n");
birth = person.getBirth()
if birth and birth.getDate() != "":
self.file.write("<text:p text:style-name=\"P1\">")
self.file.write("<text:span text:style-name=\"T1\">b. ")
self.file.write(birth.getDate())
self.file.write("</text:span></text:p>\n");
death = person.getDeath()
if death and death.getDate() != "":
self.file.write("<text:p text:style-name=\"P1\">")
self.file.write("<text:span text:style-name=\"T1\">d. ")
self.file.write(death.getDate())
self.file.write("</text:span></text:p>\n");
self.file.write("</draw:rect>\n")
if myPoints[2] != "":
self.file.write("<draw:line draw:style-name=\"gr3\" ")
self.file.write("svg:x1=\"" + myPoints[2] + "cm\" svg:y1=\"")
self.file.write(myPoints[3] + "cm\" svg:x2=\"")
self.file.write(myPoints[2] + "cm\" svg:y2=\"" + myPoints[4] + "cm\">\n")
self.file.write("<text:p text:style-name=\"P2\"/>\n")
self.file.write("</draw:line>\n");
self.file.write("<draw:line draw:style-name=\"gr3\" ")
self.file.write("svg:x1=\"" + myPoints[2] + "cm\" svg:y1=\"")
self.file.write(myPoints[4] + "cm\" svg:x2=\"")
self.file.write(myPoints[0] + "cm\" svg:y2=\"" + myPoints[4] + "cm\">\n")
self.file.write("<text:p text:style-name=\"P2\"/>\n")
self.file.write("</draw:line>\n");
self.draw_graph(index*2,start*2,level+1)
self.draw_graph((index*2)+1,(start*2)+1,level+1)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "ancestorchart.glade"
topDialog = GladeXML(glade_file,"dialog1")
name = person.getPrimaryName().getRegularName()
topDialog.get_widget("labelTitle").set_text("Ancestor chart for " + name)
topDialog.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_save_clicked" : on_save_clicked
})
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_save_clicked(obj):
global active_person
global db
outputName = topDialog.get_widget("filename").get_text()
if outputName == "":
return
if outputName[-4:] != ".sxd":
outputName = outputName + ".sxd"
max_gen = topDialog.get_widget("generations").get_value_as_int()
template = const.dataDir + os.sep + "chart.sxd"
MyReport = AncestorChart(db,active_person,outputName,template, max_gen)
MyReport.setup()
MyReport.write_report()
MyReport.end()
utils.destroy_passed_object(obj)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Produces a graphical ancestral tree graph"
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_xpm_image():
return [
"48 48 4 1",
" c None",
". c #FFFFFF",
"+ c #C0C0C0",
"@ c #000000",
" ",
" ",
" ",
" ++++++++++++++++++++++++++++++++++ ",
" +................................+ ",
" +....................@@@@@@......+ ",
" +.................@@@@@@@@@......+ ",
" +.................@..............+ ",
" +.............@@@@@@.............+ ",
" +...........@@@@@@@@.............+ ",
" +...........@.....@..............+ ",
" +...........@.....@@@@@@@@@......+ ",
" +...........@........@@@@@@......+ ",
" +.......@@@@@@...................+ ",
" +.....@@@@@@@@...................+ ",
" +.....@.....@........@@@@@@......+ ",
" +.....@.....@.....@@@@@@@@@......+ ",
" +.....@.....@.....@..............+ ",
" +.....@.....@@@@@@@@.............+ ",
" +.....@.......@@@@@@.............+ ",
" +.....@...........@..............+ ",
" +.....@...........@@@@@@@@@......+ ",
" +.....@..............@@@@@@......+ ",
" +.@@@@@@.........................+ ",
" +.@@@@@@.........................+ ",
" +.....@..............@@@@@@......+ ",
" +.....@...........@@@@@@@@@......+ ",
" +.....@...........@..............+ ",
" +.....@.......@@@@@@.............+ ",
" +.....@.....@@@@@@@@.............+ ",
" +.....@.....@.....@..............+ ",
" +.....@.....@.....@@@@@@@@@......+ ",
" +.....@.....@........@@@@@@......+ ",
" +.....@@@@@@@@...................+ ",
" +.......@@@@@@...................+ ",
" +...........@........@@@@@@......+ ",
" +...........@.....@@@@@@@@@......+ ",
" +...........@.....@..............+ ",
" +...........@@@@@@@@.............+ ",
" +.............@@@@@@.............+ ",
" +.................@..............+ ",
" +.................@@@@@@@@@......+ ",
" +....................@@@@@@......+ ",
" +................................+ ",
" ++++++++++++++++++++++++++++++++++ ",
" ",
" ",
" "]

View File

@@ -0,0 +1,442 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"View/View an ancestor graph"
import RelLib
import os
import utils
from gtk import *
from gnome.ui import *
from libglade import *
col2person = {}
reportPerson = None
zoom = 1.0
boxwidth = 200
boxheight = 50
colsep = 30
shadow_offset = 5
topDialog = None
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def report(database,active_person):
global glade_file
global col2person
global zoom
global reportPerson
global topDialog
zoom = 1.0
base = os.path.dirname(__file__)
glade_file = base + os.sep + "ancestorgraph.glade"
dic = {
"destroy_passed_object" : utils.destroy_passed_object,
"on_ok_clicked" : on_ok_clicked,
"on_personList_select_row" : on_personList_select_row
}
topDialog = GladeXML(glade_file,"graph")
topDialog.signal_autoconnect(dic)
top = topDialog.get_widget("graph")
topDialog.get_widget("backgroundcolor").set_i8(255,255,255,0)
topDialog.get_widget("boxcolor").set_i8(255,255,255,0)
topDialog.get_widget("textcolor").set_i8(0,0,0,0)
topDialog.get_widget("bordercolor").set_i8(0,0,0,0)
personList = topDialog.get_widget("personList")
nameList = database.getPersonMap().values()
nameList.sort(mysort)
reportPerson = active_person
if active_person != None:
name = active_person.getPrimaryName().getName()
topDialog.get_widget("selectedPerson").set_text(name)
col2person = {}
index = 0
for person in nameList:
name = person.getPrimaryName().getName()
birth = person.getBirth()
if birth != None:
bdate = birth.getDate()
else:
bdate = ""
personList.append([name,bdate])
col2person[index] = person
index = index + 1
top.show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_personList_select_row(obj,a,b,c):
global reportPerson
global col2person
global topDialog
reportPerson = col2person[a]
name = reportPerson.getPrimaryName().getName()
topDialog.get_widget("selectedPerson").set_text(name)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
global reportPerson
global colsep
global boxwidth
global shadow_offset
global glade_file
global topDialog
if reportPerson == None:
return
req_depth = topDialog.get_widget("generations").get_value_as_int()
font = topDialog.get_widget("fontpicker").get_font_name()
dic = { "destroy_passed_object" : utils.destroy_passed_object,
"on_zoomin_clicked" : on_zoomin_clicked,
"on_zoomout_clicked" : on_zoomout_clicked
}
window = GladeXML(glade_file,"display")
window.signal_autoconnect(dic)
displayWindow = window.get_widget("display")
canvas = window.get_widget("canvas")
rootGroup = canvas.root()
max_depth = min(determine_depth(reportPerson,0)+1,req_depth)
max_size = (2 ** (max_depth-1)) * (boxheight+colsep+shadow_offset)
x_size = (boxwidth + colsep + shadow_offset) * (max_depth)
x_size = x_size + 3 * shadow_offset
y_size = max_size + (2*boxheight)
canvas.set_usize(x_size, y_size)
canvas.set_scroll_region(0, 0,x_size, y_size)
# bkgclr = topDialog.get_widget("backgroundcolor").get_i8()
# txtclr = topDialog.get_widget("textcolor").get_i8()
# bdrclr = topDialog.get_widget("bordercolor").get_i8()
# boxclr = topDialog.get_widget("boxcolor").get_i8()
# bkgcolor = GdkColor(bkgclr[0],bkgclr[1],bkgclr[2])
# txtcolor = GdkColor(txtclr[0],txtclr[1],txtclr[2])
# bdrcolor = GdkColor(bdrclr[0],bdrclr[1],bdrclr[2])
# boxcolor = GdkColor(boxclr[0],boxclr[1],boxclr[2])
bkgcolor = "white"
txtcolor = "black"
bdrcolor = "black"
boxcolor = "white"
border = rootGroup.add("rect",
x1=0,
y1=0,
x2=x_size,
y2=y_size,
fill_color=bkgcolor,
outline_color=txtcolor)
draw(rootGroup,
reportPerson,
colsep,
(max_size+boxheight+shadow_offset)/2.0,
max_size/4.0,
1,
max_depth,
boxcolor,
txtcolor,
bdrcolor,
font)
displayWindow.show()
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
# determine_depth
#
#-------------------------------------------------------------------------
def determine_depth(person, depth):
family = person.getMainFamily()
if family == None:
return depth
father = family.getFather()
mother = family.getMother()
father_depth = 0
mother_depth = 0
if father != None:
father_depth = determine_depth(father,depth+1)
if mother != None:
mother_depth = determine_depth(mother,depth+1)
if father_depth > mother_depth:
return father_depth
else:
return mother_depth
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_zoomin_clicked(obj):
global zoom
zoom = zoom * 1.5
obj.set_pixels_per_unit(zoom)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_zoomout_clicked(obj):
global zoom
zoom = zoom * (2.0/3.0)
obj.set_pixels_per_unit(zoom)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def line(group,x1,y1,x2,y2):
global colsep
pts = []
pts.append(x1)
pts.append(y1)
pts.append(x1+(colsep/2.0))
pts.append(y1)
pts.append(x1+(colsep/2.0))
pts.append(y2)
pts.append(x2)
pts.append(y2)
group.add("line", points=pts, fill_color="black")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def draw(group,reportPerson,x,y,incr,cur_depth,max_depth,bkg,txt,bdr,font):
global boxwidth
global colsep
global shadow_offset
name = reportPerson.getPrimaryName().getName()
family = reportPerson.getMainFamily()
add_box(group,name,x,y,bkg,txt,bdr,font)
if family != None and cur_depth < max_depth:
father = family.getFather()
if father != None:
line(group,
x+boxwidth+shadow_offset,
y+(boxheight/2.0),
x+boxwidth+colsep,
y-incr+(boxheight/2.0))
draw(group,
father,
x+boxwidth+colsep,
y-incr,
incr/2.0,
cur_depth+1,
max_depth,
bkg,
txt,
bdr,
font)
mother = family.getMother()
if mother != None:
line(group,
x+boxwidth+shadow_offset,
y+(boxheight/2.0),
x+boxwidth+colsep,
y+incr+(boxheight/2.0))
draw(group,
mother,
x+boxwidth+colsep,
y+incr,
incr/2.0,
cur_depth+1,
max_depth,
bkg,
txt,
bdr,
font)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def add_box(parentgroup,mytext, x1, y1,bkg,txt,bdr,font):
global boxheight
global boxwidth
global colsep
global shadow_offset
pad = 3
group = parentgroup.add("group",x=x1,y=y1);
shadow = group.add("rect");
border = group.add("rect");
text = group.add("text",
text=mytext,
font=font,
x=pad,
y=boxheight/2.0,
fill_color=txt,
anchor=ANCHOR_WEST)
border.set(x1=0,
y1=0,
x2=boxwidth+pad,
y2=boxheight,
fill_color=bkg,
outline_color=bdr)
shadow.set(x1=shadow_offset,
y1=shadow_offset,
x2=boxwidth+pad+shadow_offset,
y2=boxheight+shadow_offset,
fill_color="gray",
outline_color="gray")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def mysort(first, second) :
name1 = first.getPrimaryName()
name2 = second.getPrimaryName()
if name1.getSurname() == name2.getSurname():
if name1.getFirstName() == name2.getFirstName():
return cmp(name1.getSuffix(), name2.getSuffix())
else:
return cmp(name1.getFirstName(), name2.getFirstName())
else:
return cmp(name1.getSurname(), name2.getSurname())
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Produces a graphical ancestral tree graph"
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_xpm_image():
return [
"48 48 4 1",
" c None",
". c #FFFFFF",
"+ c #C0C0C0",
"@ c #000000",
" ",
" ",
" ",
" ++++++++++++++++++++++++++++++++++ ",
" +................................+ ",
" +....................@@@@@@......+ ",
" +.................@@@@@@@@@......+ ",
" +.................@..............+ ",
" +.............@@@@@@.............+ ",
" +...........@@@@@@@@.............+ ",
" +...........@.....@..............+ ",
" +...........@.....@@@@@@@@@......+ ",
" +...........@........@@@@@@......+ ",
" +.......@@@@@@...................+ ",
" +.....@@@@@@@@...................+ ",
" +.....@.....@........@@@@@@......+ ",
" +.....@.....@.....@@@@@@@@@......+ ",
" +.....@.....@.....@..............+ ",
" +.....@.....@@@@@@@@.............+ ",
" +.....@.......@@@@@@.............+ ",
" +.....@...........@..............+ ",
" +.....@...........@@@@@@@@@......+ ",
" +.....@..............@@@@@@......+ ",
" +.@@@@@@.........................+ ",
" +.@@@@@@.........................+ ",
" +.....@..............@@@@@@......+ ",
" +.....@...........@@@@@@@@@......+ ",
" +.....@...........@..............+ ",
" +.....@.......@@@@@@.............+ ",
" +.....@.....@@@@@@@@.............+ ",
" +.....@.....@.....@..............+ ",
" +.....@.....@.....@@@@@@@@@......+ ",
" +.....@.....@........@@@@@@......+ ",
" +.....@@@@@@@@...................+ ",
" +.......@@@@@@...................+ ",
" +...........@........@@@@@@......+ ",
" +...........@.....@@@@@@@@@......+ ",
" +...........@.....@..............+ ",
" +...........@@@@@@@@.............+ ",
" +.............@@@@@@.............+ ",
" +.................@..............+ ",
" +.................@@@@@@@@@......+ ",
" +....................@@@@@@......+ ",
" +................................+ ",
" ++++++++++++++++++++++++++++++++++ ",
" ",
" ",
" "]

View File

@@ -0,0 +1,816 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Ahnentalfel Chart"
import RelLib
import const
import os
import re
import sort
import string
import utils
import OpenOffice
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
active_person = None
db = None
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class AncestorReport:
gen = {
1 : "First",
2 : "Second",
3 : "Third",
4 : "Fourth",
5 : "Fifth",
6 : "Sixth",
7 : "Seventh",
8 : "Eighth",
9 : "Ninth",
10: "Tenth",
11: "Eleventh",
12: "Twelfth",
13: "Thirteenth",
14: "Fourteenth",
15: "Fifteenth",
16: "Sixteenth",
17: "Seventeenth",
18: "Eigthteenth",
19: "Nineteenth",
20: "Twentieth",
21: "Twenty-first",
22: "Twenty-second",
23: "Twenty-third",
24: "Twenty-fourth",
25: "Twenty-fifth",
26: "Twenty-sixth",
27: "Twenty-seventh",
28: "Twenty-eighth",
29: "Twenty-ninth"
}
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,database,person,output,max,pgbrk):
self.map = {}
self.database = database
self.start = person
self.output = output
self.max_generations = max
self.pgbrk = pgbrk
self.file = None
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.file.close()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def filter(self,person,index):
if person == None or index >= 2**self.max_generations:
return
self.map[index] = person
family = person.getMainFamily()
if family != None:
self.filter(family.getFather(),index*2)
self.filter(family.getMother(),(index*2)+1)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_title(self,name):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_start(self,newpage):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_stop(self):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_begin(self):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_end(self):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_start(self,number,heading):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_stop(self):
pass
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_report(self):
self.filter(self.start,1)
name = self.start.getPrimaryName().getRegularName()
self.write_title("Ahnentalfel Chart for " + name)
keys = self.map.keys()
keys.sort()
generation = 0
need_header = 1
for key in keys :
if generation == 0 or key >= 2**generation:
if generation == 0:
self.heading_start(0)
else:
self.list_end()
self.heading_start(self.pgbrk)
self.file.write(AncestorReport.gen[generation+1 ]+ " Generation")
self.heading_stop()
self.list_begin()
generation = generation + 1
person = self.map[key]
name = person.getPrimaryName().getRegularName()
self.list_para_start(str(key) + ".", name )
# Check birth record
birth = person.getBirth()
if birth:
date = birth.getDateObj()
place = birth.getPlace()
if date.getDate() != "" or place != "":
self.file.write(" was born")
if date.getDate() != "":
if date.getDay() != -1 and date.getMonth() != -1:
self.file.write(" on ")
else:
self.file.write(" in ")
self.file.write(date.getDate())
if place != "":
self.file.write(" in " + place)
if place == "" or place[-1] != '.':
self.file.write(".")
self.file.write("\n")
else:
self.file.write(".\n")
death = person.getDeath()
buried = None
for event in person.getEventList():
if string.lower(event.getName()) == "burial":
buried = event
if death:
date = death.getDateObj()
place = death.getPlace()
if date.getDate() != "" or place != "":
if person.getGender() == RelLib.Person.male:
self.file.write("He")
else:
self.file.write("She")
self.file.write(" died")
if date.getDate() != "":
if date.getDay() != -1 and date.getMonth() != -1:
self.file.write(" on ")
else:
self.file.write(" in ")
self.file.write(date.getDate())
if place != "":
self.file.write(" in " + place)
if buried:
date = buried.getDateObj()
place = buried.getPlace()
if date.getDate() != "" or place != "":
self.file.write(", and was buried")
if date.getDate() != "":
if date.getDay() != -1 and date.getMonth() != -1:
self.file.write(" on ")
else:
self.file.write(" in ")
self.file.write(date.getDate())
if place != "":
self.file.write(" in " + place)
if place == "" or place[-1] != '.':
self.file.write(".")
self.file.write("\n")
else:
self.file.write(".\n")
self.list_para_stop()
self.list_end()
self.end()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class OpenOfficeAncestorReport(AncestorReport):
def __init__(self,database,person,output,max,pgbrk,template):
creator = database.getResearcher().getName()
self.open_office = OpenOffice.OpenOfficeCore(output,template,".sxw",creator)
AncestorReport.__init__(self,database,person,output,max,pgbrk)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
self.file = self.open_office.setup()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.open_office.end()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_title(self,name):
self.file.write("<text:h text:style-name=\"P1\" ")
self.file.write("text:level=\"1\">" + name + "</text:h>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_start(self,newpage):
if newpage :
self.file.write("<text:h text:style-name=\"P2\"")
else:
self.file.write("<text:h text:style-name=\"Heading 2\"")
self.file.write(" text:level=\"2\">")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_stop(self):
self.file.write("</text:h>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_start(self,number,heading):
self.file.write("<text:p text:style-name=\"Hanging indent\">")
self.file.write(number + "<text:tab-stop/>")
self.file.write("<text:span text:style-name=\"T1\">")
self.file.write(heading + "</text:span>")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_stop(self):
self.file.write("</text:p>\n")
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class AncestorReportHtml(AncestorReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,database,person,output,max,pgbrk,template):
self.template = template
AncestorReport.__init__(self,database,person,output,max,pgbrk)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_title(self,name):
self.file.write("<H1>" + name + "</H1>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_start(self,newpage):
self.file.write("<H2>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_stop(self):
self.file.write("</H2>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_start(self,number,heading):
self.file.write("<LI VALUE=\"" + number + "\">")
self.file.write("<STRONG>" + heading + "</STRONG>")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_stop(self):
self.file.write("</LI>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
if self.template == "":
self.first = [
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">\n',
'<HTML>\n',
'<HEAD>\n',
'<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">\n',
'<TITLE>\n',
'</TITLE>\n',
'</HEAD>\n',
'<BODY>\n',
'<!-- START -->\n'
]
self.last = [
'<!-- STOP -->\n',
'</BODY>\n',
'</HTML>\n'
]
else:
start = re.compile(r"<!-- START -->")
templateFile = open(self.template,"r")
lines = templateFile.readlines()
templateFile.close()
in_last = 0
for line in lines:
if start.search(line):
in_last = 1
self.last.append(line);
elif in_last == 0:
self.first.append(line)
else:
self.last.append(line);
self.file = open(self.output,"w")
titleRe = re.compile(r"<TITLE>")
for line in self.first:
if titleRe.search(line):
name = self.start.getPrimaryName().getRegularName()
self.file.write(line)
self.file.write("Ahnentafel Chart for " + name)
else:
self.file.write(line)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
for line in self.last:
self.file.write(line)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_begin(self):
self.file.write("<OL>\n");
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_end(self):
self.file.write("</OL>\n");
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class AncestorReportAbiword(AncestorReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_title(self,name):
self.file.write('<p style="Heading 1">' + name + '</p>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_start(self,newpage):
self.file.write('<p style="Heading 2">')
if newpage:
self.file.write('<pbr/>')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_stop(self):
self.file.write("</p>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_start(self,number,heading):
self.file.write('<p props="margin-left:0.5000in; text-indent:-0.5000in">')
self.file.write(number + '\t')
self.file.write('<c props="font-weight:bold">')
self.file.write(heading)
self.file.write('</c>')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_stop(self):
self.file.write("</p>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
self.file = open(self.output,"w")
self.file.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
self.file.write('<abiword version="0.7.12">\n')
self.file.write('<section>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.file.write('</section>\n')
self.file.write('</abiword>\n')
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class AncestorReportLatex(AncestorReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_start(self,newpage):
if newpage:
self.file.write("\\newpage\n")
self.file.write("\\section{")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def heading_stop(self):
self.file.write("}\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_para_start(self,number,heading):
self.file.write("\\item{" + number + "}\n")
self.file.write("\\textbf{" + heading + "}")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
self.first = [
"\\documentclass{article}\n",
"\\usepackage{makeidx}\n",
"\\makeindex\n",
"\\begin{document}\n"
]
self.last = [
"\\newpage\n",
"\\printindex\n",
"\\end{document}\n"
]
self.file = open(self.output,"w")
for line in self.first:
self.file.write(line)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_title(self,name):
self.file.write("\\title{%s}\n" % name)
self.file.write("\\author{}\n")
self.file.write("\\maketitle\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_begin(self):
self.file.write("\\begin{description}\n");
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def list_end(self):
self.file.write("\\end{description}\n");
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
for line in self.last:
self.file.write(line)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "ancestorreport.glade"
topDialog = GladeXML(glade_file,"dialog1")
topDialog.get_widget("htmltemplate").set_sensitive(0)
name = person.getPrimaryName().getRegularName()
topDialog.get_widget("labelTitle").set_text("Ahnentalfel Report for " + name)
topDialog.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_save_clicked" : on_save_clicked,
"on_html_toggled" : on_html_toggled
})
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_html_toggled(obj):
if obj.get_active():
topDialog.get_widget("htmltemplate").set_sensitive(1)
else:
topDialog.get_widget("htmltemplate").set_sensitive(0)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_save_clicked(obj):
global active_person
global db
outputName = topDialog.get_widget("filename").get_text()
max_gen = topDialog.get_widget("generations").get_value_as_int()
pgbrk = topDialog.get_widget("pagebreak").get_active()
if outputName == "":
return
if topDialog.get_widget("openoffice").get_active():
template = const.dataDir + os.sep + "base.sxw"
if outputName[-4:] != ".sxw":
outputName = outputName + ".sxw"
MyReport = OpenOfficeAncestorReport(db,active_person,outputName,\
max_gen, pgbrk, template )
elif topDialog.get_widget("html").get_active():
template = topDialog.get_widget("htmlfile").get_text()
MyReport = AncestorReportHtml(db,active_person,outputName,\
max_gen, pgbrk, template)
elif topDialog.get_widget("abiword").get_active():
if outputName[-4:] != ".abw":
outputName = outputName + ".abw"
MyReport = AncestorReportAbiword(db,active_person,outputName,\
max_gen, pgbrk)
else:
MyReport = AncestorReportLatex(db,active_person,outputName,\
max_gen, pgbrk)
MyReport.setup()
MyReport.write_report()
utils.destroy_passed_object(obj)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Produces a textual ancestral report"
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_xpm_image():
return [
"48 48 4 1",
" c None",
". c #FFFFFF",
"+ c #C0C0C0",
"@ c #000000",
" ",
" ",
" ",
" ++++++++++++++++++++++++++++++++++ ",
" +................................+ ",
" +................................+ ",
" +...@@@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +...@@@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +.....@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +........@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +.....@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +........@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +.....@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +.........@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +.....@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +.........@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +.........@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +.....@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +.........@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +.....@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +.........@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +................................+ ",
" +................................+ ",
" ++++++++++++++++++++++++++++++++++ ",
" ",
" ",
" "]

View File

@@ -0,0 +1,94 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Database Processing/Rename personal event types"
import os
from gtk import *
from gnome.ui import *
from libglade import *
import RelLib
import const
import utils
topDialog = None
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_apply_clicked(obj):
original = topDialog.get_widget("original_text").get_text()
new = topDialog.get_widget("new_text").get_text()
for person in db.getPersonMap().values():
for event in person.getEventList():
if event.getName() == original:
event.setName(new)
utils.modified()
on_close_clicked(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_close_clicked(obj):
obj.destroy()
while events_pending():
mainiteration()
#-------------------------------------------------------------------------
#
#
#-------------------------------------------------------------------------
def runTool(database,person,callback):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "changetype.glade"
topDialog = GladeXML(glade_file,"top")
topDialog.get_widget("original").set_popdown_strings(const.personalEvents)
topDialog.get_widget("new").set_popdown_strings(const.personalEvents)
topDialog.signal_autoconnect({
"on_close_clicked" : on_close_clicked,
"on_apply_clicked" : on_apply_clicked
})
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Allows all the events of a certain name to be renamed to a new name"

169
gramps/src/plugins/Check.py Normal file
View File

@@ -0,0 +1,169 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Database Processing/Check database integrity"
import RelLib
import utils
import soundex
import Config
import string
import os
from gtk import *
from gnome.ui import *
from libglade import *
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def runTool(database,active_person,callback):
checker = CheckIntegrity(database)
checker.check_for_broken_family_links()
checker.cleanup_missing_photos()
checker.cleanup_empty_families(0)
checker.report()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class CheckIntegrity:
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def __init__(self,db):
self.db = db
self.bad_family_photo = []
self.bad_person_photo = []
self.empty_family = []
self.broken_links = []
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def check_for_broken_family_links(self):
self.broken_links = []
family_list = self.db.getFamilyMap().values()[:]
for family in family_list:
for child in family.getChildList():
if family == child.getMainFamily():
continue
for family_type in child.getAltFamilyList():
if family_type[0] == family:
break
else:
self.broken_links.append((child,family))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def cleanup_missing_photos(self):
for family in self.db.getFamilyMap().values():
for photo in family.getPhotoList():
if not os.path.isfile(photo.getPath()):
self.bad_family_photo.append(family,photo)
for person in self.db.getPersonMap().values():
for photo in person.getPhotoList():
if not os.path.isfile(photo.getPath()):
self.bad_person_photo.append(person,photo)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def cleanup_empty_families(self,automatic):
family_list = self.db.getFamilyMap().values()[:]
for family in family_list:
child_list = family.getChildList()[:]
num_kids = len(child_list)
father = family.getFather()
mother = family.getMother()
if num_kids == 0:
if father or mother:
continue
elif not father and not mother:
self.db.deleteFamily(family)
elif automatic:
self.db.deleteFamily(family)
else:
self.empty_family.append(family)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def report(self):
fphotos = len(self.bad_family_photo)
pphotos = len(self.bad_person_photo)
efam = len(self.empty_family)
blink = len(self.broken_links)
errors = blink + efam + pphotos + fphotos
if errors == 0:
GnomeOkDialog("No errors were found")
return
text = ""
if blink == 1:
text = text + "1 broken family link was found\n"
elif blink > 1:
text = text + "%d broken family links were found\n" % blink
if efam == 1:
text = text + "1 empty family was found\n"
elif efam > 1:
text = text + "%d empty families were found\n" % efam
if fphotos == 1:
text = text + "1 broken family photo was found\n"
elif fphotos > 1:
text = text + "%d broken family photos were found\n" % fphotos
if pphotos == 1:
text = text + "1 broken personal photo was found\n"
elif pphotos > 1:
text = text + "%d broken personal photos were found\n" % pphotos
GnomeWarningDialog(string.strip(text))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Checks the database for any relationship errors"

View File

@@ -0,0 +1,86 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Analysis and Exploration/Interactive descendant browser"
from RelLib import *
import re
import string
import os
import utils
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def runTool(database,person,callback):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "desbrowse.glade"
topDialog = GladeXML(glade_file,"top")
topDialog.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
})
top = topDialog.get_widget("top")
tree= topDialog.get_widget("tree1")
add_to_tree(tree,active_person)
top.show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def add_to_tree(tree,person):
item = GtkTreeItem(person.getPrimaryName().getName())
item.show()
tree.append(item)
subtree = None
for family in person.getFamilyList():
for child in family.getChildList():
if subtree == None:
subtree = GtkTree()
subtree.show()
item.set_subtree(subtree)
add_to_tree(subtree,child)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Provides a browsable hierarchy of the active person"

View File

@@ -0,0 +1,339 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Descendant Report"
import RelLib
import const
import os
import re
import sort
import string
import OpenOffice
import utils
import const
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class DescendantReport:
def __init__(self,name,person):
self.name = name
self.person = person
def setup(self):
pass
def report(self):
pass
def end(self):
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class OpenOfficeDesReport(DescendantReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,name,person,db):
self.creator = db.getResearcher().getName()
DescendantReport.__init__(self,name,person)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self,template):
self.open_office = OpenOffice.OpenOfficeCore(self.name,template,\
".sxw",self.creator)
self.file = self.open_office.setup()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.open_office.end()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def report(self):
self.file.write('<text:p text:style-name="Title">')
self.file.write('Descendants of ')
self.file.write(self.person.getPrimaryName().getRegularName())
self.file.write('</text:p>\n')
self.dump(1,self.person)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def dump(self,level,person):
self.file.write('<text:p text:style-name="P' + str(level) + '">')
self.file.write(str(level) + '. ')
self.file.write(person.getPrimaryName().getRegularName())
birth = person.getBirth().getDateObj().getYear()
death = person.getDeath().getDateObj().getYear()
if birth != -1 or death != -1:
self.file.write(' (')
if birth != -1:
self.file.write('b. ' + str(birth))
if death != -1:
if birth != -1:
self.file.write(', ')
self.file.write('d. ' + str(death))
self.file.write(')')
self.file.write('</text:p>\n')
for family in person.getFamilyList():
for child in family.getChildList():
self.dump(level+1,child)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class AbiwordDesReport(DescendantReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self,template):
if self.name[-4:] != ".abw":
self.name = self.name + ".abw"
self.file = open(self.name,"w")
self.file.write('<?xml version="1.0" encoding="ISO-8859-1"?>\n')
self.file.write('<abiword version="0.7.12">\n')
self.file.write('<section>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.file.write('</section>\n')
self.file.write('</abiword>\n')
self.file.close()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def report(self):
self.file.write('<p style="Heading 1">')
self.file.write('Descendants of ')
self.file.write(self.person.getPrimaryName().getRegularName())
self.file.write('</p>\n')
self.dump(1,self.person)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def dump(self,level,person):
self.file.write('<p style="Normal"')
if level > 1:
self.file.write(' props="margin-left:')
val = float(level-1) / 2.0
self.file.write("%6.3fin\"" % (val))
self.file.write('>')
self.file.write(str(level) + '. ')
self.file.write(person.getPrimaryName().getRegularName())
birth = person.getBirth().getDateObj().getYear()
death = person.getDeath().getDateObj().getYear()
if birth != -1 or death != -1:
self.file.write(' (')
if birth != -1:
self.file.write('b. ' + str(birth))
if death != -1:
if birth != -1:
self.file.write(', ')
self.file.write('d. ' + str(death))
self.file.write(')')
self.file.write('</p>\n')
for family in person.getFamilyList():
for child in family.getChildList():
self.dump(level+1,child)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class DesReportWindow:
def __init__(self,person,db):
self.person = person
glade_file = os.path.dirname(__file__) + os.sep + "desreport.glade"
self.top = GladeXML(glade_file,"dialog1")
self.top.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_html_toggled": on_html_toggled,
"on_save_clicked": on_save_clicked
})
mytop = self.top.get_widget("dialog1")
mytop.set_data("o",self)
mytop.set_data("d",db)
mytop.show()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
report = DesReportWindow(person,database)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_save_clicked(obj):
myobj = obj.get_data("o")
db = obj.get_data("d")
file = myobj.top.get_widget("filename").get_text()
if file == "":
return
if myobj.top.get_widget("openoffice").get_active():
report = OpenOfficeDesReport(file,myobj.person,db)
elif myobj.top.get_widget("abiword").get_active():
report = AbiwordDesReport(file,myobj.person)
else:
return
report.setup(const.dataDir + os.sep + "deslist.sxw")
report.report()
report.end()
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_html_toggled(obj):
myobj = obj.get_data(OBJECT)
if myobj.form.get_widget("html").get_active():
myobj.form.get_widget("htmltemplate").set_sensitive(1)
else:
myobj.form.get_widget("htmltemplate").set_sensitive(0)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Generates a list of descendants of the active person"
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_xpm_image():
return [
"48 48 4 1",
" c None",
". c #FFFFFF",
"+ c #C0C0C0",
"@ c #000000",
" ",
" ",
" ",
" ++++++++++++++++++++++++++++++++++ ",
" +................................+ ",
" +...@@@@@@@@@@@@@@@@@@@@@@@@@@...+ ",
" +................................+ ",
" +................................+ ",
" +...@@@@@@@@@@@..................+ ",
" +................................+ ",
" +................................+ ",
" +......@@@@@@@@@@@...............+ ",
" +................................+ ",
" +................................+ ",
" +.........@@@@@@@@@@@............+ ",
" +................................+ ",
" +................................+ ",
" +......@@@@@@@@@@@...............+ ",
" +................................+ ",
" +................................+ ",
" +.........@@@@@@@@@@@............+ ",
" +................................+ ",
" +................................+ ",
" +.............@@@@@@@@@@@........+ ",
" +................................+ ",
" +................................+ ",
" +.............@@@@@@@@@@@........+ ",
" +................................+ ",
" +................................+ ",
" +......@@@@@@@@@@@...............+ ",
" +................................+ ",
" +................................+ ",
" +.........@@@@@@@@@@@............+ ",
" +................................+ ",
" +................................+ ",
" +............@@@@@@@@@@@.........+ ",
" +................................+ ",
" +................................+ ",
" +................@@@@@@@@@@......+ ",
" +................................+ ",
" +................................+ ",
" +................@@@@@@@@@@......+ ",
" +................................+ ",
" +................................+ ",
" ++++++++++++++++++++++++++++++++++ ",
" ",
" ",
" "]

View File

@@ -0,0 +1,698 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Analysis and Exploration/Compare individual events"
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
import os
import re
import sort
import utils
import string
import OpenOffice
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
import ListColors
import Filter
import const
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
OBJECT = "o"
INDEX = "i"
FUNCTION = "f"
QUALIFIER= "q"
FILTER = "x"
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class TableReport:
def __init__(self,filename):
self.filename = filename
def initialize(self):
pass
def finalize(self):
pass
def write_table_head():
pass
def set_row(self,val):
pass
def write_table_data():
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class OpenOfficeTable(TableReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def initialize(self):
templateFile = const.dataDir + os.sep + "table.sxc"
self.open_office = OpenOffice.OpenOfficeCore(self.filename,\
templateFile,".sxc")
self.file = self.open_office.setup()
self.file.write('<table:table table:name="Sheet1" table:style-name="ta1">\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def finalize(self):
self.file.write('</table:table>\n')
self.open_office.end()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_table_data(self,data):
length = len(data)
self.file.write('<table:table-row table:style-name="ro1">\n')
for item in data:
self.file.write('<table:table-cell table:style-name="ce' + str(self.row))
self.file.write('" table:value-type="string">\n')
self.file.write('<text:p>' + item + '</text:p>\n')
self.file.write('</table:table-cell>\n')
self.file.write('</table:table-row>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def set_row(self,val):
self.row = val + 2
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_table_head(self,data):
length = len(data)
self.prev = 3
self.file.write('<table:table-column table:style-name="co1" ')
self.file.write('table:number-columns-repeated="' + str(length+1) + '"/>\n')
self.file.write('<table:table-row table:style-name="ro1">\n')
for item in data:
self.file.write('<table:table-cell table:style-name="ce1" ')
self.file.write('table:value-type="string">\n')
self.file.write('<text:p>' + item + '</text:p>\n')
self.file.write('</table:table-cell>\n')
self.file.write('</table:table-row>\n')
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class HtmlTable(TableReport):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,file,template):
self.template = template
TableReport.__init__(self,file)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def initialize(self):
if self.template == "":
self.template = const.dataDir + os.sep + "table.html"
templateFile = open(self.template,"r")
lines = templateFile.readlines()
templateFile.close()
self.last = []
self.first = []
in_last = 0
for line in lines:
if line[0:14] == "<!-- START -->":
in_last = 1
self.last.append(line);
elif in_last == 0:
self.first.append(line)
else:
self.last.append(line);
self.file = open(self.filename,"w")
for line in self.first:
self.file.write(line)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def finalize(self):
self.file.write("</table>")
for line in self.last:
self.file.write(line)
self.file.close()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_table_data(self,data):
length = len(data)
self.file.write('<tr>\n')
for item in data:
self.file.write('<td>\n')
if item == "":
self.file.write('&nbsp;')
else:
self.file.write(fix(item))
self.file.write('\n</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_table_head(self,data):
self.file.write('<table cellspacing=1 cellpadding=1 border=1>\n')
self.file.write('<tr>\n')
for item in data:
self.file.write('<th>\n')
self.file.write(fix(item))
self.file.write('\n</th>\n')
self.file.write('</tr>\n')
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class EventComparison:
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def __init__(self,database):
self.db = database
base = os.path.dirname(__file__)
self.glade_file = base + os.sep + "eventcmp.glade"
self.filterDialog = GladeXML(self.glade_file,"filters")
self.filterDialog.signal_autoconnect({
"on_add_clicked": on_add_clicked,
"on_delete_clicked":on_delete_clicked,
"on_select_row" : on_select_row,
"on_filter_save_clicked" : on_filter_save_clicked,
"on_apply_clicked":on_apply_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
top =self.filterDialog.get_widget("filters")
self.filter_menu = self.filterDialog.get_widget("filter_list")
self.filter_list_obj = self.filterDialog.get_widget("active_filters")
qualifier = self.filterDialog.get_widget("qualifier")
self.filter_list_obj.set_data(INDEX,-1)
self.filter_list_obj.set_data(OBJECT,self)
self.filter_list = []
myMenu = GtkMenu()
for filter in Filter.filterList:
menuitem = GtkMenuItem(filter)
myMenu.append(menuitem)
menuitem.set_data(FILTER,Filter.filterMap[filter])
menuitem.set_data(FUNCTION,Filter.filterEnb[filter])
menuitem.set_data(QUALIFIER,qualifier)
menuitem.connect("activate",on_filter_name_changed)
menuitem.show()
self.filter_menu.set_menu(myMenu)
top.set_data(OBJECT,self)
top.show()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def display_results(self):
my_list = []
for person in self.db.getPersonMap().values():
match = 1
for filter in self.filter_list:
if not filter.compare(person):
match = 0
if match == 1:
my_list.append(person)
if len(my_list) == 0:
GnomeWarningDialog("No matches were found")
return
self.topDialog = GladeXML(self.glade_file,"top")
self.topDialog.signal_autoconnect({
"on_write_table" : on_write_table,
"destroy_passed_object" : utils.destroy_passed_object
})
top = self.topDialog.get_widget("top")
top.set_data(OBJECT,self)
table = self.topDialog.get_widget("addarea")
my_list.sort(sort.by_last_name)
map = {}
for individual in my_list:
elist = individual.getEventList()
for event in elist:
name = event.getName()
if not name:
break
if map.has_key(name):
map[name] = map[name] + 1
else:
map[name] = 1
unsort_list = []
for item in map.keys():
unsort_list.append((map[item],item))
unsort_list.sort(by_value)
sort_list = []
for item in unsort_list:
sort_list.append(item[1])
event_titles = ["Person","Birth","Death"] + sort_list
eventlist = GtkCList(len(event_titles),event_titles)
eventlist.set_data(INDEX,-1)
table.add(eventlist)
eventlist.show()
color_clist = ListColors.ColorList(eventlist,2)
for individual in my_list:
name = individual.getPrimaryName().getName()
birth = individual.getBirth()
death = individual.getDeath()
map = {}
elist = individual.getEventList()[:]
for ievent in elist:
event_name = ievent.getName()
if map.has_key(event_name):
map[event_name].append(ievent)
else:
map[event_name] = [ievent]
first = 1
done = 0
while done == 0:
added = 0
if first:
tlist = [name,birth.getDate(),death.getDate()]
blist = ["",birth.getPlace(),death.getPlace()]
else:
tlist = ["","",""]
blist = ["","",""]
for ename in event_titles[3:]:
if map.has_key(ename) and len(map[ename]) > 0:
mylist = map[ename]
event = mylist[0]
del mylist[0]
tlist.append(event.getDate())
blist.append(event.getPlace())
added = 1
else:
tlist.append("")
blist.append("")
if first:
first = 0
color_clist.add(tlist)
color_clist.add(blist)
elif added == 0:
done = 1
else:
color_clist.add(tlist)
color_clist.add(blist)
for index in range(0,len(event_titles)):
eventlist.set_column_width(index,eventlist.optimal_column_width(index))
top.show()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def save_data(self):
my_list = []
for person in self.db.getPersonMap().values():
match = 1
for filter in self.filter_list:
if not filter.compare(person):
match = 0
if match == 1:
my_list.append(person)
my_list.sort(sort.by_last_name)
map = {}
for individual in my_list:
elist = individual.getEventList()[:]
for event in elist:
name = event.getName()
if not name:
break
if map.has_key(name):
map[name] = map[name] + 1
else:
map[name] = 1
unsort_list = []
for item in map.keys():
unsort_list.append((map[item],item))
unsort_list.sort(by_value)
sort_list = []
for item in unsort_list:
sort_list.append(item[1])
name = self.form.get_widget("filename").get_text()
if self.form.get_widget("openoffice").get_active():
spreadsheet = OpenOfficeTable(name)
elif self.form.get_widget("html").get_active():
template = self.form.get_widget("htmlfile").get_text()
spreadsheet = HtmlTable(name,template)
spreadsheet.initialize()
event_titles = ["Person","Birth","Death"] + sort_list
spreadsheet.write_table_head(event_titles)
index = 0
for individual in my_list:
spreadsheet.set_row(index%2)
index = index + 1
name = individual.getPrimaryName().getName()
birth = individual.getBirth()
death = individual.getDeath()
map = {}
elist = individual.getEventList()[:]
for ievent in elist:
event_name = ievent.getName()
if map.has_key(event_name):
map[event_name].append(ievent)
else:
map[event_name] = [ievent]
first = 1
done = 0
while done == 0:
added = 0
if first:
tlist = [name,birth.getDate(),death.getDate()]
blist = ["",birth.getPlace(),death.getPlace()]
else:
tlist = ["","",""]
blist = ["","",""]
for ename in event_titles[3:]:
if map.has_key(ename) and len(map[ename]) > 0:
mylist = map[ename]
event = mylist[0]
del mylist[0]
tlist.append(event.getDate())
blist.append(event.getPlace())
added = 1
else:
tlist.append("")
blist.append("")
if first:
first = 0
spreadsheet.write_table_data(tlist)
spreadsheet.write_table_data(blist)
elif added == 0:
done = 1
else:
spreadsheet.write_table_data(tlist)
spreadsheet.write_table_data(blist)
spreadsheet.finalize()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def display_save_form(self):
self.form = GladeXML(self.glade_file,"dialog1")
self.form.signal_autoconnect({
"on_save_clicked": on_save_clicked,
"on_html_toggled": on_html_toggled,
"destroy_passed_object" : utils.destroy_passed_object
})
self.save_form = self.form.get_widget("dialog1")
self.save_form.set_data(OBJECT,self)
self.save_form.show()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def runTool(database,person,callback):
EventComparison(database)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Genealogical Research Event Analysis Tool\n\n" \
"Aids in the analysis of data by allowing the development "\
"of custom filters that can be applied to the database to "\
"find similar events"
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_apply_clicked(obj):
myobj = obj.get_data(OBJECT)
myobj.display_results()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_write_table(obj):
myobj = obj.get_data(OBJECT)
myobj.display_save_form()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_save_clicked(obj):
myobj = obj.get_data(OBJECT)
myobj.save_data()
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_html_toggled(obj):
myobj = obj.get_data(OBJECT)
if myobj.form.get_widget("html").get_active():
myobj.form.get_widget("htmltemplate").set_sensitive(1)
else:
myobj.form.get_widget("htmltemplate").set_sensitive(0)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_double_click(obj,event):
import EditPerson
row = obj.get_data(INDEX)
if event.button == 1 and event.type == GDK._2BUTTON_PRESS and row != -1:
EditPerson.EditPerson(obj.get_row_data(row))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_select_row(obj,row,b,c):
obj.set_data(INDEX,row)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_delete_clicked(obj):
myobj = obj.get_data(OBJECT)
row = myobj.filter_list_obj.get_data(INDEX)
if row == -1:
return
myobj.filter_list_obj.remove(row)
myobj.filter_list_obj.set_data(INDEX,row-1)
myobj.filter_list_obj.unselect_all()
del myobj.filter_list[row]
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_add_clicked(obj):
myobj = obj.get_data(OBJECT)
invert = myobj.filterDialog.get_widget("invert").get_active()
qualifier = myobj.filterDialog.get_widget("qualifier").get_text()
menu = myobj.filter_menu.get_menu()
function = menu.get_active().get_data(FILTER)
myfilter = function(qualifier)
myfilter.set_invert(invert)
myobj.filter_list.append(myfilter)
row = myobj.filter_list_obj.get_data(INDEX)
myobj.filter_list_obj.set_data(INDEX,row+1)
if invert:
invert_text = "yes"
else:
invert_text = "no"
name = myfilter.__doc__
myobj.filter_list_obj.append([name,qualifier,invert_text])
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_filter_name_changed(obj):
function = obj.get_data(FUNCTION)
qualifier = obj.get_data(QUALIFIER)
qualifier.set_sensitive(function())
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def by_value(first,second):
return cmp(second[0],first[0])
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_filter_save_clicked(obj):
myobj = obj.get_data(OBJECT)
for filter in myobj.filter_list:
print "%s(\"%s\"),%d" % (filter,filter.text,filter.invert)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def fix(line):
l = string.strip(line)
l = string.replace(l,'&','&amp;')
l = string.replace(l,'>','&gt;')
l = string.replace(l,'<','&lt;')
return string.replace(l,'"','&quot;')

View File

@@ -0,0 +1,739 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Family Group Report"
import RelLib
import const
import os
import re
import sort
import string
import tempfile
import OpenOffice
import utils
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
active_person = None
db = None
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class FamilyGroup:
def __init__(self,database,family,output,template):
pass
def setup(self):
pass
def end(self):
pass
def write_header(self):
pass
def write_parent(self,type,name):
pass
def start_parent_stats(self):
pass
def end_parent_stats(self):
pass
def write_parent_stats(self,str1,str2,str3):
pass
def write_parent_parent(self,str1,str2):
pass
def start_child_stats(self):
pass
def end_child_stats(self):
pass
def write_child_stats(self,str1,str2,str3,str4,last):
pass
def write_child_name(self,index,child):
pass
def write_child_spouse(self,spouse):
pass
def dump_parent(self,person):
self.start_parent_stats();
if person.getGender() == RelLib.Person.male:
self.write_parent("Husband:",person)
else:
self.write_parent("Wife:",person)
birth = person.getBirth()
death = person.getDeath()
self.write_parent_stats("Birth",birth.getDate(),birth.getPlace())
self.write_parent_stats("Death",death.getDate(),death.getPlace())
family = person.getMainFamily()
if family == None or family.getFather() == None:
father_name = ""
else:
father_name = family.getFather().getPrimaryName().getRegularName()
if family == None or family.getMother() == None:
mother_name = ""
else:
mother_name = family.getMother().getPrimaryName().getRegularName()
self.write_parent_parent("Father",father_name)
self.write_parent_parent("Mother",mother_name)
self.end_parent_stats();
def dump_child(self,index,person):
self.start_child_stats();
birth = person.getBirth()
death = person.getDeath()
self.write_child_name(index,person)
families = len(person.getFamilyList())
self.write_child_stats("","Birth",birth.getDate(),\
birth.getPlace(),0)
if families == 0:
last = 1
else:
last = 0
self.write_child_stats("","Death",death.getDate(),\
death.getPlace(),last)
index = 1
for family in person.getFamilyList():
if person == family.getFather():
self.write_child_spouse(family.getMother())
else:
self.write_child_spouse(family.getFather())
m = family.getMarriage()
if families == index:
last = 1
else:
last = 0
self.write_child_stats("","Married",m.getDate(),m.getPlace(),last)
self.end_child_stats();
def write_report(self):
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class OpenOfficeFamilyGroup(FamilyGroup):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,database,family,output,template):
self.map = {}
self.database = database
self.family = family
creator = db.getResearcher().getName()
self.open_office = OpenOffice.OpenOfficeCore(output,template,".sxw",creator)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
self.file = self.open_office.setup()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.open_office.end()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_header(self):
self.file.write('<text:h text:style-name="Heading 1" ')
self.file.write('text:level="1">')
self.file.write('Family Group Record')
self.file.write('</text:h>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent(self,type,name):
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell ")
self.file.write("table:style-name=\"Table1.A3\" ")
self.file.write("table:number-columns-spanned=\"3\" ")
self.file.write("table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"ParentHead\">")
self.file.write(type)
self.file.write("<text:tab-stop/>")
self.file.write(name.getPrimaryName().getRegularName())
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:covered-table-cell>\n")
self.file.write("</table:covered-table-cell>\n")
self.file.write("<table:covered-table-cell>\n")
self.file.write("</table:covered-table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def start_parent_stats(self):
self.file.write("<table:table table:name=\"Table1\""\
" table:style-name=\"Table1\">\n")
self.file.write("<table:table-column table:style-name=\""\
"Table1.A\"/>\n")
self.file.write("<table:table-column table:style-name=\""\
"Table1.B\"/>\n")
self.file.write("<table:table-column table:style-name=\""
"Table1.C\"/>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end_parent_stats(self):
self.file.write("</table:table>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent_stats(self,str1,str2,str3):
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table1.A1\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">" + str1 + \
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table1.A1\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">" + str2 + \
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table1.A2\" table:value-type=\"string\">\n");
self.file.write("<text:p text:style-name=\"P4\">" + str3 +
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent_parent(self,str1,str2):
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table1.A1\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">" + str1 + \
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell ")
self.file.write("table:style-name=\"Table1.A1\" ")
self.file.write("table:number-columns-spanned=\"2\" ")
self.file.write("table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">")
self.file.write(str2)
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:covered-table-cell>\n")
self.file.write("</table:covered-table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def start_child_stats(self):
self.file.write("<table:table table:name=\"Table3\" "
"table:style-name=\"Table3\">\n")
self.file.write("<table:table-column table:style-name=\""\
"Table3.A\"/>\n")
self.file.write("<table:table-column table:style-name=\""\
"Table3.B\"/>\n")
self.file.write("<table:table-column table:style-name=\""\
"Table3.C\"/>\n")
self.file.write("<table:table-column table:style-name=\""\
"Table3.D\"/>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end_child_stats(self):
self.file.write("</table:table>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_stats(self,str1,str2,str3,str4,last):
self.file.write("<table:table-row>\n")
if last == 1:
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A2\" table:value-type=\"string\">\n")
else:
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A1\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">" + str1 +\
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A4\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">" + str2 +
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A4\" table:value-type=\"string\">\n");
self.file.write("<text:p text:style-name=\"P4\">" + str3 +
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A4\" table:value-type=\"string\">\n");
self.file.write("<text:p text:style-name=\"P4\">" + str4 +
"</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_name(self,index,child):
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A3\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">" + str(index))
if child.getGender() == RelLib.Person.male:
self.file.write("M")
else:
self.file.write("F")
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:number-columns-spanned"\
"=\"3\" table:style-name=\""\
"Table3.A5\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P2\">")
self.file.write(child.getPrimaryName().getRegularName())
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:covered-table-cell>\n")
self.file.write("</table:covered-table-cell>\n")
self.file.write("<table:covered-table-cell>\n")
self.file.write("</table:covered-table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_spouse(self,spouse):
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A1\" table:value-type=\"string\">\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:style-name=\""\
"Table3.A4\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">")
self.file.write("Spouse")
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell table:number-columns-spanned"\
"=\"2\" table:style-name=\""\
"Table3.A4\" table:value-type=\"string\">\n")
self.file.write("<text:p text:style-name=\"P4\">")
self.file.write(spouse.getPrimaryName().getRegularName())
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("<table:covered-table-cell>\n")
self.file.write("</table:covered-table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_report(self):
self.write_header()
self.dump_parent(self.family.getFather())
self.dump_parent(self.family.getMother())
if len(self.family.getChildList()) > 0:
self.file.write("<text:p text:style-name=\"ParentHead\">")
self.file.write("Children")
self.file.write("<text:tab-stop/>")
self.file.write("</text:p>\n")
index = 1
for child in self.family.getChildList():
self.dump_child(index,child)
index = index + 1
self.end()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class HtmlFamilyGroup(FamilyGroup):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,database,family,output,template):
self.map = {}
self.database = database
self.family = family
self.output = output
self.first = []
self.last = []
if template == "":
template = const.dataDir + os.sep + "family.html"
self.template = template
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def fix(self,str):
if str=="":
return "&nbsp;"
else:
return str
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
templateFile = open(self.template,"r")
lines = templateFile.readlines()
templateFile.close()
in_last = 0
for line in lines:
if line[0:14] == "<!-- START -->":
in_last = 1
self.last.append(line);
elif in_last == 0:
self.first.append(line)
else:
self.last.append(line);
self.file = open(self.output,"w")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_header(self):
for line in self.first:
self.file.write(line)
self.file.write("<H1>")
self.file.write("Family Group Record")
self.file.write("</H1>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
for line in self.last:
self.file.write(line)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent(self,type,name):
self.file.write('<tr>\n')
self.file.write('<td colspan="3" class="parent_name">')
self.file.write(type)
self.file.write(' ')
self.file.write(name.getPrimaryName().getRegularName())
self.file.write('</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def start_parent_stats(self):
self.file.write('<table cellspacing="1" width="100%" border="1">\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end_parent_stats(self):
self.file.write("</table>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent_stats(self,str1,str2,str3):
self.file.write('<tr>\n')
self.file.write('<td width="20%">' + self.fix(str1) + '</td>\n')
self.file.write('<td width="30%">' + self.fix(str2) + '</td>\n')
self.file.write('<td>' + self.fix(str3) + '</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent_parent(self,str1,str2):
self.file.write('<tr>\n')
self.file.write('<td>' + self.fix(str1) + '</td>\n')
self.file.write('<td colspan="2" class="child_name">' + self.fix(str2) + '</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def start_child_stats(self):
self.file.write('<table cellspacing="1" width="100%" border="1">\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end_child_stats(self):
self.file.write("</table>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_stats(self,str1,str2,str3,str4,last):
self.file.write('<tr>\n')
self.file.write('<td width="10%">' + self.fix(str1) + '</td>\n')
self.file.write('<td width="20%">' + self.fix(str2) + '</td>\n')
self.file.write('<td width="30%">' + self.fix(str3) + '</td>\n')
self.file.write('<td>' + self.fix(str4) + '</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_name(self,index,child):
self.file.write("<tr>\n")
self.file.write("<td>" + str(index))
if child.getGender() == RelLib.Person.male:
self.file.write("M")
else:
self.file.write("F")
self.file.write("</td>\n")
self.file.write("<td colspan=\"3\">")
self.file.write(child.getPrimaryName().getRegularName())
self.file.write("</td>\n")
self.file.write("</tr>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_spouse(self,spouse):
self.file.write("<tr>\n")
self.file.write("<td>&nbsp;</td>\n")
self.file.write("<td>Spouse</td>\n")
self.file.write("<td colspan=\"2\">")
self.file.write(spouse.getPrimaryName().getRegularName())
self.file.write("</td>\n")
self.file.write("</tr>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_report(self):
self.write_header()
self.dump_parent(self.family.getFather())
self.dump_parent(self.family.getMother())
if len(self.family.getChildList()) > 0:
self.file.write("<H2>")
self.file.write("Children")
self.file.write("</H2>\n")
index = 1
for child in self.family.getChildList():
self.dump_child(index,child)
index = index + 1
self.end()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "familygroup.glade"
topDialog = GladeXML(glade_file,"dialog1")
name = person.getPrimaryName().getRegularName()
family_list = person.getFamilyList()
label = topDialog.get_widget("labelTitle")
label.set_text("Family Group chart for " + name)
topDialog.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_save_clicked" : on_save_clicked,
"on_html_toggled" : on_html_toggled
})
frame = topDialog.get_widget("spouse")
option_menu = topDialog.get_widget("spouse_menu")
if len(family_list) > 1:
frame.show()
else:
frame.hide()
my_menu = GtkMenu()
for family in family_list:
if person == family.getFather():
spouse = family.getMother()
else:
spouse = family.getFather()
item = GtkMenuItem(spouse.getPrimaryName().getName())
item.set_data("f",family)
item.show()
my_menu.append(item)
option_menu.set_menu(my_menu)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_html_toggled(obj):
topDialog.get_widget("htmltemplate").set_sensitive(obj.get_active())
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_save_clicked(obj):
global active_person
global db
outputName = topDialog.get_widget("filename").get_text()
if outputName == "":
return
menu = topDialog.get_widget("spouse_menu").get_menu()
family = menu.get_active().get_data("f")
if topDialog.get_widget("html").get_active():
template = topDialog.get_widget("htmlfile").get_text()
MyReport = HtmlFamilyGroup(db,family,outputName,template)
else:
template = const.dataDir + os.sep + "familygrp.sxw"
MyReport = OpenOfficeFamilyGroup(db,family,outputName,template)
MyReport.setup()
MyReport.write_report()
utils.destroy_passed_object(obj)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Creates a family group report, showing information on "\
"a set of parents and their children."

View File

@@ -0,0 +1,247 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Relationship graph"
from RelLib import *
import os
import re
import sort
import string
import utils
from gtk import *
from gnome.ui import *
from libglade import *
active_person = None
db = None
topDialog = None
glade_file = None
ind_list = []
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def ancestor_filter(database,person,list):
if person == None:
return
if person not in list:
list.append(person)
family = person.getMainFamily()
if family != None:
ancestor_filter(database,family.getFather(),list)
ancestor_filter(database,family.getMother(),list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def descendant_filter(database,person,list):
if person == None:
return
if person not in list:
list.append(person)
for family in person.getFamilyList():
for child in family.getChildList():
descendant_filter(database,child,list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def an_des_filter(database,person,list):
descendant_filter(database,person,list)
ancestor_filter(database,person,list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def entire_db_filter(database,person,list):
for entry in database.getPersonMap().values():
list.append(entry)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
filter_map = {
"Ancestors" : ancestor_filter,
"Descendants" : descendant_filter,
"Ancestors and Descendants" : an_des_filter,
"Entire Database" : entire_db_filter
}
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "graphviz.glade"
dic = {
"destroy_passed_object" : utils.destroy_passed_object,
"on_ok_clicked" : on_ok_clicked,
}
topDialog = GladeXML(glade_file,"top")
topDialog.signal_autoconnect(dic)
top = topDialog.get_widget("top")
topDialog.get_widget("targetDirectory").set_default_path(os.getcwd())
filterName = topDialog.get_widget("filterName")
popdown_strings = filter_map.keys()
popdown_strings.sort()
filterName.set_popdown_strings(popdown_strings)
name = person.getPrimaryName().getName()
topDialog.get_widget("personName").set_text(name)
top.show()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_ok_clicked(obj):
global active_person
global filter_map
global db
global glade_file
global ind_list
filterName = topDialog.get_widget("filter").get_text()
file_name = topDialog.get_widget("filename").get_text()
if file_name == "":
return
paper = topDialog.get_widget("paper")
multi = topDialog.get_widget("multi").get_active()
scaled = topDialog.get_widget("scaled").get_active()
portrait = topDialog.get_widget("portrait").get_active()
width = paper.get_width()/72.0
height = paper.get_height()/72.0
file = open(file_name,"w")
filter = filter_map[filterName]
ind_list = []
filter(db,active_person,ind_list)
file.write("digraph g {\n")
file.write("bgcolor=white;\n")
file.write("rankdir=LR;\n")
file.write("center=1;\n")
if scaled == 1:
file.write("size=\"%3.1fin,%3.1fin\";\n" % (width-0.5,height-0.5))
file.write("ratio=compress;\n")
else:
file.write("ratio=auto;\n")
if multi == 1:
file.write("page=\"%3.1f,%3.1f\";\n" % (width,height))
if portrait == 1:
file.write("orientation=portrait;\n")
else:
file.write("orientation=landscape;\n")
if len(ind_list) > 1:
dump_index(ind_list,file)
dump_person(ind_list,file)
file.write("}\n")
file.close()
utils.destroy_passed_object(obj)
#########################################################################
#
# Write a web page for a specific person represented by the key
#
#########################################################################
def dump_person(person_list,file):
for person in person_list:
family = person.getMainFamily()
if family == None:
continue
father = family.getFather()
if father and father in person_list:
file.write('p' + str(person.getId()) + ' -> p')
file.write(str(father.getId()) + ';\n')
mother = family.getMother()
if mother and mother in person_list:
file.write('p' + str(person.getId()) + ' -> p')
file.write(str(mother.getId()) + ';\n')
#########################################################################
#
# Write a web page for a specific person represented by the key
#
#########################################################################
def dump_index(person_list,file):
for person in person_list:
name = person.getPrimaryName().getName()
id = person.getId()
# file.write('p' + str(id) + ' [shape=box, fontsize=11, ')
file.write('p' + str(id) + ' [shape=box, ')
file.write('fontname="Arial", label="' + name + '"];\n')
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Generates relationship graphs, currently only in GraphVis " \
"format. GraphViz (dot) will transform the graph into "\
"postscript, jpeg, png, vrml, svg, and many other formats. "\
"GraphViz is a research project from former AT&T Research Labs. "\
"For more information or to get a copy of GraphViz, goto "\
"http://www.graphviz.org"

View File

@@ -0,0 +1,549 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Individual web pages"
from RelLib import *
import const
import utils
import os
import re
import sort
import string
import time
from gtk import *
from gnome.ui import *
from libglade import *
titleRe = re.compile(r"<TITLE>")
active_person = None
db = None
topDialog = None
glade_file = None
ind_list = []
restrict = 1
restrict_photos = 0
no_photos = 0
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def individual_filter(database,person,list):
list.append(person)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def ancestor_filter(database,person,list):
if person == None:
return
if person not in list:
list.append(person)
family = person.getMainFamily()
if family != None:
ancestor_filter(database,family.getFather(),list)
ancestor_filter(database,family.getMother(),list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def descendant_filter(database,person,list):
if person == None or person in list:
return
if person not in list:
list.append(person)
for family in person.getFamilyList():
for child in family.getChildList():
descendant_filter(database,child,list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def an_des_filter(database,person,list):
descendant_filter(database,person,list)
ancestor_filter(database,person,list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def entire_db_filter(database,person,list):
for entry in database.getPersonMap().values():
list.append(entry)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def an_des_of_gparents_filter(database,person,list):
my_list = []
family = person.getMainFamily()
if family == None:
return
mother = family.getMother()
father = family.getFather()
if mother:
mfamily = mother.getMainFamily()
if mfamily:
if mfamily.getFather():
my_list.append(mfamily.getFather())
if mfamily.getMother():
my_list.append(mfamily.getMother())
if father:
ffamily = father.getMainFamily()
if ffamily:
if ffamily.getFather():
my_list.append(ffamily.getFather())
if ffamily.getMother():
my_list.append(ffamily.getMother())
for person in my_list:
descendant_filter(database,person,list)
ancestor_filter(database,person,list)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
filter_map = {
"Individual" : individual_filter,
"Ancestors" : ancestor_filter,
"Descendants" : descendant_filter,
"Ancestors and descendants" : an_des_filter,
"Grandparent's ancestors and descendants" : an_des_of_gparents_filter,
"Entire database" : entire_db_filter
}
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def probably_alive(person):
if person == None:
return 1
if restrict == 0:
return 0
death = person.getDeath()
birth = person.getBirth()
if death.getDate() != "":
return 0
if birth.getDate() != "":
year = birth.getDateObj().getYear()
time_struct = time.localtime(time.time())
current_year = time_struct[0]
if year != -1 and current_year - year > 110:
return 0
return 1
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "htmlreport.glade"
dic = {
"destroy_passed_object" : utils.destroy_passed_object,
"on_nophotos_toggled" : on_nophotos_toggled,
"on_ok_clicked" : on_ok_clicked,
}
topDialog = GladeXML(glade_file,"top")
topDialog.signal_autoconnect(dic)
top = topDialog.get_widget("top")
topDialog.get_widget("targetDirectory").set_default_path(os.getcwd())
filterName = topDialog.get_widget("filterName")
popdown_strings = filter_map.keys()
popdown_strings.sort()
filterName.set_popdown_strings(popdown_strings)
name = person.getPrimaryName().getName()
topDialog.get_widget("personName").set_text(name)
top.show()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_nophotos_toggled(obj):
if obj.get_active():
topDialog.get_widget("restrict_photos").set_sensitive(0)
else:
topDialog.get_widget("restrict_photos").set_sensitive(1)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_ok_clicked(obj):
global active_person
global filter_map
global db
global glade_file
global ind_list
global restrict_photos
global restrict
global no_photos
start = re.compile(r"<!-- START -->")
stop = re.compile(r"<!-- STOP -->")
top = []
bottom = []
filterName = topDialog.get_widget("filter").get_text()
directoryName = topDialog.get_widget("targetDirectory").get_full_path(0)
templateName = topDialog.get_widget("htmlTemplate").get_full_path(0)
prefix = topDialog.get_widget("prefix").get_text()
restrict = topDialog.get_widget("restrict").get_active()
restrict_photos = topDialog.get_widget("restrict_photos").get_active()
no_photos = topDialog.get_widget("nophotos").get_active()
if directoryName == None:
directoryName = os.getcwd()
elif not os.path.isdir(directoryName):
parent_dir = os.path.dirname(directoryName)
if not os.path.isdir(parent_dir):
GnomeErrorDialog("Neither " + directoryName + " nor " + \
parent_dir + " are directories")
return
else:
try:
print "trying to make",directoryName
os.mkdir(directoryName)
except IOError, value:
GnomeErrorDialog("Could not create the directory " + directoryName + "\n" + \
value[1])
return
except:
GnomeErrorDialog("Could not create the directory " + directoryName)
return
if templateName == None:
templateName = const.dataDir + os.sep + "family.html"
try:
templateFile = open(templateName,"r")
except IOError, value:
GnomeErrorDialog("Could not open the template file (" + templateName + ")\n" + \
value[1])
return
except:
GnomeErrorDialog("Could not open the template file (" + templateName + ")")
return
top_add = 1
bottom_add = 0
for line in templateFile.readlines():
if top_add == 1:
top.append(line)
match = start.search(line)
if match != None:
top_add = 0
elif bottom_add == 0:
match = stop.search(line)
if match != None:
bottom_add = 1
bottom.append(line)
else:
bottom.append(line)
templateFile.close()
if top_add == 1:
GnomeErrorDialog("The HTML template (" + templateName + ")\n" + \
"did not have a '<!-- START -->' comment at the\n" + \
"beginning of a line. The comment tells GRAMPS where\n" + \
"to insert the data in the template. Please fix the template\n" + \
"and try again.")
return
if bottom_add == 0 :
GnomeErrorDialog("The HTML template (" + templateName + ")\n" + \
"did not have a '<!-- STOP -->' comment at the\n" + \
"beginning of a line. The comment tells GRAMPS where\n" + \
"to resume the template. Please fix the template\n" + \
"and try again.")
return
filter = filter_map[filterName]
ind_list = []
filter(db,active_person,ind_list)
for person in ind_list:
dump_person(person,prefix,top,bottom,directoryName)
if len(ind_list) > 1:
dump_index(ind_list,"index.html",prefix,top,bottom,directoryName)
utils.destroy_passed_object(obj)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def print_event(html,name,event):
if event == None:
return
date = event.getDate()
place = event.getPlace()
if date != "" or place != "":
html.write("<H2>%s</H2>\n" % name)
html.write("<UL>\n")
if date != "":
html.write("<LI>Date : %s</LI>\n" % date)
if place != "":
html.write("<LI>Place : %s</LI>\n" % place)
html.write("</UL>\n")
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def name_or_link(individual, prefix):
name = individual.getPrimaryName().getRegularName()
if individual in ind_list:
id = individual.getId()
return "<A HREF=\"" + prefix + str(id) + ".html\">" + name + "</A>"
else:
return name
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def write_reference(html, parent, prefix):
if parent != None and parent.getPrimaryName() != None:
html.write("<LI>")
html.write(name_or_link(parent,prefix))
html.write("</LI>\n")
#########################################################################
#
# Write a web page for a specific person represented by the key
#
#########################################################################
def dump_person(person,prefix,templateTop,templateBottom,targetDir):
filebase = "%s%d.html" % (prefix,person.getId())
html = open(targetDir + os.sep + filebase,"w")
name = person.getPrimaryName().getRegularName()
alive = probably_alive(person)
for line in templateTop:
html.write(line)
regex_match = titleRe.search(line)
if regex_match != None:
html.write("Family Tree - %s\n" % name )
html.write("<H1>%s</H1>\n" % person.getPrimaryName().getRegularName())
photo_list = person.getPhotoList()
if no_photos or (alive and restrict_photos == 1):
pass
elif len(photo_list) > 0:
import GdkImlib
file = photo_list[0].getPath()
image = GdkImlib.Image(file)
width = int( (float(image.rgb_width) * 200.0) / float(image.rgb_height))
base = os.path.basename(file)
image_name = targetDir + os.sep + base
cmd = const.convert + " -size " + str(width) + "x200 "\
+ file + " " + image_name
os.system(cmd)
html.write('<IMG SRC="' + base + '" ALT="')
html.write(photo_list[0].getDescription())
html.write('" WIDTH="' + str(width) + '" HEIGHT="200">\n')
if not alive:
print_event(html,"Birth",person.getBirth())
print_event(html,"Death",person.getDeath())
family = person.getMainFamily()
if family != None:
html.write("<H2>Parents</H2>\n")
html.write("<UL>\n")
write_reference(html,family.getFather(), prefix)
write_reference(html,family.getMother(), prefix)
html.write("</UL>\n")
for family in person.getFamilyList():
html.write("<H2>Spouse</H2>\n")
html.write("<UL>\n")
if person.getGender() == Person.male:
spouse = family.getMother()
else:
spouse = family.getFather()
if spouse == None:
name = None
spouse_alive = 0
else:
name = spouse.getPrimaryName()
spouse_alive = probably_alive(spouse)
if name == None or name.getRegularName() == "":
html.write("<LI>Spouse's name is not known</LI>\n")
else:
write_reference(html,spouse,prefix)
marriage = family.getMarriage()
if marriage and not alive and not spouse_alive:
place = marriage.getPlace()
date = marriage.getDate()
if place != "" and date != "":
html.write("<LI>Married %s, %s</LI>\n" % (date, place))
elif place == "":
html.write("<LI>Marriage place :%s</LI>\n" % place)
else:
html.write("<LI>Marriage date :%s</LI>\n" % date)
if spouse:
sp_family = spouse.getMainFamily()
if sp_family:
sp_father = sp_family.getFather()
sp_mother = sp_family.getMother()
if sp_father and sp_mother:
html.write("<LI>Spouse's parents: ")
html.write(name_or_link(sp_father,prefix))
html.write(" and ")
html.write(name_or_link(sp_mother,prefix))
html.write("</LI>\n")
elif sp_father:
html.write("<LI>Spouse's father: %s</LI>\n" %
name_or_link(sp_father,prefix))
elif sp_mother:
html.write("<LI>Spouse's mother: %s</LI>\n" %
name_or_link(sp_mother,prefix))
html.write("</UL>\n")
childList = family.getChildList()
if len(childList) > 0:
html.write("<H3>Children</H3>\n")
html.write("<UL>\n")
for child in childList:
write_reference(html,child,prefix)
html.write("</UL>\n")
note = person.getNote()
if note != "":
html.write("<H2>Notes</H2>\n")
noteList = string.split(note,"\n")
for text in noteList:
html.write("<P>" + text + "</P>\n")
for line in templateBottom:
html.write(line)
html.close()
#########################################################################
#
# Write a web page for a specific person represented by the key
#
#########################################################################
def dump_index(person_list,filename,prefix,templateTop,templateBottom,targetDir):
html = open(targetDir + os.sep + filename,"w")
for line in templateTop:
html.write(line)
regex_match = titleRe.search(line)
if regex_match != None:
html.write("Family Tree - Index\n")
html.write("<H1>Family Tree Index</H1>\n")
person_list.sort(sort.by_last_name)
for person in person_list:
name = person.getPrimaryName().getName()
id = person.getId()
html.write("<A HREF=\"%s%d.html\">%s</A><BR>\n" % (prefix,id,name))
for line in templateBottom:
html.write(line)
html.close()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Generates web (HTML) pages for individuals, or a set of " \
"individuals."

View File

@@ -0,0 +1,645 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Generate files/Individual Summary"
import RelLib
import const
import os
import re
import sort
import string
import utils
import OpenOffice
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
active_person = None
db = None
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class IndivSummary:
def __init__(self,database,family,output,template):
pass
def setup(self):
return 1
def end(self):
pass
def write_header(self):
pass
def write_trailer(self):
pass
def write_report(self):
pass
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class OpenOfficeIndivSummary(IndivSummary):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,database,person,output,template):
c = database.getResearcher().getName()
self.open_office = OpenOffice.OpenOfficeCore(output,template,".sxw",c)
self.map = {}
self.database = database
self.person = person
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
self.file = self.open_office.setup()
return 1
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end(self):
self.open_office.end()
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_header(self):
self.file.write('<text:h text:style-name="Heading 1" ')
self.file.write('text:level="1">')
self.file.write('Summary of ')
self.file.write(self.person.getPrimaryName().getRegularName())
self.file.write('</text:h>\n')
if self.image != "":
width = 46.0 * self.scale
self.file.write('<text:p text:style-name="Text body"/>')
self.file.write('<text:p text:style-name="Text body">')
self.file.write('<draw:image draw:style-name="Individual Photo" ')
self.file.write('draw:name="')
self.file.write(self.person.getPrimaryName().getRegularName())
self.file.write('" text:anchor-type=')
self.file.write('"paragraph" svg:y="0mm" svg:height="46mm" ')
val = "%6.2f" % width
self.file.write('svg:width=' + string.strip('"%6.2fmm"' % width))
self.file.write(' draw:z-index="0" xlink:href="#Pictures/')
self.file.write(self.image)
self.file.write('" xlink:type="simple" xlink:show="embed" ')
self.file.write('xlink:actuate="onLoad"/>\n')
self.file.write('</text:p>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_simple_row(self,field1,field2):
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell ")
self.file.write("table:value-type=\"string\">\n")
self.file.write('<text:p text:style-name="Table Contents">')
self.file.write(field1)
self.file.write('</text:p>\n')
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell ")
self.file.write("table:value-type=\"string\">\n")
self.file.write('<text:p text:style-name="Table Contents">')
self.file.write(field2)
self.file.write("</text:p>\n")
self.file.write("</table:table-cell>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_header_row(self,field1):
self.file.write('<table:table-row>\n')
self.file.write('<table:table-cell ')
self.file.write('table:number-columns-spanned="2" ')
self.file.write('table:value-type=\"string\">\n')
self.file.write('<text:p text:style-name="P1">')
self.file.write(field1)
self.file.write('</text:p>\n')
self.file.write("</table:table-cell>\n")
self.file.write("<table:covered-table-cell/>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_spouse(self,person):
if person:
name = person.getPrimaryName().getRegularName()
else:
name = "unknown"
self.file.write('<table:table-row>\n')
self.file.write('<table:table-cell ')
self.file.write('table:number-columns-spanned="2" ')
self.file.write('table:value-type=\"string\">\n')
self.file.write('<text:p text:style-name="P2">')
self.file.write(name)
self.file.write('</text:p>\n')
self.file.write("</table:table-cell>\n")
self.file.write("<table:covered-table-cell/>\n")
self.file.write("</table:table-row>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_general(self):
self.file.write('<table:table table:name="Table1" table:style-name="Table1">\n')
self.file.write('<table:table-column table:style-name="Table1.A"/>\n')
self.file.write('<table:table-column table:style-name="Table1.B"/>\n')
name = self.person.getPrimaryName().getRegularName()
self.write_simple_row("Name:",name)
if self.person.getGender() == RelLib.Person.male:
self.write_simple_row("Gender:","Male")
else:
self.write_simple_row("Gender:","Female")
family = self.person.getMainFamily()
if family:
father = family.getFather().getPrimaryName().getRegularName()
mother = family.getMother().getPrimaryName().getRegularName()
else:
father = ""
mother = ""
self.write_simple_row("Father:",father)
self.write_simple_row("Mother:",mother)
self.file.write('</table:table>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_fact(self,event):
if event == None:
return
name = event.getName()
date = event.getDate()
place = event.getPlace()
description = event.getDescription()
if date == "":
if place == "":
return
else:
self.write_simple_row(name,place + ". " + description)
else:
if place == "":
self.write_simple_row(name,date + ". " + description)
else:
self.write_simple_row(name,date + " in " + place + ". " + \
description)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_facts(self):
self.file.write('<text:p text:style-name="Standard"/>')
self.file.write('<table:table table:name="Table2" table:style-name="Table1">\n')
self.file.write('<table:table-column table:style-name="Table1.A"/>\n')
self.file.write('<table:table-column table:style-name="Table1.B"/>\n')
self.write_header_row("Individual Facts")
event_list = [ self.person.getBirth(), self.person.getDeath() ]
event_list = event_list + self.person.getEventList()
for event in event_list:
self.write_fact(event)
self.file.write('</table:table>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_families(self):
self.file.write('<text:p text:style-name="Standard"/>')
self.file.write('<table:table table:name="Table2" table:style-name="Table1">\n')
self.file.write('<table:table-column table:style-name="Table1.A"/>\n')
self.file.write('<table:table-column table:style-name="Table1.B"/>\n')
self.write_header_row("Marriages/Children")
for family in self.person.getFamilyList():
if self.person == family.getFather():
self.write_spouse(family.getMother())
else:
self.write_spouse(family.getFather())
event_list = [ family.getMarriage(), family.getDivorce() ]
event_list = event_list + family.getEventList()
for event in event_list:
self.write_fact(event)
child_list = family.getChildList()
if len(child_list) > 0:
self.file.write("<table:table-row>\n")
self.file.write("<table:table-cell ")
self.file.write("table:value-type=\"string\">\n")
self.file.write('<text:p text:style-name="Table Contents">')
self.file.write('Children')
self.file.write('</text:p>\n')
self.file.write("</table:table-cell>\n")
self.file.write("<table:table-cell ")
self.file.write("table:value-type=\"string\">\n")
self.file.write('<text:p text:style-name="Table Contents">')
first = 1
for child in family.getChildList():
if first == 1:
first = 0
else:
self.file.write('<text:line-break/>')
self.file.write(child.getPrimaryName().getRegularName())
self.file.write('</text:p>\n')
self.file.write("</table:table-cell>\n")
self.file.write("</table:table-row>\n")
self.file.write('</table:table>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_report(self):
photo_list = self.person.getPhotoList()
if len(photo_list) > 0:
import GdkImlib
file = photo_list[0].getPath()
image = GdkImlib.Image(file)
height = image.rgb_height
scale = float(height)/150.0
width = int(image.rgb_width * scale)
height = int(height * scale)
base = os.path.basename(file)
image_name = self.open_office.add_image(base)
cmd = const.convert + " -size " + str(width) + "x150 "\
+ file + " " + image_name
os.system(cmd)
self.scale = float(height)/float(width)
self.image = base
else:
self.image = ""
self.write_header()
self.write_general()
self.write_facts()
self.write_families()
self.end()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
class HtmlIndivSummary(IndivSummary):
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def __init__(self,database,family,output,template):
self.map = {}
self.database = database
self.family = family
self.output = output
self.first = []
self.last = []
if template == "":
template = const.dataDir + os.sep + "family.html"
self.template = template
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def fix(self,str):
if str=="":
return "&nbsp;"
else:
return str
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def setup(self):
templateFile = open(self.template,"r")
lines = templateFile.readlines()
templateFile.close()
in_last = 0
for line in lines:
if line[0:14] == "<!-- START -->":
in_last = 1
self.last.append(line);
elif in_last == 0:
self.first.append(line)
else:
self.last.append(line);
if in_last == 0:
GnomeErrorDialog("HTML template did not have a START comment")
return 0
self.file = open(self.output,"w")
return 1
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_header(self):
for line in self.first:
self.file.write(line)
self.file.write("<H1>")
self.file.write("Family Group Record")
self.file.write("</H1>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_trailer(self):
for line in self.last:
self.file.write(line)
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent(self,type,name):
self.file.write('<tr>\n')
self.file.write('<td colspan="3" class="parent_name">')
self.file.write(type)
self.file.write(' ')
self.file.write(name.getPrimaryName().getRegularName())
self.file.write('</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def start_parent_stats(self):
self.file.write('<table cellspacing="1" width="100%" border="1">\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end_parent_stats(self):
self.file.write("</table>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent_stats(self,str1,str2,str3):
self.file.write('<tr>\n')
self.file.write('<td width="20%">' + self.fix(str1) + '</td>\n')
self.file.write('<td width="30%">' + self.fix(str2) + '</td>\n')
self.file.write('<td>' + self.fix(str3) + '</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_parent_parent(self,str1,str2):
self.file.write('<tr>\n')
self.file.write('<td>' + self.fix(str1) + '</td>\n')
self.file.write('<td colspan="2" class="child_name">' + self.fix(str2) + '</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def start_child_stats(self):
self.file.write('<table cellspacing="1" width="100%" border="1">\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def end_child_stats(self):
self.file.write("</table>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_stats(self,str1,str2,str3,str4,last):
self.file.write('<tr>\n')
self.file.write('<td width="10%">' + self.fix(str1) + '</td>\n')
self.file.write('<td width="20%">' + self.fix(str2) + '</td>\n')
self.file.write('<td width="30%">' + self.fix(str3) + '</td>\n')
self.file.write('<td>' + self.fix(str4) + '</td>\n')
self.file.write('</tr>\n')
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_name(self,index,child):
self.file.write("<tr>\n")
self.file.write("<td>" + str(index))
if child.getGender() == RelLib.Person.male:
self.file.write("M")
else:
self.file.write("F")
self.file.write("</td>\n")
self.file.write("<td colspan=\"3\">")
self.file.write(child.getPrimaryName().getRegularName())
self.file.write("</td>\n")
self.file.write("</tr>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_child_spouse(self,spouse):
self.file.write("<tr>\n")
self.file.write("<td>&nbsp;</td>\n")
self.file.write("<td>Spouse</td>\n")
self.file.write("<td colspan=\"2\">")
self.file.write(spouse.getPrimaryName().getRegularName())
self.file.write("</td>\n")
self.file.write("</tr>\n")
#--------------------------------------------------------------------
#
#
#
#--------------------------------------------------------------------
def write_report(self):
self.write_header()
self.dump_parent(self.family.getFather())
self.dump_parent(self.family.getMother())
if len(self.family.getChildList()) > 0:
self.file.write("<H2>")
self.file.write("Children")
self.file.write("</H2>\n")
index = 1
for child in self.family.getChildList():
self.dump_child(index,child)
index = index + 1
self.write_trailer()
self.end()
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "indsum.glade"
topDialog = GladeXML(glade_file,"dialog1")
name = person.getPrimaryName().getRegularName()
label = topDialog.get_widget("labelTitle")
label.set_text("Individual Summary for " + name)
topDialog.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
"on_save_clicked" : on_save_clicked,
"on_html_toggled" : on_html_toggled
})
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_html_toggled(obj):
topDialog.get_widget("htmltemplate").set_sensitive(obj.get_active())
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def on_save_clicked(obj):
global active_person
global db
outputName = topDialog.get_widget("filename").get_text()
if outputName == "":
return
if topDialog.get_widget("html").get_active():
template = topDialog.get_widget("htmlfile").get_text()
MyReport = HtmlIndivSummary(db,family,outputName,template)
else:
template = const.dataDir + os.sep + "indsum.sxw"
MyReport = OpenOfficeIndivSummary(db,active_person,outputName,template)
if MyReport.setup() == 0:
return
MyReport.write_report()
utils.destroy_passed_object(obj)
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def get_description():
return "Creates a family group report, showing information on "\
"a set of parents and their children."

View File

@@ -0,0 +1,25 @@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
datadir = @datadir@/@PACKAGE@
INSTALL = @INSTALL@
plugins = ${datadir}/plugins
srcdir = @top_srcdir@
pycomp = ${srcdir}/py-compile
@SET_MAKE@
all:
${pycomp} *.py
install:
-mkdir ${plugins}
${INSTALL} -c *.py *.pyo *.glade ${plugins}
uninstall:
rm ${plugins}/*.py ${plugins}/*.pyo ${plugins}/*.glade ${plugins}/*.xpm
-rmdir ${plugins}
clean:
-rm -f core *.pyo *.pyc *.bak *~

935
gramps/src/plugins/Merge.py Normal file
View File

@@ -0,0 +1,935 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Database Processing/Merge people"
import RelLib
import utils
import soundex
import Check
import string
import os
from gtk import *
from gnome.ui import *
from libglade import *
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def is_initial(name):
if len(name) > 2:
return 0
elif len(name) == 2:
if name[0] in string.uppercase and name[1] == '.':
return 1
else:
return name[0] in string.uppercase
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ancestors_of(p1,list):
if p1 == None:
return
list.append(p1)
f1 = p1.getMainFamily()
if f1 != None:
ancestors_of(f1.getFather(),list)
ancestors_of(f1.getMother(),list)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_name(p1):
if p1 == None:
return None
else:
return p1.getPrimaryName()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_merge_ok_clicked(obj):
myobj = obj.get_data("t")
active = myobj.menu.get_menu().get_active().get_data("v")
myobj.use_soundex = myobj.soundex_obj.get_active()
utils.destroy_passed_object(obj)
myobj.find_potentials(active)
myobj.show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
class Merge:
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def __init__(self,database,callback):
self.db = database
self.map = {}
self.list = []
self.index = 0
self.merger = None
self.mergee = None
self.removed = {}
self.update = callback
self.use_soundex = 1
self.family_list = database.getFamilyMap().values()[:]
self.person_list = database.getPersonMap().values()[:]
base = os.path.dirname(__file__)
self.glade_file = base + os.sep + "merge.glade"
top = GladeXML(self.glade_file,"dialog")
topWin = top.get_widget("dialog")
topWin.set_data("t",self)
my_menu = GtkMenu()
item = GtkMenuItem("Low")
item.set_data("v",0.25)
item.show()
my_menu.append(item)
item = GtkMenuItem("Medium")
item.set_data("v",1.0)
item.show()
my_menu.append(item)
item = GtkMenuItem("High")
item.set_data("v",2.0)
item.show()
my_menu.append(item)
self.soundex_obj = top.get_widget("soundex")
self.menu = top.get_widget("menu")
self.menu.set_menu(my_menu)
top.signal_autoconnect({
"on_merge_ok_clicked" : on_merge_ok_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def progress_update(self,val):
self.progress.set_value(val)
while events_pending():
mainiteration()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def find_potentials(self,thresh):
top = GladeXML(self.glade_file,"message")
self.topWin = top.get_widget("message")
self.progress = top.get_widget("progressbar1")
self.topWin.show()
index = 0
males = {}
females = {}
for p1 in self.person_list:
key = self.gen_key(p1.getPrimaryName().getSurname())
if p1.getGender() == RelLib.Person.male:
if males.has_key(key):
males[key].append(p1)
else:
males[key] = [p1]
else:
if females.has_key(key):
females[key].append(p1)
else:
females[key] = [p1]
length = len(self.person_list)
num = 0
for p1 in self.person_list:
if num % 25 == 0:
self.progress_update((float(num)/float(length))*100)
num = num + 1
key = self.gen_key(p1.getPrimaryName().getSurname())
if p1.getGender() == RelLib.Person.male:
remaining = males[key]
else:
remaining = females[key]
index = 0
for p2 in remaining:
index = index + 1
if p1 == p2:
continue
chance = self.compare_people(p1,p2)
if chance >= thresh:
if self.map.has_key(p1):
val = self.map[p1]
if val[1] > chance:
self.map[p1] = (p2,chance)
else:
self.map[p1] = (p2,chance)
self.list = self.map.keys()[:]
self.list.sort(by_id)
self.length = len(self.list)
self.topWin.destroy()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def show(self):
self.topDialog = GladeXML(self.glade_file,"merge")
self.merge_btn = self.topDialog.get_widget("merge_btn")
self.next_btn = self.topDialog.get_widget("next_btn")
self.altname = self.topDialog.get_widget("altname")
self.topDialog.signal_autoconnect({
"on_next_clicked" : on_next_clicked,
"on_merge_clicked" : on_merge_clicked,
"destroy_passed_object" : update_and_destroy
})
if len(self.map) > 0:
top = self.topDialog.get_widget("merge")
top.set_data("MergeObject",self)
top.show()
top.set_data("t",self)
self.load_next()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def merge(self):
self.merge_btn.set_sensitive(0)
utils.modified()
if self.topDialog.get_widget("bname2").get_active():
if self.altname.get_active():
self.mergee.addAlternateName(self.mergee.getPrimaryName())
self.mergee.setPrimaryName(self.merger.getPrimaryName())
else:
if self.altname.get_active():
self.mergee.addAlternateName(self.merger.getPrimaryName())
if self.topDialog.get_widget("bbirth2").get_active():
self.mergee.getBirth().setDate(self.merger.getBirth().getDate())
if self.topDialog.get_widget("bplace2").get_active():
self.mergee.getBirth().setPlace(self.merger.getBirth().getPlace())
if self.topDialog.get_widget("death2").get_active():
self.mergee.getDeath().setDate(self.merger.getDeath().getDate())
if self.topDialog.get_widget("dplace2").get_active():
self.mergee.getDeath().setPlace(self.merger.getDeath().getPlace())
if self.topDialog.get_widget("bfather2").get_active():
orig_family = self.mergee.getMainFamily()
if orig_family:
orig_family.removeChild(self.mergee)
source_family = self.merger.getMainFamily()
self.mergee.setMainFamily(source_family)
if source_family:
if self.merger in source_family.getChildList():
source_family.removeChild(self.merger)
if self.mergee not in source_family.getChildList():
source_family.addChild(self.mergee)
else:
source_family = self.merger.getMainFamily()
if source_family:
source_family.removeChild(self.merger)
self.merger.setMainFamily(None)
self.merge_families()
for event in self.merger.getEventList():
self.mergee.addEvent(event)
for photo in self.merger.getPhotoList():
self.mergee.addPhoto(photo)
for name in self.merger.getAlternateNames():
self.mergee.addAlternateName(name)
if self.mergee.getNickName() == "":
self.mergee.setNickName(self.merger.getNickName())
if self.merger.getNote() != "":
old_note = self.mergee.getNote()
if old_note:
old_note = old_note + "\n\n"
self.mergee.setNote(old_note + self.merger.getNote())
del self.db.getPersonMap()[self.merger.getId()]
self.removed[self.merger] = self.mergee
self.removed[self.mergee] = self.mergee
checker = Check.CheckIntegrity(self.db)
checker.cleanup_empty_families(1)
checker.check_for_broken_family_links()
self.load_next()
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def find_family(self,family):
if self.mergee.getGender() == RelLib.Person.male:
mother = family.getMother()
father = self.mergee
else:
father = family.getFather()
mother = self.mergee
for myfamily in self.family_list:
if myfamily.getFather() == father and \
myfamily.getMother() == mother:
return myfamily
return None
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def merge_families(self):
family_num = 0
mylist = self.merger.getFamilyList()[:]
for src_family in mylist:
family_num = family_num + 1
if not self.db.getFamilyMap().has_key(src_family.getId()):
continue
if src_family in self.mergee.getFamilyList():
continue
tgt_family = self.find_family(src_family)
#
# This is the case where a new family to be added to the
# mergee 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 mergee) from
# both the parents
#
if tgt_family in self.mergee.getFamilyList():
if tgt_family.getFather() != None and \
src_family in tgt_family.getFather().getFamilyList():
tgt_family.getFather().removeFamily(src_family)
if tgt_family.getMother() != None and \
src_family in tgt_family.getMother().getFamilyList():
tgt_family.getMother().removeFamily(src_family)
# copy children from source to target
# delete the old source family
del self.db.getFamilyMap()[src_family.getId()]
continue
#
# This is the case where a new family to be added
# and it is not already in the list.
#
if tgt_family:
# tgt_family a duplicate family, transfer children from
# the merger 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
for child in src_family.getChildList():
if child not in tgt_family.getChildList():
tgt_family.addChild(child)
if child.getMainFamily() == src_family:
child.setMainFamily(tgt_family)
else:
index = 0
for fam in child.getAltFamilies():
if fam == src_family:
child.getAltFamilies()[index] = tgt_family
index = index + 1
# add family events from the old to the new
for event in src_family.getEventList():
tgt_family.addEvent(event)
# add mariage information
marriage = src_family.getMarriage()
if marriage:
other_marriage = tgt_family.getMarriage()
if other_marriage != None:
if other_marriage.getPlace() == "":
other_marriage.setPlace(marriage.getPlace())
if other_marriage.getDate() == "":
other_marriage.setDate(marriage.getDate())
else:
tgt_family.setMarriage(marriage)
# add divorce information
divorce = src_family.getDivorce()
if divorce != None:
other_divorce = tgt_family.getDivorce()
if other_divorce != None:
if other_divorce.getPlace() == "":
other_divorce.setPlace(divorce.getPlace())
if other_divorce.getDate() == "":
other_divorce.setDate(divorce.getDate())
else:
tgt_family.setDivorce(divorce)
# change parents of the family to point to the new
# family
if src_family.getFather():
src_family.getFather().removeFamily(src_family)
src_family.getFather().addFamily(tgt_family)
if src_family.getMother():
src_family.getMother().removeFamily(src_family)
src_family.getMother().addFamily(tgt_family)
del self.db.getFamilyMap()[src_family.getId()]
else:
self.remove_marriage(src_family,self.merger)
if src_family not in self.mergee.getFamilyList():
self.mergee.addFamily(src_family)
if self.mergee.getGender() == RelLib.Person.male:
src_family.setFather(self.mergee)
else:
src_family.setMother(self.mergee)
# a little debugging here
for fam in self.db.getFamilyMap().values():
name = self.merger.getPrimaryName().getName()
if self.merger in fam.getChildList():
fam.removeChild(self.merger)
fam.addChild(self.mergee)
if self.merger == fam.getFather():
fam.setFather(self.mergee)
if self.merger == fam.getMother():
fam.setMother(self.mergee)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def remove_marriage(self,family,person):
if not person:
return
index = 0
for fam in person.getFamilyList():
if fam == family:
del person.getFamilyList()[index]
return
index = index + 1
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def load_next(self):
if self.length == 0:
return
done = 0
while not done:
person1 = self.list[self.index]
self.index = self.index + 1
if self.index > len(self.list):
return
if self.removed.has_key(person1):
continue
(person2,val) = self.map[person1]
if self.removed.has_key(person2):
continue
done = 1
label_text = "Merge %d of %d" % (self.index,self.length)
self.topDialog.get_widget("progress").set_text(label_text)
f1 = person1.getMainFamily()
f2 = person2.getMainFamily()
name1 = person1.getPrimaryName().getName()
death1 = person1.getDeath().getDate()
dplace1 = person1.getDeath().getPlace()
birth1 = person1.getBirth().getDate()
bplace1 = person1.getBirth().getPlace()
name2 = person2.getPrimaryName().getName()
death2 = person2.getDeath().getDate()
dplace2 = person2.getDeath().getPlace()
birth2 = person2.getBirth().getDate()
bplace2 = person2.getBirth().getPlace()
if f2 and not f1:
self.topDialog.get_widget("bfather2").set_active(1)
else:
self.topDialog.get_widget("bfather1").set_active(1)
if f1 and f1.getFather():
father1 = f1.getFather().getPrimaryName().getName()
else:
father1 = ""
if f1 and f1.getMother():
mother1 = f1.getMother().getPrimaryName().getName()
else:
mother1 = ""
if f2 and f2.getFather():
father2 = f2.getFather().getPrimaryName().getName()
else:
father2 = ""
if f2 and f2.getMother():
mother2 = f2.getMother().getPrimaryName().getName()
else:
mother2 = ""
label1 = "First Person (" + str(person1.getId()) + ")"
label2 = "Second Person (" + str(person2.getId()) + ")"
self.topDialog.get_widget("PersonFrame1").set_label(label1)
self.topDialog.get_widget("PersonFrame2").set_label(label2)
self.topDialog.get_widget("name1_text").set_text(name1)
self.topDialog.get_widget("name1_text").set_position(0)
self.topDialog.get_widget("name2_text").set_text(name2)
self.topDialog.get_widget("name2_text").set_position(0)
self.topDialog.get_widget("bname1").set_active(1)
self.topDialog.get_widget("birth1_text").set_text(birth1)
self.topDialog.get_widget("birth1_text").set_position(0)
self.topDialog.get_widget("birth2_text").set_text(birth2)
self.topDialog.get_widget("birth2_text").set_position(0)
if birth2 and not birth1:
self.topDialog.get_widget("bbirth2").set_active(1)
else:
self.topDialog.get_widget("bbirth1").set_active(1)
self.topDialog.get_widget("bplace1_text").set_text(bplace1)
self.topDialog.get_widget("bplace1_text").set_position(0)
self.topDialog.get_widget("bplace2_text").set_text(bplace2)
self.topDialog.get_widget("bplace2_text").set_position(0)
if bplace2 and not bplace1:
self.topDialog.get_widget("bplace2").set_active(1)
else:
self.topDialog.get_widget("bplace1").set_active(1)
self.topDialog.get_widget("death1_text").set_text(death1)
self.topDialog.get_widget("death1_text").set_position(0)
self.topDialog.get_widget("death2_text").set_text(death2)
self.topDialog.get_widget("death2_text").set_position(0)
if death2 and not death1:
self.topDialog.get_widget("death2").set_active(1)
else:
self.topDialog.get_widget("death1").set_active(1)
self.topDialog.get_widget("dplace1_text").set_text(dplace1)
self.topDialog.get_widget("dplace1_text").set_position(0)
self.topDialog.get_widget("dplace2_text").set_text(dplace2)
self.topDialog.get_widget("dplace2_text").set_position(0)
if dplace2 and not dplace1:
self.topDialog.get_widget("dplace2").set_active(1)
else:
self.topDialog.get_widget("dplace1").set_active(1)
self.topDialog.get_widget("father1").set_text(father1)
self.topDialog.get_widget("father1").set_position(0)
self.topDialog.get_widget("father2").set_text(father2)
self.topDialog.get_widget("father2").set_position(0)
self.topDialog.get_widget("mother1").set_text(mother1)
self.topDialog.get_widget("mother1").set_position(0)
self.topDialog.get_widget("mother2").set_text(mother2)
self.topDialog.get_widget("mother2").set_position(0)
p1list = person1.getFamilyList()
p2list = person2.getFamilyList()
length = min(len(p1list),3)
self.topDialog.get_widget("spouse1").clear()
for index in range(0,3):
if index < length and p1list[index]:
if person1.getGender() == RelLib.Person.male:
spouse = p1list[index].getMother()
x = p1list[index].getFather()
else:
spouse = p1list[index].getFather()
x = p1list[index].getMother()
if spouse == None:
name = "unknown"
else:
name = spouse.getPrimaryName().getName() + \
" (" + str(spouse.getId()) + ")"
self.topDialog.get_widget("spouse1").append([name])
length = min(len(p2list),3)
self.topDialog.get_widget("spouse2").clear()
for index in range(0,3):
if index < length and p2list[index]:
if person2.getGender() == RelLib.Person.male:
spouse = p2list[index].getMother()
x = p2list[index].getFather()
else:
spouse = p2list[index].getFather()
x = p2list[index].getMother()
if spouse == None:
name = "unknown"
else:
name = spouse.getPrimaryName().getName() + \
" (" + str(spouse.getId()) + ")"
self.topDialog.get_widget("spouse2").append([name])
self.mergee = person1
self.merger = person2
self.topDialog.get_widget("chance").set_text(str(val))
if len(self.list) > self.index+1:
self.merge_btn.set_sensitive(1)
self.next_btn.set_sensitive(1)
else:
self.merge_btn.set_sensitive(0)
self.next_btn.set_sensitive(0)
if name1 != name2:
self.altname.set_sensitive(1)
self.altname.set_active(1)
else:
self.altname.set_sensitive(0)
self.altname.set_active(0)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def list_reduce(self,list1,list2):
value = 0
for name in list1:
for name2 in list2:
if is_initial(name) and name[0] == name2[0]:
value = value + 0.25
break
if is_initial(name2) and name2[0] == name[0]:
value = value + 0.25
break
if name == name2:
value = value + 0.5
break
if name[0] == name2[0] and self.name_compare(name,name2):
value = value + 0.25
break
if value == 0:
return -1
else:
return min(value,1)
#-----------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------
def gen_key(self,val):
if self.use_soundex:
return soundex.soundex(val)
else:
return val
#-----------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------
def name_compare(self,s1,s2):
if self.use_soundex:
return soundex.compare(s1,s2)
else:
return s1 == s2
#-----------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------
def date_match(self,date1,date2):
if date1.getDate() == "" or date2.getDate() == "":
return 0
if date1.getDate() == date2.getDate():
return 1
if date1.getYear() == date2.getYear():
if date1.getMonth() == date2.getMonth():
return 0.75
if date1.getMonth() == -1 or date2.getMonth() == -1:
return 0.75
else:
return -1
else:
return -1
#-----------------------------------------------------------------
#
#
#
#-----------------------------------------------------------------
def name_match(self,name,name1):
if not name1 or not name:
return 0
srn1 = name.getSurname()
sfx1 = name.getSuffix()
srn2 = name1.getSurname()
sfx2 = name1.getSuffix()
if not self.name_compare(srn1,srn2):
return -1
if sfx1 != sfx2:
if sfx1 != "" and sfx2 != "":
return -1
if name.getFirstName() == name1.getFirstName():
return 1
else:
list1 = string.split(name.getFirstName())
list2 = string.split(name1.getFirstName())
if len(list1) < len(list2):
return self.list_reduce(list1,list2)
else:
return self.list_reduce(list2,list1)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def place_match(self,name1,name2):
if name1 == "" or name2 == "":
return 0
if name1 == name2:
return 1
list1 = string.split(string.replace(name1,","," "))
list2 = string.split(string.replace(name2,","," "))
value = 0
for name in list1:
for name2 in list2:
if name == name2:
value = value + 0.5
break
if name[0] == name2[0] and self.name_compare(name,name2):
value = value + 0.25
break
if value == 0:
return -1
else:
return min(value,1)
#---------------------------------------------------------------------
#
#
#
#---------------------------------------------------------------------
def compare_people(self,p1,p2):
name1 = p1.getPrimaryName()
name2 = p2.getPrimaryName()
chance = self.name_match(name1,name2)
if chance == -1 :
return -1
birth1 = p1.getBirth()
death1 = p1.getDeath()
birth2 = p2.getBirth()
death2 = p2.getDeath()
value = self.date_match(birth1.getDateObj(),birth2.getDateObj())
if value == -1 :
return -1
chance = chance + value
value = self.date_match(death1.getDateObj(),death2.getDateObj())
if value == -1 :
return -1
chance = chance + value
value = self.place_match(birth1.getPlace(),birth2.getPlace())
if value == -1 :
return -1
chance = chance + value
value = self.place_match(death1.getPlace(),death2.getPlace())
if value == -1 :
return -1
chance = chance + value
ancestors = []
ancestors_of(p1,ancestors)
if p2 in ancestors:
return -1
ancestors = []
ancestors_of(p2,ancestors)
if p1 in ancestors:
return -1
f1 = p1.getMainFamily()
f2 = p2.getMainFamily()
if f1 and f2:
dad1 = get_name(f1.getFather())
dad2 = get_name(f2.getFather())
value = self.name_match(dad1,dad2)
if value == -1:
return -1
chance = chance + value
mom1 = get_name(f1.getMother())
mom2 = get_name(f2.getMother())
value = self.name_match(mom1,mom2)
if value == -1:
return -1
chance = chance + value
for f1 in p1.getFamilyList():
for f2 in p2.getFamilyList():
if p1.getGender() == RelLib.Person.female:
father1 = f1.getFather()
father2 = f2.getFather()
if father1 and father2:
if father1 == father2:
chance = chance + 1
else:
fname1 = get_name(father1)
fname2 = get_name(father2)
value = self.name_match(fname1,fname2)
if value != -1:
chance = chance + value
else:
mother1 = f1.getMother()
mother2 = f2.getMother()
if mother1 and mother2:
if mother1 == mother2:
chance = chance + 1
else:
mname1 = get_name(mother1)
mname2 = get_name(mother2)
value = self.name_match(mname1,mname2)
if value != -1:
chance = chance + value
return chance
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def runTool(database,active_person,callback):
mergeObj = Merge(database,callback)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Searches the entire database, looking for individual "\
"entries that may represent the same person"
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def update_and_destroy(obj):
obj.get_data("t").update(1)
utils.destroy_passed_object(obj)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_next_clicked(obj):
myObject = obj.get_data("MergeObject")
myObject.load_next()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_merge_clicked(obj):
myObject = obj.get_data("MergeObject")
myObject.merge()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def by_id(p1,p2):
return cmp(p1.getId(),p2.getId())

View File

@@ -0,0 +1,96 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Database Processing/Extract information from names"
import os
import re
from gnome.ui import *
import RelLib
import utils
#-------------------------------------------------------------------------
#
# Search each name in the database, and compare the firstname against the
# form of "Name (Nickname)". If it matches, change the first name entry
# to "Name" and add "Nickname" into the nickname field.
#
#-------------------------------------------------------------------------
def runTool(database,active_person,callback):
title_re = re.compile(r"^([A-Za-z][A-Za-z]+\.)\s+(.*)$")
nick_re = re.compile(r"(.+)[(\"](.*)[)\"]")
title_count = 0
nick_count = 0
personMap = database.getPersonMap()
for key in personMap.keys():
person = personMap[key]
name = person.getPrimaryName()
first = name.getFirstName()
match = title_re.match(first)
if match:
groups = match.groups()
name.setFirstName(groups[1])
name.setTitle(groups[0])
title_count = title_count + 1
match = nick_re.match(first)
if match:
groups = match.groups()
name.setFirstName(groups[0])
person.setNickName(groups[1])
nick_count = nick_count + 1
if nick_count == 1:
msg = "1 nickname was extracted\n"
else:
msg = "%d nicknames were extracted\n" % nick_count
if title_count == 1:
msg = msg + "1 title was extracted"
else:
msg = msg + "%d titles were extracted" % title_count
if nick_count > 0 or title_count > 0:
utils.modified()
box = GnomeOkDialog(msg)
box.show()
callback(1)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Searches the entire database and attempts to extract titles "\
"and nicknames that may be embedded in a person's given name field."

View File

@@ -0,0 +1,670 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Import from GEDCOM"
from RelLib import *
import latin_ansel
import latin_utf8
import os
import re
import string
import const
import utils
import shutil
from gtk import *
from gnome.ui import *
from libglade import *
topDialog = None
db = None
callback = None
glade_file = None
clear_data = 0
InvalidGedcom = "Invalid GEDCOM file"
ged2rel = {}
for val in const.personalConstantEvents.keys():
key = const.personalConstantEvents[val]
if key != "":
ged2rel[key] = val
ged2fam = {}
for val in const.familyConstantEvents.keys():
key = const.familyConstantEvents[val]
if key != "":
ged2fam[key] = val
def find_file(fullname,altpath):
if os.path.isfile(fullname):
return fullname
other = altpath + os.sep + os.path.basename(fullname)
if os.path.isfile(other):
return other
else:
return ""
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def importData(database, filename):
global callback
global topDialog
global glade_file
global statusWindow
headRegexp = re.compile(r"\s*0\s+HEAD")
charRegexp = re.compile(r"\s*1\s+CHAR\s+(\S+)\s*$")
sourceRegexp = re.compile(r"\s*1\s+SOUR\s+(\S?[\s\S]*\S)\s*$")
srcrefRegexp = re.compile(r"\s*2\s+SOUR\s+@(.+)@")
indiRegexp = re.compile(r"\s*0\s+@(.+)@\s+INDI")
familyRegexp = re.compile(r"\s*0\s+@(.+)@\s+FAM")
srcRegexp = re.compile(r"\s*0\s+@(.+)@\s+SOUR")
topRegexp = re.compile(r"\s*0\s+")
changeRegexp = re.compile(r"\s*1\s+CHAN")
geventRegexp = re.compile(r"\s*1\s+EVEN")
numRegexp = re.compile(r"\s*[2-9]\s")
eventRegexp = re.compile(r"\s*1\s+([\S]+)\s*(.*)?$")
titleRegexp = re.compile(r"\s*1\s+TITL\s*(.*)?$")
objeRegexp = re.compile(r"\s*1\s+OBJE")
title2Regexp = re.compile(r"\s*2\s+TITL\s*(.*)?$")
fileRegexp = re.compile(r"\s*2\s+FILE\s*(.*)?$")
uidRegexp = re.compile(r"\s*1\s+_UID\s*(.*)?$")
authorRegexp = re.compile(r"\s*1\s+AUTH\s*(.*)?$")
pubRegexp = re.compile(r"\s*1\s+PUBL\s*(.*)?$")
callnoRegexp = re.compile(r"\s*1\s+CALN\s*(.*)?$")
prefixRegexp = re.compile(r"\s*2\s+NPFX\s*(.*)?$")
suffixRegexp = re.compile(r"\s*2\s+NSFX\s*(.*)?$")
birthRegexp = re.compile(r"\s*1\s+BIRT\s*(.*)?$")
noterefRegexp= re.compile(r"\s*1\s+NOTE\s+@(.+)@")
noteactRegexp= re.compile(r"\s*1\s+NOTE\s+(.+)*")
refnRegexp = re.compile(r"\s*1\s+REFN")
noteRegexp = re.compile(r"\s*0\s+@(.+)@\s+NOTE\s*(.*)?$")
concRegexp = re.compile(r"\s*1\s+CONC\s(.*)?$")
contRegexp = re.compile(r"\s*1\s+CONT\s(.*)?$")
deathRegexp = re.compile(r"\s*1\s+DEAT\s*(.*)?$")
divorceRegexp= re.compile(r"\s*1\s+DIV\s*(.*)?$")
marriedRegexp= re.compile(r"\s*1\s+MAR\s*(.*)?$")
genderRegexp = re.compile(r"\s*1\s+SEX\s+(\S)?")
typeRegexp = re.compile(r"\s*2\s+TYPE\s*(.*)?$")
placeRegexp = re.compile(r"\s*2\s+PLAC\s*(.*)?$")
pageRegexp = re.compile(r"\s*3\s+PAGE\s*(.*)?$")
dateRegexp = re.compile(r"\s*2\s+DATE\s*(.*)?$")
nameRegexp = re.compile(r"\s*1\s+NAME\s+([\S\s]*\S)?\s*/([^/]+)?/\s*,?\s*([\S]+)?")
famsRegexp = re.compile(r"\s*1\s+FAMS\s+@(.*)@")
famcRegexp = re.compile(r"\s*1\s+FAMC\s+@(.*)@")
fatherRegexp = re.compile(r"\s*1\s+HUSB\s+@(.*)@")
motherRegexp = re.compile(r"\s*1\s+WIFE\s+@(.*)@")
childRegexp = re.compile(r"\s*1\s+CHIL\s+@(.*)@")
noteId = ""
inlineNote = 0
inlocalNote = 0
user2note = {}
person2note = {}
personActive = 0
familyActive = 0
sourceActive = 0
noteActive = 0
allLines = []
values = {}
index = 0
currentLine = 0
fmap = {}
pmap = {}
smap = {}
familyTree = 0
in_change = 0
photo = None
ansel = 0
# add some checking here
gedcom = open(filename,"r")
if clear_data == 1:
database.new()
statusTop = GladeXML(glade_file,"status")
statusWindow = statusTop.get_widget("status")
progressWindow = statusTop.get_widget("progress")
allLines = gedcom.readlines()
gedcom.close()
# use search here instead of match, since PAF5 seems to like to
# insert garbage as the first couple of characters in the file
regex_match = headRegexp.search(allLines[0])
if regex_match == None:
raise InvalidGedcom
total = len(allLines)
value = 0
for index in range(1,21):
value = value + total/20
values[index] = value
index = 1
value = values[1]
for line in allLines:
line = string.replace(line, '\r', "")
if ansel == 1:
line = latin_ansel.ansel_to_latin(line)
if currentLine == value and index <= 20:
index = index + 1
if index <= 20:
value = values[index]
progressWindow.set_percentage(float(currentLine)/float(total))
while events_pending():
mainiteration()
currentLine = currentLine + 1
regex_match = charRegexp.match(line)
if regex_match:
id = regex_match.groups()
if id[0] == "ANSEL":
ansel = 1
continue
regex_match = changeRegexp.match(line)
if regex_match:
in_change = 1
continue
if in_change:
if numRegexp.match(line):
in_change = 0
continue
regex_match = indiRegexp.match(line)
if regex_match:
id = regex_match.groups()
person = database.findPerson(id[0],pmap)
personActive = 1
familyActive = 0
sourceActive = 0
noteActive = 0
continue
regex_match = familyRegexp.match(line)
if regex_match:
id = regex_match.groups()
family = database.findFamily(id[0],fmap)
personActive = 0
familyActive = 1
sourceActive = 0
noteActive = 0
continue
regex_match = srcRegexp.match(line)
if regex_match:
id = regex_match.groups()
source = database.findSource(id[0],smap)
personActive = 0
familyActive = 0
sourceActive = 1
noteActive = 0
continue
regex_match = noteRegexp.match(line)
if regex_match:
matches = regex_match.groups()
noteId = matches[0]
noteActive = 1
sourceActive = 0
familyActive = 0
personActive = 0
if matches[1] == None:
user2note[noteId] = ""
else:
user2note[noteId] = matches[1]
continue
regex_match = sourceRegexp.match(line)
if regex_match:
matches = regex_match.groups()
if matches[0] == "FTW":
familyTree = 1
continue
regex_match = topRegexp.match(line)
if regex_match:
personActive = 0
familyActive = 0
noteActive = 0
continue
if familyActive == 1:
regex_match = srcrefRegexp.match(line)
if regex_match:
matches = regex_match.groups()
source = database.findSource(matches[0],smap)
mySource = Source()
mySource.setBase(source)
event.setSource(mySource)
continue
regex_match = pageRegexp.match(line)
if regex_match:
matches = regex_match.groups()
mySource.setPage(matches[0])
continue
regex_match = fatherRegexp.match(line)
if regex_match:
matches = regex_match.groups()
father = database.findPerson(matches[0],pmap)
family.setFather(father)
continue
regex_match = motherRegexp.match(line)
if regex_match:
matches = regex_match.groups()
mother = database.findPerson(matches[0],pmap)
family.setMother(mother)
continue
regex_match = childRegexp.match(line)
if regex_match :
matches = regex_match.groups()
child = database.findPerson(matches[0],pmap)
family.addChild(child)
continue
regex_match = marriedRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
event.setName("Marriage")
family.setMarriage(event)
continue
regex_match = divorceRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
event.setName("Divorce")
family.setDivorce(event)
continue
regex_match = placeRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event.setPlace(matches[0])
continue
regex_match = geventRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
family.addEvent(event)
continue
regex_match = dateRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event.setDate(matches[0])
continue
regex_match = typeRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event.setName(matches[0])
continue
elif personActive == 1:
regex_match = nameRegexp.match(line)
if regex_match :
matches = regex_match.groups()
name = Name()
if matches[0] :
name.setFirstName(matches[0])
if matches[1] :
name.setSurname(matches[1])
if matches[2] :
name.setSuffix(matches[2])
person.setPrimaryName(name)
continue
regex_match = titleRegexp.match(line)
if regex_match:
continue
regex_match = prefixRegexp.match(line)
if regex_match:
matches = regex_match.groups()
name.setTitle(matches[0])
continue
regex_match = uidRegexp.match(line)
if regex_match:
matches = regex_match.groups()
person.setPafUid(matches[0])
continue
regex_match = suffixRegexp.match(line)
if regex_match:
matches = regex_match.groups()
name.setSuffix(matches[0])
continue
if inlocalNote == 1:
regex_match = concRegexp.match(line)
if regex_match :
matches = regex_match.groups()
user2note[noteId] = user2note[noteId] + matches[0]
continue
regex_match = contRegexp.match(line)
if regex_match :
matches = regex_match.groups()
user2note[noteId] = user2note[noteId] + "\n" + matches[0]
continue
inlocalNote = 0
person.setNote(user2note[noteId])
regex_match = noteactRegexp.match(line)
if regex_match :
inlocalNote = 1
matches = regex_match.groups()
noteId = "local%d" % inlineNote
inlineNote = inlineNote + 1
if matches[0] == None:
user2note[noteId] = ""
else:
user2note[noteId] = matches[0]
continue
regex_match = srcrefRegexp.match(line)
if regex_match:
matches = regex_match.groups()
source = database.findSource(matches[0],smap)
mySource = Source()
mySource.setBase(source)
event.setSource(mySource)
continue
regex_match = pageRegexp.match(line)
if regex_match:
matches = regex_match.groups()
mySource.setPage(matches[0])
continue
regex_match = noterefRegexp.match(line)
if regex_match :
matches = regex_match.groups()
person2note[person] = matches[0]
continue
regex_match = genderRegexp.match(line)
if regex_match :
matches = regex_match.groups()
if matches[0] == "M":
person.setGender(Person.male)
else:
person.setGender(Person.female)
continue
regex_match = famcRegexp.match(line)
if regex_match :
matches = regex_match.groups()
new_family = database.findFamily(matches[0],fmap)
person.setMainFamily(new_family)
continue
regex_match = famsRegexp.match(line)
if regex_match :
matches = regex_match.groups()
new_family = database.findFamily(matches[0],fmap)
person.addFamily(new_family)
continue
regex_match = birthRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
# check to see if the person already had a birthdate set.
# if he/she does, then add the birthdate as an alternate.
# this assumes that the first birthdate in the GEDCOM file
# is the one that should be considered the primary
lbirth = person.getBirth()
if lbirth.getDate() != "" or lbirth.getPlace() != "":
person.addEvent(event)
event.setName("Alternate Birth")
else:
person.setBirth(event)
continue
regex_match = deathRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
# check to see if the person already had a birthdate set.
# if he/she does, then add the birthdate as an alternate.
# this assumes that the first birthdate in the GEDCOM file
# is the one that should be considered the primary
ldeath = person.getDeath()
if ldeath.getDate() != "" or ldeath.getPlace() != "":
person.addEvent(event)
event.setName("Alternate Death")
else:
person.setDeath(event)
continue
regex_match = refnRegexp.match(line)
if regex_match :
continue
regex_match = geventRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
person.addEvent(event)
continue
regex_match = eventRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event = Event()
if ged2rel.has_key(matches[0]):
type = ged2rel[matches[0]]
elif ged2fam.has_key(matches[0]):
type = ged2fam[matches[0]]
else:
type = matches[0]
event.setName(type)
if matches[1] :
event.setDescription(matches[1])
person.addEvent(event)
continue
regex_match = typeRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event.setName(matches[0])
continue
regex_match = placeRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event.setPlace(matches[0])
continue
regex_match = dateRegexp.match(line)
if regex_match :
matches = regex_match.groups()
event.setDate(matches[0])
continue
regex_match = fileRegexp.match(line)
if regex_match :
matches = regex_match.groups()
imagepath = find_file(matches[0],os.path.dirname(filename))
savepath = database.getSavePath()
if imagepath != "" and savepath != "":
id = person.getId()
for index in range(0,100):
base = "i%s_%d.jpg" % (id,index)
name = savepath + os.sep + base
if os.path.exists(name) == 0:
break
shutil.copy(imagepath,name)
photo = Photo()
continue
regex_match = title2Regexp.match(line)
if regex_match and photo != None:
matches = regex_match.groups()
photo.setDescripton(matches[0])
continue
if objeRegexp.match(line):
photo = None
continue
elif noteActive == 1:
regex_match = concRegexp.match(line)
if regex_match :
matches = regex_match.groups()
user2note[noteId] = user2note[noteId] + matches[0]
continue
regex_match = contRegexp.match(line)
if regex_match :
matches = regex_match.groups()
user2note[noteId] = user2note[noteId] + "\n" + matches[0]
continue
elif sourceActive == 1:
regex_match = titleRegexp.match(line)
if regex_match:
matches = regex_match.groups()
source.setTitle(matches[0])
continue
regex_match = authorRegexp.match(line)
if regex_match:
matches = regex_match.groups()
source.setAuthor(matches[0])
continue
regex_match = pubRegexp.match(line)
if regex_match:
matches = regex_match.groups()
source.setPubInfo(matches[0])
continue
regex_match = callnoRegexp.match(line)
if regex_match:
matches = regex_match.groups()
source.setCallNumber(matches[0])
continue
for person in person2note.keys():
name = person.getPrimaryName()
noteId = person2note[person]
person.setNote(user2note[noteId])
statusWindow.destroy()
callback(1)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
global db
global topDialog
global clear_data
name = topDialog.get_widget("filename").get_text()
if name == "":
return
if topDialog.get_widget("new").get_active():
clear_data = 1
else:
clear_data = 0
utils.destroy_passed_object(obj)
try:
importData(db,name)
except InvalidGedcom:
GnomeErrorDialog(name + " is not a valid GEDCOM file")
statusWindow.destroy()
except IOError, val:
GnomeErrorDialog("Could not load " + name + "\n" + val[1])
statusWindow.destroy()
# except:
# GnomeErrorDialog("Could not load " + name + \
# "\n due to an unexpected internal error")
# statusWindow.destroy()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def readData(database,active_person,cb):
global db
global topDialog
global callback
global glade_file
db = database
callback = cb
base = os.path.dirname(__file__)
glade_file = base + os.sep + "gedcomimport.glade"
dic = {
"destroy_passed_object" : utils.destroy_passed_object,
"on_ok_clicked" : on_ok_clicked
}
topDialog = GladeXML(glade_file,"gedcomImport")
topDialog.signal_autoconnect(dic)
topDialog.get_widget("gedcomImport").show()

View File

@@ -0,0 +1,81 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Import from Gramps"
import libglade
from ReadXML import *
import utils
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def progress(val):
pass
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def readData(database,active_person,cb):
global db
global topDialog
global callback
global glade_file
db = database
callback = cb
base = os.path.dirname(__file__)
glade_file = base + os.sep + "grampsimport.glade"
dic = {
"destroy_passed_object" : utils.destroy_passed_object,
"on_ok_clicked" : on_ok_clicked
}
topDialog = libglade.GladeXML(glade_file,"grampsImport")
topDialog.signal_autoconnect(dic)
topDialog.get_widget("grampsImport").show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_ok_clicked(obj):
global db
global topDialog
import const
if topDialog.get_widget("new").get_active():
db.new()
name = topDialog.get_widget("filename").get_text()
name = name + os.sep + const.indexFile
utils.destroy_passed_object(obj)
importData(db,name,progress)
callback(1)

View File

@@ -0,0 +1,262 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"Utilities/Relationship calculator"
import os
from gtk import *
from gnome.ui import *
from libglade import *
import RelLib
import sort
topDialog = None
other_person = None
col2person = []
#-------------------------------------------------------------------------
#
#
#-------------------------------------------------------------------------
def filter(person,index,list,map):
if person == None:
return
list.append(person)
map[person] = index
family = person.getMainFamily()
if family != None:
filter(family.getFather(),index+1,list,map)
filter(family.getMother(),index+1,list,map)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_peopleList_select_row(obj,a,b,c):
global other_person
other_person = col2person[a]
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_apply_clicked(obj):
firstMap = {}
firstList = []
secondMap = {}
secondList = []
common = []
rank = 9999999
filter(active_person,0,firstList,firstMap)
filter(other_person,0,secondList,secondMap)
for person in firstList:
if person in secondList:
new_rank = firstMap[person]
if new_rank < rank:
rank = new_rank
common = [ person ]
elif new_rank == rank:
common.append(person)
firstRel = -1
secondRel = -1
firstName = active_person.getPrimaryName().getRegularName()
secondName = other_person.getPrimaryName().getRegularName()
length = len(common)
if length == 1:
person = common[0]
secondRel = firstMap[person]
firstRel = secondMap[person]
commontext = " Their common ancestor is "
commontext = commontext + person.getPrimaryName().getRegularName() + "."
elif length > 1:
index = 0
commontext = " Their common ancestors are "
for person in common:
secondRel = firstMap[person]
firstRel = secondMap[person]
if length == index + 1:
commontext = commontext + " and "
elif index != 0:
commontext = commontext + ", "
commontext = commontext + person.getPrimaryName().getRegularName()
index = index + 1
else:
commontext = ""
if firstRel == -1:
text = "There is no relationship between " + firstName + " and " + secondName + "."
elif firstRel == 0:
if other_person.getGender() == RelLib.Person.male:
root = "father"
else:
root = "mother"
if secondRel == 0:
text = firstName + " and " + secondName + " are the same person."
else:
text = secondName + get_prefix(secondRel,root) + firstName
elif secondRel == 0:
if other_person.getGender() == RelLib.Person.male:
text = secondName + get_prefix(firstRel,"son") + firstName + "."
else:
text = secondName + get_prefix(firstRel,"daughter") + firstName + "."
elif firstRel == 1:
if other_person.getGender() == RelLib.Person.male:
root = "uncle"
else:
root = "aunt"
if secondRel == 1:
if other_person.getGender() == RelLib.Person.male:
text = secondName + " is the brother of " + firstName + "."
else:
text = secondName + " is the sister of " + firstName + "."
else:
text = secondName + get_prefix(secondRel-1,root) + firstName + "."
elif secondRel == 1:
if other_person.getGender() == RelLib.Person.male:
text = secondName + get_prefix(firstRel-1,"nephew") + firstName + "."
else:
text = secondName + get_prefix(firstRel-1,"niece") + firstName + "."
else:
if secondRel > firstRel:
text = secondName + cousin(secondRel-1,secondRel-firstRel) + firstName + "."
else:
text = secondName + cousin(firstRel-1,firstRel-secondRel) + firstName + "."
text1 = topDialog.get_widget("text1")
text1.set_point(0)
length = text1.get_length()
text1.forward_delete(length)
if firstRel == 0 or secondRel == 0:
text1.insert_defaults(text)
else:
text1.insert_defaults(text + commontext)
text1.set_word_wrap(1)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def cousin(level,removed):
if level == 1:
root = " is the 1st cousin"
elif level == 2:
root = " is the 2nd cousin"
elif level == 3:
root = " is the 3rd cousin"
else:
root = " is the %dth cousin" % level
if removed == 0:
root = root + " of "
elif removed == 1:
root = root + " once removed of "
elif removed == 2:
root = root + " twice removed of "
else:
root = root + " %d times removed of " % removed
return root
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_prefix(level,root):
if level == 1:
return " is the " + root + " of "
elif level == 2:
return " is the grand" + root + " of "
elif level == 3:
return " is the great grand" + root + " of "
elif level == 4:
return " is the 2nd great grand" + root + " of "
elif level == 5:
return " is the 3rd great grand" + root + " of "
else:
return " is the %dth great grand%s of " % (level - 2,root)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def on_close_clicked(obj):
obj.destroy()
while events_pending():
mainiteration()
#-------------------------------------------------------------------------
#
#
#-------------------------------------------------------------------------
def runTool(database,person,callback):
global active_person
global topDialog
global glade_file
global db
active_person = person
db = database
base = os.path.dirname(__file__)
glade_file = base + os.sep + "relcalc.glade"
topDialog = GladeXML(glade_file,"relcalc")
name = person.getPrimaryName().getRegularName()
topDialog.get_widget("name").set_text("Relationship to " + name)
peopleList = topDialog.get_widget("peopleList")
name_list = database.getPersonMap().values()
name_list.sort(sort.by_last_name)
for per in name_list:
col2person.append(per)
name = per.getPrimaryName().getName()
birthday = per.getBirth().getDate()
peopleList.append([name,birthday])
topDialog.signal_autoconnect({
"on_close_clicked" : on_close_clicked,
"on_peopleList_select_row" : on_peopleList_select_row,
"on_apply_clicked" : on_apply_clicked
})
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Calculates the relationship between two people"

View File

@@ -0,0 +1,117 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"View/Summary of the database"
from RelLib import *
import os
import posixpath
import re
import sort
import string
import utils
from gtk import *
from gnome.ui import *
from libglade import *
#------------------------------------------------------------------------
#
#
#
#------------------------------------------------------------------------
def report(database,person):
base = os.path.dirname(__file__)
glade_file = base + os.sep + "summary.glade"
topDialog = GladeXML(glade_file,"summary")
topDialog.signal_autoconnect({
"destroy_passed_object" : utils.destroy_passed_object,
})
personList = database.getPersonMap().values()
familyList = database.getFamilyMap().values()
with_photos = 0
total_photos = 0
incomp_names = 0
disconnected = 0
missing_bday = 0
males = 0
females = 0
people = 0
bytes = 0
namelist = []
for person in personList:
length = len(person.getPhotoList())
if length > 0:
with_photos = with_photos + 1
total_photos = total_photos + length
for file in person.getPhotoList():
bytes = bytes + posixpath.getsize(file.getPath())
name = person.getPrimaryName()
if name.getFirstName() == "" or name.getSurname() == "":
incomp_names = incomp_names + 1
if person.getMainFamily() == None and len(person.getFamilyList()) == 0:
disconnected = disconnected + 1
if person.getBirth().getDate() == "":
missing_bday = missing_bday + 1
if person.getGender() == Person.female:
females = females + 1
else:
males = males + 1
if name.getSurname() not in namelist:
namelist.append(name.getSurname())
text = "Individuals\n"
text = text + "----------------------------\n"
text = text + "Number of individuals : %d\n" % len(personList)
text = text + "Males : %d\n" % males
text = text + "Females : %d\n" % females
text = text + "Individuals with incomplete names : %d\n" % incomp_names
text = text + "Individuals missing birth dates : %d\n" % missing_bday
text = text + "Disconnected individuals : %d\n" % disconnected
text = text + "\nPhotos and files\n"
text = text + "----------------------------\n"
text = text + "Individuals with photos : %d\n" % with_photos
text = text + "Total number of photos : %d\n" % total_photos
text = text + "Total size of photos : %d bytes\n" % bytes
text = text + "\nFamily Information\n"
text = text + "----------------------------\n"
text = text + "Number of families : %d\n" % len(familyList)
text = text + "Unique surnames : %d\n" % len(namelist)
top = topDialog.get_widget("summary")
textwindow = topDialog.get_widget("textwindow")
textwindow.show_string(text)
top.show()
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_description():
return "Provides a summary of the current database"

Some files were not shown because too many files have changed in this diff Show More