diff --git a/gramps2/.cvsignore b/gramps2/.cvsignore new file mode 100644 index 000000000..c365ab55d --- /dev/null +++ b/gramps2/.cvsignore @@ -0,0 +1,5 @@ +Makefile +config.cache +config.log +config.status +gramps.sh diff --git a/gramps2/AUTHORS b/gramps2/AUTHORS new file mode 100644 index 000000000..461241508 --- /dev/null +++ b/gramps2/AUTHORS @@ -0,0 +1,5 @@ +Donald N. Allingham ** Concept and main design + +David Hampton ** Autocomp.py and Report.py + +Donald A. Peterson ** Makefiles, LaTeXDoc.py diff --git a/gramps2/COPYING b/gramps2/COPYING new file mode 100644 index 000000000..a43ea2126 --- /dev/null +++ b/gramps2/COPYING @@ -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. + + + Copyright (C) 19yy + + 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. + + , 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. diff --git a/gramps2/ChangeLog b/gramps2/ChangeLog new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/gramps2/ChangeLog @@ -0,0 +1 @@ + diff --git a/gramps2/INSTALL b/gramps2/INSTALL new file mode 100644 index 000000000..5b2bdffdd --- /dev/null +++ b/gramps2/INSTALL @@ -0,0 +1,79 @@ +For rebuilding from source, here are some guidelines to follow. For +developers who may be adding functionality to the program, be sure to read +the last section of this documen: "FINAL WORDS". + +SUPER-SHORT VERSION: +You should be able to just run "./configure && make". But if you make any +significant changes or experience any problems, you may wish to run +"./autogen.sh && make" to regenerate everything. + +This will call aclocal if necessary, then automake, which creates +Makefile.in from Makefile.am rules. Then it calls autoconf, which will +generate configure from configure.in and the Makefile.{am,in} sources. +Finally, autogen calls configure to generate the final files necessary for +building gramps. + +SHORT VERSION: +Execute: +aclocal +automake --add-missing --gnu && autoconf && make + +HTML documentation is built from SGML sources via jw. It is known to work +with docbook-utils-0.6.9. There is a problem with 0.6.10, which seems to +have some messed up dsl files. If you have difficulty building the HTML +documentation with your version of jw, then remove "doc" from the SUBDIRS +list in the top-level Makefile and send a report of where the failure was to +the gramps-devel list. This distribution is tested with the style sheets +and PNG support from the gnome-doc-tools-2-1 package. + +MORE INFO: Version and package info is now set in configure.in through a +call to the AM_INIT_AUTOMAKE macro. The results are stored in variables +PACKAGE and VERSION, which then get substituted wherever necessary. +(gramps.sh, gramps.spec, src/const.py, asst. Makefiles, etc.) We also +manually set the RELEASE variable for setting things like "pre" or minor +bugfix issues. * Note: Using @VERSION@ in the manuals has the advantage that +the current manual always states that it describes current version of +gramps. The disadvantage is that this becomes misleading if the manual +isn't regularly updated. Keep in mind this is GRAMPS version and not +*manual* version. Another problem is that the standard GNOME SGML +documentation make rules (sgmldocs.make) have their own rule, but automake +generates its own rule and this introduces a conflict. + +"make (un)install" now runs scrollkeeper-update to ensure +documentation database is up to date. Scrollkeeper v. > 0.1.4 should in +principle work, v. > 0.2 should see no problems. + +VERBOSE, UGLY DETAILS FOR DEVELOPERS: +Using automake/autoconf adds many, MANY build targets to the makefiles. +Basically, we only care about the main and "install" targets. However, +there are some others that bear further notice: + +* make dist -- will create a lovely gramps-{VERSION}.tar.gz archive with +everything needed to distribute, including the HTML documentation just in +case Joe User doen't know about or have a compatable jw/db2html. After +running "make dist" you can create the rpms using +"rpm -ta gramps-{VERSION}.tar.gz". How nice is that? + +* make clean -- only gets rid of byte-compiled stuff like .so files. + +* make distclean -- improves on clean by eliminating configuration (*.in, +config.*, Makefiles, and converted documentation.) stuff. This is generally +what you (as a developer) will want for testing "fresh" compiles. + +* make trans -- We add this one on our own for building the template.po file. + +Another caveat of the automake mantra is that new/overriding make +targets/rules/defines should generally go in the Makefile.am files rather +than Makefile.in. + +* Note: Another beauty of the automake mechanism (and having automake macros +in the configure script) is that once the scripts have been made, a change +to any .am file will trigger "make" to regenerate the Makefile.in/configure +scripts as appropriate. It is _very_ convenient. + +FINAL WORDS: automake "thinks" of a distribution in terms of "SOURCES", such +as raw C code, "COMPILED OBJECTS" like executables and libraries, and +"DATA", such as images, scripts, and documentation. Thus, for gramps we +concentrate on DATA-type objects. We must tell automake what objects are +important. We do this by adding to the EXTRA_DIST variable in the various +Makefile.am files before running automake. diff --git a/gramps2/Makefile.am b/gramps2/Makefile.am new file mode 100644 index 000000000..d11ae66d1 --- /dev/null +++ b/gramps2/Makefile.am @@ -0,0 +1,30 @@ +# copyright (C) 2000 Sun Microsystems, Inc. + +SUBDIRS = src doc omf-install + +EXTRA_DIST = autogen.sh gramps.spec.in + +bin_SCRIPTS = gramps + +grampsdocdir = $(datadir)/doc/gramps-$(VERSION) +scrollkeeper_localstate_dir = $(localstatedir)/lib/scrollkeeper + +gramps: gramps.sh + cp gramps.sh gramps + +dist-hook: gramps.spec + cp gramps.spec $(distdir) + +# Build/rebuild the catalog +install-data-hook: + rm -rf $(DESTDIR)$(scrollkeeper_localstate_dir) + $(mkinstalldirs) $(DESTDIR)$(scrollkeeper_localstate_dir) + $(mkinstalldirs) $(DESTDIR)$(localstatedir)/log + scrollkeeper-rebuilddb -p $(DESTDIR)$(scrollkeeper_localstate_dir) + +# Remove generated files +uninstall-local: + -rm -rf $(DESTDIR)$(gramps_localstate_dir) + -rm -f $(DESTDIR)$(localstatedir)/log/gramps.log + -rm -f $(DESTDIR)$(localstatedir)/log/gramps.log.1 + diff --git a/gramps2/Makefile.comm b/gramps2/Makefile.comm new file mode 100644 index 000000000..b750e4c17 --- /dev/null +++ b/gramps2/Makefile.comm @@ -0,0 +1,18 @@ +# Generated automatically from Makefile.comm.in by configure. +# Hold variable definitions needed by slave Makefiles +prefix = /usr/local +exec_prefix = ${prefix} +bindir = ${exec_prefix}/bin +datadir = ${prefix}/share/gramps +INSTALL = /usr/bin/install -c +sharedir = ${prefix}/share/gramps +GNOMEHELP = ${prefix}/share/gnome/help +GM = gramps-manual +EG = extending-gramps +DB2HTML = + + + +# Ensure the correct "/bin/sh" for interpreting commands +# in case the user has some other shell environment +SHELL = /bin/sh diff --git a/gramps2/Makefile.in b/gramps2/Makefile.in new file mode 100644 index 000000000..17c084b13 --- /dev/null +++ b/gramps2/Makefile.in @@ -0,0 +1,490 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# copyright (C) 2000 Sun Microsystems, Inc. +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ + +SUBDIRS = src doc omf-install + +EXTRA_DIST = autogen.sh gramps.spec.in + +bin_SCRIPTS = gramps + +grampsdocdir = $(datadir)/doc/gramps-$(VERSION) +scrollkeeper_localstate_dir = $(localstatedir)/lib/scrollkeeper +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = gramps.spec gramps.sh +SCRIPTS = $(bin_SCRIPTS) + +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ + Makefile.in NEWS TODO aclocal.m4 configure configure.in \ + gramps.sh.in gramps.spec.in install-sh missing mkinstalldirs \ + py-compile +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: + +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe) + +$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +gramps.spec: $(top_builddir)/config.status gramps.spec.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +gramps.sh: $(top_builddir)/config.status gramps.sh.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +binSCRIPT_INSTALL = $(INSTALL_SCRIPT) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_SCRIPTS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f $$d$$p; then \ + f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ + echo " $(binSCRIPT_INSTALL) $$d$$p $(DESTDIR)$(bindir)/$$f"; \ + $(binSCRIPT_INSTALL) $$d$$p $(DESTDIR)$(bindir)/$$f; \ + else :; fi; \ + done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ + echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ + rm -f $(DESTDIR)$(bindir)/$$f; \ + done +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = . +distdir = $(PACKAGE)-$(VERSION) + +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } + +GZIP_ENV = --best +distcleancheck_listfiles = find . -type f -print + +distdir: $(DISTFILES) + $(am__remove_distdir) + mkdir $(distdir) + $(mkinstalldirs) $(distdir)/. $(distdir)/src + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="${top_distdir}" distdir="$(distdir)" \ + dist-hook + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist dist-all: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + $(am__remove_distdir) + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/=inst && pwd` \ + && cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + find $$dc_install_base -type f -print ; \ + exit 1; } >&2 ) \ + && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \ + && rm -f $(distdir).tar.gz \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @echo "$(distdir).tar.gz is ready for distribution" | \ + sed 'h;s/./=/g;p;x;p;x' +distcleancheck: distclean + if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(SCRIPTS) +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(bindir) + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook + +install-exec-am: install-binSCRIPTS + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf autom4te.cache +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-binSCRIPTS uninstall-info-am uninstall-local + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive dist dist-all dist-gzip distcheck \ + distclean distclean-generic distclean-recursive distclean-tags \ + distcleancheck distdir dvi dvi-am dvi-recursive info info-am \ + info-recursive install install-am install-binSCRIPTS \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive tags tags-recursive uninstall \ + uninstall-am uninstall-binSCRIPTS uninstall-info-am \ + uninstall-info-recursive uninstall-local uninstall-recursive + + +gramps: gramps.sh + cp gramps.sh gramps + +dist-hook: gramps.spec + cp gramps.spec $(distdir) + +# Build/rebuild the catalog +install-data-hook: + rm -rf $(DESTDIR)$(scrollkeeper_localstate_dir) + $(mkinstalldirs) $(DESTDIR)$(scrollkeeper_localstate_dir) + $(mkinstalldirs) $(DESTDIR)$(localstatedir)/log + scrollkeeper-rebuilddb -p $(DESTDIR)$(scrollkeeper_localstate_dir) + +# Remove generated files +uninstall-local: + -rm -rf $(DESTDIR)$(gramps_localstate_dir) + -rm -f $(DESTDIR)$(localstatedir)/log/gramps.log + -rm -f $(DESTDIR)$(localstatedir)/log/gramps.log.1 +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/NEWS b/gramps2/NEWS new file mode 100644 index 000000000..b4976c73f --- /dev/null +++ b/gramps2/NEWS @@ -0,0 +1,362 @@ +Version 0.7.3 +* New Russian (Alex Roitman) and Danish (Lars Lundin) translations. + GRAMPS now supports English, Italian, German, French, Spanish, + Brazilian-Portuguese, Swedish, Danish, and Russian. +* Custom filter editor allows you to create your personal complex + filters that can be applied to reports to select the people that + you want. Tools->Utilites->Custom Filter Editor to access the + filter builder. (Thanks to Jeff Ollie for some major contributions + here). +* New report - Complete Individual Report. Allows you to produce a + more complete form of the Individual Summary. You can use filters + to select all ancestors, all decendants, or any custom filter you + want to create more of a 'book' form of a report. +* On-the-fly document generation instead of pre-built HTML files + (Thanks to Don Peterson) +* Web page generation now generates a two column list, along with + labels. +* GEDCOM impovements, including the ability to use GRAMPS as a GEDCOM + viewer (accepts a GEDCOM file as an argument). + + +Version 0.7.2 +* New Brazilian-Portuguese translation (Marcos Bedinelli) +* Python Imaging Library no longer required for several report + formats. +* Better sizing of images in reports (Bruce DeGrasse) +* An image subdirectory name can now be specified in the WebPage + generation. This allows you to specify the subdirectory (or + absence of a subdirectory) where images are placed when generating + a web site. +* Merging allows you to choose the GRAMPS ID of the merged person. +* Better handling of auto completion of names, places, and other + items. +* Ability to rerun Startup dialog when necessary +* More information in the Startup dialog +* Fewer intermediate files when handling images for reports +* Reports are now plugins, stored in the DocGen library +* Filter out control characters on GEDCOM import +* New document format generators for SVG and PostScript. +* Improved document format generators for LaTeX (Donald Peterson), + KWord (Bruce DeGrasse), and AbiWord. +* Names now have a type (e.g. "Married Name", "Birth Name") + associated with them. +* Eliminated the intermediate dialog box on importing - GRAMPS + now always appends to the current database. +* If an imported GEDCOM contains REFN tags, they are correlated + to the GRAMPS ID if possible. + + +Version 0.7.1 +* A database must now be open at all times. Prevents the problem of + not having a place to put files. +* Several drop down menus for names have been replaced with + autocompletion text boxes. +* Autosave - allows the database to be saved to a backup file + periodically. +* New Descendant Graph dialog. +* Reorganization of reports. +* New preferences dialog. +* Configurable guessing of last names for new children. +* Slightly improved incomplete date handling. +* More sort columns and improved sorting in the lists. +* New tooltips (Don Peterson) +* Improved navigation in the Pedigree View (Shane Hathaway) +* Italian translation (Marco Molteni) + +Version 0.7.0 +* LD_PRELOAD set to handle Mandrake 8.1 shared library problems. +* Drag and drop copying of events, address, attributes, and URLs. +* Improved GEDCOM. GRAMPS now understands many more of the "quirks" + of the GEDCOM produced by other programs. In addition, GRAMPS can + now tailor its GEDCOM output several other programs. An XML data + file is used to describe to GRAMPS the types of quirks each + format uses. +* Support for French Republican, Hebrew, and Julian calendars. +* LDS ordinance support. +* Cleaned up report dialog code. +* Bug fixes in GEDCOM reading and relationship calculator. +* Toolbar may display Icons and Text, Text only, or Icons only. This + helps in some of the translations, where the long text forced the + toolbar to be unusually large. +* Dragging and dropping media objects can optionally display property + dialogs. +* All toolbar icons have tooltips. +* Keyboard shortcuts for bookmark saving. +* Find dialog supports autocompletion, and has the more standard shortcut + of C-F. +* Change in XML database format to provides better support for dates. +* Added entries to the Help menu to jump to the GRAMPS home page and the + GRAMPS mailing list page. + +Version 0.6.2 +* Fixed SuSE 7.3/lib-imlib problem. +* Improved GEDCOM import/export. Gramps now passes the GEDCHK program + and can now properly handle the quirks in names, notes, and parent/child + relationships from PAF, Legacy, FTW, Brother's Keeper, and Family Origins. +* After an Add Spouse, make the new spouse display in the Family View + interface. + +Version 0.6.1 +* Fixed Family View/Pedigree View button swap +* Updated Spanish translation + +Version 0.6.0 +* Support for QUAY, NCHI, and CAUS on GEDCOM import. GEDCOM + import is significantly faster. +* Support for multiple sources per item. +* Support for revision control. RCS based revision control is + available. +* Confidence level moved to SourceReference instead of object. +* All fields of birth and death events are editable. Clicking the + Edit button brings up the event editor. Birth and death fields + on the Edit Person dialog are now read only. +* Support for unknown gender. +* Central image/media repository added. All images in a gallery + are references to these media objects. Media objects can have + global properties (in the repository) or local properties (in + each gallery). +* Media types are beyond images are now supported (PDF, MP3, + word processor documents, etc.) +* Drag and drop of images from one gallery to another. Drag and + drop from file managers into the gallery. Drag and drop from a + web page to a gallery. +* Drag and drop reordering of children in children lists. +* Drag and drop reordering of images in a gallery. +* Autocompletion support on most entry boxes with drop down menus. +* Plugins can be reloaded without re-starting gramps. +* Two people can be selected and directly merged from the main + person list. +* Two places can be selected and directly merged from the main + place list. +* The "Find and Merge" functionality has been improved to make it + easier to find matches. +* Web page generation is significantly faster. +* Many plugins enhanced. Descendant browser can jump to an Edit Person + display, Event Comparison can now save and load complex filters, + etc. +* User had significant more control over the format of the internal + GRAMPS' ids. You can now set a prefix for each type (such as "I-" + for individuals) or specify more powerful formatting using C-like + format statements (such as "I-%04d"). +* Adoption relationships are visible on the pedigree view (seen as + a dotted line). +* Reordering GRAMPS' ids attempts to preserve the integer originally + assigned to the object. +* The person view can be sorted by GRAMPS id. +* KWord format generated is now compatible with KWord 1.1. Images may + now be included in KWord documents (requires Python Imaging Library). + Tables are not working yet. I can figure out how to format a KWord + table. + +Version 0.5.1 +* Bug fixes +* Allow gramps' ids to be edited +* Added Jesper Zedlitz's PAF for Palm export +* Progress report on GEDCOM import +* Add a new person from the parent selection dialog +* Improved configure script for FreeBSD +* Documenation improvements +* Slight performance improvements reading large databases + +Version 0.5.0 +* New pedegree form which can display 3, 4, or 5 generations + depending on the screen size. Supports better navigation. +* Added a Find function to quickly find people. +* Implemented Place objects, allowing additional information + to be stored about a place. +* New icons for Person View and Family View. +* Online documentation. +* Pressing enter on qualifier field for a filter will apply + the filter. +* New verification tool added to look for odd things in the + database. +* Improvements in GEDCOM import, including handling some + Family Tree Maker pecularities. +* Spanish translation is now available. This brings the languages + to English, Spanish, Swedish, German, and French. + +Version 0.4.1 +* Tool/Report menus added to top level menu bar +* Extract Titles and Nicknames plugin improved to provide more + information +* Several bug fixes, including the problem of swapping father/ + mother relationships in families +* Significant improvements in speed for updating displays after + adding, editing, or deleting people, and for applying filters. +* Added Bruce DeGrasse's Detailed Ancestral Report. This will + eventually replace the current Ancestral Report. + +Version 0.4.0 +* Redesigned Family page. More complex family relationships can be + handled. +* ISO date format supported +* Places are stored in a pulldown menu +* gramps ID can be displayed in many lists +* Multiple selection in Add Children box +* Internal gramps ID now a string instead of an integer +* Double clicking on a name in the Pedegree view brings up the edit + box for that person +* Support for same sex parent families has been added +* Complete rework of Edit Person dialog +* Added privacy flag and confidence level to events, attributes, etc. +* Automatically detect gzip'ed XML vs. XML +* Added option to write either gzip'ed XML or straight XML +* Warn on closing the edit person and marriage/relationshp window + when modifications have been made. +* French translation +* New plugin from Jesper Zedlitz that implements a graphical + representation of the people in the database, allowing you to + reposition people according to your own desires. +* XML is indented properly +* XML DTD available + +Version 0.3.2 +* Fixed Style Editor on WebPage.py, to allow styles to be edited. +* WebPage generator now lists more information, including sources. +* May have ironed out the PyXML/Python/SAX issues once and for all, + cleaning up the python 1.5/2.X problems. +* Added the ability to set default directories for reports and + databases. +* Fixed major bug that added a marriage and divorce to every record + that was viewed in the family viewer. +* Fixed bug that was dropping images +* Many, many other bug fixes. +* Improved many of the translations. + +Version 0.3.1 +* Improved Web Site generation (changed from Individual Web Pages) +* Faster load times for XML database +* Fixed unicode problems with Python 2.0 +* Improved GEDCOM exporter +* Use the GRAMPSDIR environment variable in the shell script to determine + the root path instead of dynamically doing it by attempting to look + at __file__ in const.py +* Added better GEDCOM importing for files generated by Brother's + Keeper and Reunion. + +Version 0.3.0 +* Support for RTF (export to MSWord) and limited support for KWord + and LaTeX added. +* User defined styles for reports. Allows the selection of fonts, + sizes, colors, alignment, and many other features in output + reports. Styles can be saved for future use. +* Improved report formats +* Initial German translation. Please note that the German translation + is new, and it will take a while before it is fully in sync with the + program. It will probably take a release or two before it is as + stable as the Swedish translation (it can take a while to provide the + translations, and the code is changing, so it takes a while to flush + things out). +* Output format preference and page size preference can be set in the + preferences menu. +* Names can now have sources and notes. +* Lots of bug fixes +* Fixes to GEDCOM importer + +Version 0.2.0 +* New GEDCOM importer. This new importer understands the GEDCOM + file structure, and intelligently parses the file. More + information is extracted from the GEDCOM file. Guessing the + context of information is no longer done, so the data should go + into the right place. The display dialog now displays useful and + interesting information as the file is loaded. The importer + has been checked with file generated Personal Ancestral File, + Brother's Keeper, DISGEN, the GEDCOM Torture test, and even the + sometimes strange output of Family Tree Maker. +* Better support for sources. Source button on the main page, and + sources are entered from the main screen, instead of being about + five layers deep. +* Events, sources, attributes, and addresses can now have both + sources and notes. +* Limited configurability in status bar display. Instead of just a + name, you can have a name, the internal ID and a name, or a user + selectable attribute and a name. +* A user selectable attribute can be displayed on the Edit Person + display along with the gramps internal ID. The attribute is + specified in the preferences settings, and the value is taken + from the person's attribute list. +* Images now load faster. Thumbnail images are created and maintained + by gramps, eliminating the need to rescale images everytime a + gallery is displayed. +* Paper size preference can now be specified in the preferences + dialog. Once this is set, gramps will make this the default for + report generators. Eventually, you will be able to do the same + for output format preference. This button is current disabled. +* Generating slightly better XML. Maintaining compatibility with + the older files. + + +Version 0.1.5 + +* Plenty of bug fixes in the report generators and merging due to the + previous addition of date ranges. +* Added PDF file type generation for reports. Depends on the reportlab + package (available at www.reportlab.com). If the package is not + installed, gramps will run, but without PDF generation ability. +* Will use the Python Imaging Library if present to handle images. If + not, it will revert to the old method of using Imagick (convert). +* The user can select an attribute (from the attribute list) to display + on the Edit Person window. +* The internal gramps ID is now displayed on the Edit Person window. +* Marriage types can now be recorded. +* Addresses now use a single date instead of multiple dates, since + dates can now deal with ranges. +* Due to a bug in Python 2.0/GTK interaction, list colors are disabled + for Python 2.0 and above. +* configure script now properly deals with Python include paths, + eliminating the need to hand edit the src/Makefile to get gramps to + run under Python 2.X. +* Photos are now displayed properly again in the Edit Person gallery. +* Family notes are now implemented. + +Version 0.1.4 + +* Implemented date ranges. Valid forms are "from to " and + "between and ". +* 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. +* Added into CVS on sourceforge +* Fixed quite a few bugs + +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. \ No newline at end of file diff --git a/gramps2/README b/gramps2/README new file mode 100644 index 000000000..183651e75 --- /dev/null +++ b/gramps2/README @@ -0,0 +1,65 @@ +Please read the COPYING file first. +If building from source, also read the INSTALL file (at least through the +"SUPER-SHORT VERSION") before going further. + +Requirements +-------------------------------- +Python 1.5.2 or greater +Gnome 1.2 or greater +PyGnome 1.0.53 or greater + +If you are using python 1.5.2, you may also need PyXML 0.6.2 or +greater. Many distributions already provide this, but if your +installation does not have it, you can get it from +http://sourceforge.net/project/showfiles.php?group_id=6473 + +Documentation +--------------------------------- +Gramps documentation is supplied in the form of SGML files, which will be +installed in the GNOME help path(*). Recent versions of Nautilus and Galeon +can generate HTML on-the-fly documents from these. For more information on +building HTML files (including info about packages that do and do not work +with the documentation) see the INSTALL file. To generate HTML +documentation the following packages *MUST* installed: +* db2html >= 0.6.9 (jw >= 1.1) to convert the SGML -> HTML +* gnome-doc-tools-2-1 for the GNOME documentation style sheets +The former is part of the docbook-utils package, the latter can be found +from the developer section at gnome.org. (note that docbook-utils 0.6.10 is +buggy) + +One also needs png support for sgml, which should be a part of the +gnome-doc-tools package. The /etc/sgml/catalog file should +contain an entry pointing to PNG support. If configured properly, your +db2html should automatically look up and use the /etc/sgml/catalog file. + +Of course, current HTML documentation can also be found on the gramps website, +http://gramps.sourceforge.net/help.html + +(*) More precisely, they are installed in ${prefix}/share/gnome/help, where +${prefix} is given by the --prefix= option to configure. If this is +different from where your standard GNOME installation looks for help files +and documentation, then set your GNOMEDIR environment variable to the +${prefix} path before starting gramps. For example, if you are installing +gramps in /usr/local/, then type the following: +in tcsh: setenv GNOMEDIR /usr/local/ +in bash: GNOMEDIR=/usr/local/ ; export GNOMEDIR + + +Building on non-Linux systems: i18n support and GNU make +-------------------------------------------------------- + +Linux has libintl (GNU gettext) built-in the C library. Other systems +are likely to have libintl as a separate or optional library. Also, +other systems may have a different make utility. + +On those systems, like FreeBSD, you must tell configure where to find +the libintl library and the libintl.h include file: + +CPPFLAGS="-I/usr/local/include -L/usr/local/lib" ./configure --prefix=/usr/local + +Once you have done this, if make fails, use gmake (the name FreeBSD +gives to GNU make) instead. + +-------------------------------- +Donald Allingham +dallingham@users.sourceforge.net diff --git a/gramps2/TODO b/gramps2/TODO new file mode 100644 index 000000000..79168315c --- /dev/null +++ b/gramps2/TODO @@ -0,0 +1,31 @@ +* Allow for multiple notes. A tabbed interface would be really useful, + since there are no titles for notes. Not all objects would necessarily + need multiple notes. Determine which ones should and shouldn't. +* Drag and drop should display the icon we are dragging instead of just + the default icon. Nautilus does this very effectively, and GTK has + support for this. +* Provide an "import" of a gramps package. Not too difficult to do this, + since there is already a ReadTarFile class which will unpackage the + file. Needs have an interface built around it. +* Catch uncaught exceptions at the top level, notifiy the user, and + store the results in a file that can be emailed. Have the start of + this with the gramps.err file, but most users don't realize that + this file has been created. Some type of notification is needed. +* Speed up the reading of the database. The python XML routines are not + as fast as I would like, and it can take a minute or so to read a + large database. This is way too slow. +* Finish the generic load of revision control interfaces to allow a + revision control plugin system. Most of the work is already done. +* Extend the gramps package exporting to export to a ISO-9660 CD-ROM + image. Thumbnails would need to be exported for this as well, since + the CD-ROM would be read-only after burning. +* Disable the save buttons if gramps database is marked read-only. Disable + the adding of media objects as well, since this will cause gramps to + try to create a thumbnail in a readonly database. +* 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. +* Sort all lists +* Startup tips. +* And a whole lot more.... diff --git a/gramps2/aclocal.m4 b/gramps2/aclocal.m4 new file mode 100644 index 000000000..bcf9c02c5 --- /dev/null +++ b/gramps2/aclocal.m4 @@ -0,0 +1,939 @@ +# aclocal.m4 generated automatically by aclocal 1.6.3 -*- Autoconf -*- + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# Do all the work for Automake. -*- Autoconf -*- + +# This macro actually does too much some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. + +# 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, 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. + +# serial 8 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +AC_PREREQ([2.52]) + +# Autoconf 2.50 wants to disallow AM_ names. We explicitly allow +# the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], [AC_PACKAGE_TARNAME])dnl + AC_SUBST([VERSION], [AC_PACKAGE_VERSION])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl + +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_][CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_][CC], + defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_][CXX], + defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + +# Copyright 2002 Free Software Foundation, Inc. + +# 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, 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 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.6"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.6.3])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright 2001, 2002 Free Software Foundation, Inc. + +# 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, 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. + +# serial 2 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# +# Check to make sure that the build environment is sane. +# + +# Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + +# 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, 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. + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# -*- Autoconf -*- + + +# Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + +# 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, 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. + +# serial 3 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# AM_AUX_DIR_EXPAND + +# Copyright 2001 Free Software Foundation, Inc. + +# 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, 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. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +# Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50]) + +AC_DEFUN([AM_AUX_DIR_EXPAND], [ +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. + +# Copyright 2001 Free Software Foundation, Inc. + +# 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, 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. + +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# AM_PROG_INSTALL_STRIP + +# Copyright 2001 Free Software Foundation, Inc. + +# 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, 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. + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# serial 4 -*- Autoconf -*- + +# Copyright 1999, 2000, 2001 Free Software Foundation, Inc. + +# 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, 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. + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null +AC_SUBST([DEPDIR]) +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + +# 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, 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. + +#serial 2 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright 2001 Free Software Foundation, Inc. -*- Autoconf -*- + +# 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, 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. + +# serial 2 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST(am__include) +AC_SUBST(am__quote) +AC_MSG_RESULT($_am_result) +rm -f confinc confmf +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright 1997, 2000, 2001 Free Software Foundation, Inc. + +# 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, 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. + +# serial 5 + +AC_PREREQ(2.52) + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([conditional \"$1\" was never defined. +Usually this means the macro was only invoked conditionally.]) +fi])]) + + +# Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + +# 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, 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. + +# AM_PATH_PYTHON([MINIMUM-VERSION]) + +# Adds support for distributing Python modules and packages. To +# install modules, copy them to $(pythondir), using the python_PYTHON +# automake variable. To install a package with the same name as the +# automake package, install to $(pkgpythondir), or use the +# pkgpython_PYTHON automake variable. + +# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as +# locations to install python extension modules (shared libraries). +# Another macro is required to find the appropriate flags to compile +# extension modules. + +# If your package is configured with a different prefix to python, +# users will have to add the install directory to the PYTHONPATH +# environment variable, or create a .pth file (see the python +# documentation for details). + +# If the MINIUMUM-VERSION argument is passed, AM_PATH_PYTHON will +# cause an error if the version of python installed on the system +# doesn't meet the requirement. MINIMUM-VERSION should consist of +# numbers and dots only. + +AC_DEFUN([AM_PATH_PYTHON], + [ + dnl Find a Python interpreter. Python versions prior to 1.5 are not + dnl supported because the default installation locations changed from + dnl $prefix/lib/site-python in 1.4 to $prefix/lib/python1.5/site-packages + dnl in 1.5. + m4_define([_AM_PYTHON_INTERPRETER_LIST], + [python python2 python2.2 python2.1 python2.0 python1.6 python1.5]) + + m4_if([$1],[],[ + dnl No version check is needed. + # Find any Python interpreter. + AC_PATH_PROG([PYTHON], _AM_PYTHON_INTERPRETER_LIST)],[ + dnl A version check is needed. + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + AC_MSG_CHECKING([whether $PYTHON version >= $1]) + AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], + [AC_MSG_RESULT(yes)], + [AC_MSG_ERROR(too old)]) + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + AC_CACHE_CHECK([for a Python interpreter with version >= $1], + [am_cv_pathless_PYTHON],[ + for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST : ; do + if test "$am_cv_pathless_PYTHON" = : ; then + AC_MSG_ERROR([no suitable Python interpreter found]) + fi + AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) + done]) + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) + fi + ]) + + dnl Query Python for its version number. Getting [:3] seems to be + dnl the best way to do this; it's what "site.py" does in the standard + dnl library. + + AC_CACHE_CHECK([for $am_cv_pathless_PYTHON version], [am_cv_python_version], + [am_cv_python_version=`$PYTHON -c "import sys; print sys.version[[:3]]"`]) + AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) + + dnl Use the values of $prefix and $exec_prefix for the corresponding + dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made + dnl distinct variables so they can be overridden if need be. However, + dnl general consensus is that you shouldn't need this ability. + + AC_SUBST([PYTHON_PREFIX], ['${prefix}']) + AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) + + dnl At times (like when building shared libraries) you may want + dnl to know which OS platform Python thinks this is. + + AC_CACHE_CHECK([for $am_cv_pathless_PYTHON platform], + [am_cv_python_platform], + [am_cv_python_platform=`$PYTHON -c "import sys; print sys.platform"`]) + AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) + + + dnl Set up 4 directories: + + dnl pythondir -- where to install python scripts. This is the + dnl site-packages directory, not the python standard library + dnl directory like in previous automake betas. This behaviour + dnl is more consistent with lispdir.m4 for example. + dnl + dnl Also, if the package prefix isn't the same as python's prefix, + dnl then the old $(pythondir) was pretty useless. + + AC_SUBST([pythondir], + [$PYTHON_PREFIX"/lib/python"$PYTHON_VERSION/site-packages]) + + dnl pkgpythondir -- $PACKAGE directory under pythondir. Was + dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is + dnl more consistent with the rest of automake. + dnl Maybe this should be put in python.am? + + AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) + + dnl pyexecdir -- directory for installing python extension modules + dnl (shared libraries) Was PYTHON_SITE_EXEC in previous betas. + + AC_SUBST([pyexecdir], + [${PYTHON_EXEC_PREFIX}/lib/python${PYTHON_VERSION}/site-packages]) + + dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) + dnl Maybe this should be put in python.am? + + AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) +]) + + +# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# --------------------------------------------------------------------------- +# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. +# Run ACTION-IF-FALSE otherwise. +# This test uses sys.hexversion instead of the string equivalant (first +# word of sys.version), in order to cope with versions such as 2.2c1. +# hexversion has been introduced in Python 1.5.2; it's probably not +# worth to support older versions (1.5.1 was released on October 31, 1998). +AC_DEFUN([AM_PYTHON_CHECK_VERSION], + [prog="import sys, string +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +minver = map(int, string.split('$2', '.')) + [[0, 0, 0]] +minverhex = 0 +for i in xrange(0, 4): minverhex = (minverhex << 8) + minver[[i]] +sys.exit(sys.hexversion < minverhex)" + AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) + +# Copyright 2001 Free Software Foundation, Inc. -*- Autoconf -*- + +# 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, 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. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + diff --git a/gramps2/autogen.sh b/gramps2/autogen.sh new file mode 100755 index 000000000..c34847ba0 --- /dev/null +++ b/gramps2/autogen.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. +# shamelessly borrowed and hacked from the Galeon source distribution + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +PKG_NAME="gramps" + +(test -f $srcdir/configure.in \ + && test -f $srcdir/src/gramps_main.py) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level $PKG_NAME directory" + exit 1 +} + +DIE=0 + + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`autoconf' installed to compile $PKG_NAME." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`automake' installed to compile $PKG_NAME." + echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.6.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing \`aclocal'. The version of \`automake'" + echo "installed doesn't appear recent enough." + echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.6.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo \`$0\'" command line." + echo +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + + +dr=$srcdir +echo processing $dr +( cd $dr + aclocalinclude="$ACLOCAL_FLAGS" + echo "Running aclocal $aclocalinclude ..." + aclocal $aclocalinclude || { + echo + echo "**Error**: aclocal failed. This may mean that you have not" + echo "installed all of the packages you need, or you may need to" + echo "set ACLOCAL_FLAGS to include \"-I \$prefix/share/aclocal\"" + echo "for the prefix where you installed the packages whose" + echo "macros were not found" + exit 1 + } + + echo "Running automake --gnu $am_opt ..." + automake --add-missing --gnu $am_opt || + { echo "**Error**: automake failed."; exit 1; } + echo "Running autoconf ..." + autoconf || { echo "**Error**: autoconf failed."; exit 1; } +) || exit 1 + + echo "Setting py-compile script executable ..." + chmod 755 py-compile + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile $PKG_NAME || exit 1 +else + echo Skipping configure process. +fi diff --git a/gramps2/configure b/gramps2/configure new file mode 100755 index 000000000..5253f28be --- /dev/null +++ b/gramps2/configure @@ -0,0 +1,4941 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.53. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + + +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Name of the executable. +as_me=`(basename "$0") 2>/dev/null || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/gramps.py" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_STAT_H +# include +#endif +#if STDC_HEADERS +# include +# include +#else +# if HAVE_STDLIB_H +# include +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include +# endif +# include +#endif +#if HAVE_STRINGS_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif +#if HAVE_UNISTD_H +# include +#endif" + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.53. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell meta-characters. +ac_configure_args= +ac_sep= +for ac_arg +do + case $ac_arg in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n ) continue ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + ac_sep=" " ;; + esac + # Get rid of the leading space. +done + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + +am__api_version="1.6" +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="${MAKE}"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + # test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# Define the identity of the package. + PACKAGE=gramps + VERSION=0.9.0pre1 + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. + + + +RELEASE=rc4 + +VERSIONSTRING=$VERSION +if test x"$RELEASE" != "x" +then + VERSIONSTRING="$VERSION-$RELEASE" +fi + + + + + + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_MSGFMT+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +MSGFMT=$ac_cv_path_MSGFMT + +if test -n "$MSGFMT"; then + echo "$as_me:$LINENO: result: $MSGFMT" >&5 +echo "${ECHO_T}$MSGFMT" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + + +LANGUAGES="sv de fr es it pt_BR ru da_DK cs" + + +DISTLANGS= +POFILES= +MOFILES= +for lang in $LANGUAGES; do + POFILES="$POFILES $lang.po" + MOFILES="$MOFILES $lang.mo" +done + + + + + + + + if test -n "$PYTHON"; then + # If the user set $PYTHON, use it and don't search something else. + echo "$as_me:$LINENO: checking whether $PYTHON version >= 2.2" >&5 +echo $ECHO_N "checking whether $PYTHON version >= 2.2... $ECHO_C" >&6 + prog="import sys, string +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +minver = map(int, string.split('2.2', '.')) + [0, 0, 0] +minverhex = 0 +for i in xrange(0, 4): minverhex = (minverhex << 8) + minver[i] +sys.exit(sys.hexversion < minverhex)" + if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 + ($PYTHON -c "$prog") >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + { { echo "$as_me:$LINENO: error: too old" >&5 +echo "$as_me: error: too old" >&2;} + { (exit 1); exit 1; }; } +fi + + else + # Otherwise, try each interpreter until we find one that satisfies + # VERSION. + echo "$as_me:$LINENO: checking for a Python interpreter with version >= 2.2" >&5 +echo $ECHO_N "checking for a Python interpreter with version >= 2.2... $ECHO_C" >&6 +if test "${am_cv_pathless_PYTHON+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + for am_cv_pathless_PYTHON in python python2 python2.2 python2.1 python2.0 python1.6 python1.5 : ; do + if test "$am_cv_pathless_PYTHON" = : ; then + { { echo "$as_me:$LINENO: error: no suitable Python interpreter found" >&5 +echo "$as_me: error: no suitable Python interpreter found" >&2;} + { (exit 1); exit 1; }; } + fi + prog="import sys, string +# split strings by '.' and convert to numeric. Append some zeros +# because we need at least 4 digits for the hex conversion. +minver = map(int, string.split('2.2', '.')) + [0, 0, 0] +minverhex = 0 +for i in xrange(0, 4): minverhex = (minverhex << 8) + minver[i] +sys.exit(sys.hexversion < minverhex)" + if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 + ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + break +fi + + done +fi +echo "$as_me:$LINENO: result: $am_cv_pathless_PYTHON" >&5 +echo "${ECHO_T}$am_cv_pathless_PYTHON" >&6 + # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. + # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. +set dummy $am_cv_pathless_PYTHON; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PYTHON+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PYTHON in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +PYTHON=$ac_cv_path_PYTHON + +if test -n "$PYTHON"; then + echo "$as_me:$LINENO: result: $PYTHON" >&5 +echo "${ECHO_T}$PYTHON" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + fi + + + + echo "$as_me:$LINENO: checking for $am_cv_pathless_PYTHON version" >&5 +echo $ECHO_N "checking for $am_cv_pathless_PYTHON version... $ECHO_C" >&6 +if test "${am_cv_python_version+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + am_cv_python_version=`$PYTHON -c "import sys; print sys.version[:3]"` +fi +echo "$as_me:$LINENO: result: $am_cv_python_version" >&5 +echo "${ECHO_T}$am_cv_python_version" >&6 + PYTHON_VERSION=$am_cv_python_version + + + + PYTHON_PREFIX='${prefix}' + + PYTHON_EXEC_PREFIX='${exec_prefix}' + + + + echo "$as_me:$LINENO: checking for $am_cv_pathless_PYTHON platform" >&5 +echo $ECHO_N "checking for $am_cv_pathless_PYTHON platform... $ECHO_C" >&6 +if test "${am_cv_python_platform+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + am_cv_python_platform=`$PYTHON -c "import sys; print sys.platform"` +fi +echo "$as_me:$LINENO: result: $am_cv_python_platform" >&5 +echo "${ECHO_T}$am_cv_python_platform" >&6 + PYTHON_PLATFORM=$am_cv_python_platform + + + + + + pythondir=$PYTHON_PREFIX"/lib/python"$PYTHON_VERSION/site-packages + + + + pkgpythondir=\${pythondir}/$PACKAGE + + + + pyexecdir=${PYTHON_EXEC_PREFIX}/lib/python${PYTHON_VERSION}/site-packages + + + + pkgpyexecdir=\${pyexecdir}/$PACKAGE + + + +pythondir=\${prefix}/share +pyexecdir=\${prefix}/share +pkgpythondir=\${prefix}/share/\${PACKAGE} +pkgpyexecdir=\${prefix}/share/\${PACKAGE} + +# Extract the first word of "sh", so it can be a program name with args. +set dummy sh; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_BINSH+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $BINSH in + [\\/]* | ?:[\\/]*) + ac_cv_path_BINSH="$BINSH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_BINSH="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +BINSH=$ac_cv_path_BINSH + +if test -n "$BINSH"; then + echo "$as_me:$LINENO: result: $BINSH" >&5 +echo "${ECHO_T}$BINSH" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[:3]"` + +if test "$PYTHON_VERSION" != "2.2" +then + # Extract the first word of "python2.2", so it can be a program name with args. +set dummy python2.2; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_PYTHON22+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PYTHON22 in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON22="$PYTHON22" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON22="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +PYTHON22=$ac_cv_path_PYTHON22 + +if test -n "$PYTHON22"; then + echo "$as_me:$LINENO: result: $PYTHON22" >&5 +echo "${ECHO_T}$PYTHON22" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +else + PYTHON22=$PYTHON +fi + +# Extract the first word of "zip", so it can be a program name with args. +set dummy zip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_ZIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $ZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ZIP="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +ZIP=$ac_cv_path_ZIP + +if test -n "$ZIP"; then + echo "$as_me:$LINENO: result: $ZIP" >&5 +echo "${ECHO_T}$ZIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="${MAKE}"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$as_dir/$ac_word" ${1+"$@"} + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 + (eval $ac_compiler --version &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 + (eval $ac_compiler -v &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 + (eval $ac_compiler -V &5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null; + ls a.out conftest 2>/dev/null; + ls a.* conftest.* 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;; + a.out ) # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool --akim. + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5 +echo "$as_me: error: C compiler cannot create executables" >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include ' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_declaration +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null + + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CC" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#include +#include +#include + +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_header_stdc=no +fi +rm -f conftest.err conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +if test "${ac_cv_header_libintl_h+set}" = set; then + echo "$as_me:$LINENO: checking for libintl.h" >&5 +echo $ECHO_N "checking for libintl.h... $ECHO_C" >&6 +if test "${ac_cv_header_libintl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_libintl_h" >&5 +echo "${ECHO_T}$ac_cv_header_libintl_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking libintl.h usability" >&5 +echo $ECHO_N "checking libintl.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking libintl.h presence" >&5 +echo $ECHO_N "checking libintl.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +#include +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + egrep -v '^ *\+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: libintl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: libintl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: libintl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: libintl.h: proceeding with the preprocessor's result" >&2;};; + no:yes ) + { echo "$as_me:$LINENO: WARNING: libintl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: libintl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: libintl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: libintl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: libintl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: libintl.h: proceeding with the preprocessor's result" >&2;};; +esac +echo "$as_me:$LINENO: checking for libintl.h" >&5 +echo $ECHO_N "checking for libintl.h... $ECHO_C" >&6 +if test "${ac_cv_header_libintl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_libintl_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_libintl_h" >&5 +echo "${ECHO_T}$ac_cv_header_libintl_h" >&6 + +fi + + + +echo "$as_me:$LINENO: checking for textdomain in -lc" >&5 +echo $ECHO_N "checking for textdomain in -lc... $ECHO_C" >&6 +if test "${ac_cv_lib_c_textdomain+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char textdomain (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +textdomain (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_c_textdomain=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_c_textdomain=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_c_textdomain" >&5 +echo "${ECHO_T}$ac_cv_lib_c_textdomain" >&6 +if test $ac_cv_lib_c_textdomain = yes; then + LIBS="" +else + echo "$as_me:$LINENO: checking for textdomain in -lintl" >&5 +echo $ECHO_N "checking for textdomain in -lintl... $ECHO_C" >&6 +if test "${ac_cv_lib_intl_textdomain+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char textdomain (); +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +textdomain (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_intl_textdomain=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_lib_intl_textdomain=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_intl_textdomain" >&5 +echo "${ECHO_T}$ac_cv_lib_intl_textdomain" >&6 +if test $ac_cv_lib_intl_textdomain = yes; then + LIBS="-lintl" +else + { { echo "$as_me:$LINENO: error: \"Could not find internationalization libraries\"" >&5 +echo "$as_me: error: \"Could not find internationalization libraries\"" >&2;} + { (exit 1); exit 1; }; } +fi + + +fi + + + +# Extract the first word of "gnome-config", so it can be a program name with args. +set dummy gnome-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_HAVE_GNOME_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$HAVE_GNOME_CONFIG"; then + ac_cv_prog_HAVE_GNOME_CONFIG="$HAVE_GNOME_CONFIG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_HAVE_GNOME_CONFIG=""YES"" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_HAVE_GNOME_CONFIG" && ac_cv_prog_HAVE_GNOME_CONFIG=""NO"" +fi +fi +HAVE_GNOME_CONFIG=$ac_cv_prog_HAVE_GNOME_CONFIG +if test -n "$HAVE_GNOME_CONFIG"; then + echo "$as_me:$LINENO: result: $HAVE_GNOME_CONFIG" >&5 +echo "${ECHO_T}$HAVE_GNOME_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +GNOMEHELP=`gnome-config --prefix` + + +echo "$as_me:$LINENO: checking Python bindings for sax/xml" >&5 +echo $ECHO_N "checking Python bindings for sax/xml... $ECHO_C" >&6 + +cat > conftest.py <&5 +echo "$as_me: error: + +**** The python interpreter can't find the SAX/XML bindings." >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + +echo "$as_me:$LINENO: checking Python bindings for gtk" >&5 +echo $ECHO_N "checking Python bindings for gtk... $ECHO_C" >&6 + +cat > conftest.py <&5 +echo "$as_me: error: + +**** The python interpreter can't find the python bindings for gtk 2.0." >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + +echo "$as_me:$LINENO: checking Python bindings for GNOME" >&5 +echo $ECHO_N "checking Python bindings for GNOME... $ECHO_C" >&6 + +cat > conftest.py <&5 +echo "$as_me: error: +**** The python interpreter can't find the python bindings for GNOME." >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + +echo "$as_me:$LINENO: checking Python/libglade bindings" >&5 +echo $ECHO_N "checking Python/libglade bindings... $ECHO_C" >&6 + +cat > conftest.py <&5 +echo "$as_me: error: + +**** The python interpreter can't find the python bindings for libglade." >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + +echo "$as_me:$LINENO: checking Python bindings for gconf" >&5 +echo $ECHO_N "checking Python bindings for gconf... $ECHO_C" >&6 + +cat > conftest.py <&5 +echo "$as_me: error: + +**** The python interpreter can't find the python bindings for gconf." >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + + + +echo "$as_me:$LINENO: checking for headers required to compile python extensions" >&5 +echo $ECHO_N "checking for headers required to compile python extensions... $ECHO_C" >&6 + +if test "$PYTHON22" != ""; then + py_prefix=`$PYTHON22 -c "import sys; print sys.prefix"` + py_exec_prefix=`$PYTHON22 -c "import sys; print sys.exec_prefix"` + P22_INCLUDES="-I${py_prefix}/include/python2.2" + if test "$py_prefix" != "$py_exec_prefix"; then + P22_INCLUDES="$P22_INCLUDES -I${py_exec_prefix}/include/python2.2" + fi + if test -f "${py_exec_prefix}/include/python2.2/Python.h" + then + INTLLIBS="${INTLLIBS}intl22.so " + fi +fi + +echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 + +SCROLLKEEPER_REQUIRED=0.1.4 + + +# Extract the first word of "scrollkeeper-config", so it can be a program name with args. +set dummy scrollkeeper-config; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_SCROLLKEEPER_CONFIG+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $SCROLLKEEPER_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SCROLLKEEPER_CONFIG="$SCROLLKEEPER_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SCROLLKEEPER_CONFIG="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_SCROLLKEEPER_CONFIG" && ac_cv_path_SCROLLKEEPER_CONFIG="no" + ;; +esac +fi +SCROLLKEEPER_CONFIG=$ac_cv_path_SCROLLKEEPER_CONFIG + +if test -n "$SCROLLKEEPER_CONFIG"; then + echo "$as_me:$LINENO: result: $SCROLLKEEPER_CONFIG" >&5 +echo "${ECHO_T}$SCROLLKEEPER_CONFIG" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x$SCROLLKEEPER_CONFIG = xno; then + { { echo "$as_me:$LINENO: error: Couldn't find scrollkeeper-config. Please install the scrollkeeper package." >&5 +echo "$as_me: error: Couldn't find scrollkeeper-config. Please install the scrollkeeper package." >&2;} + { (exit 1); exit 1; }; } + DISABLE_SCROLLKEEPER=1 + +fi + +# Extract the first word of "jw", so it can be a program name with args. +set dummy jw; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_JW+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $JW in + [\\/]* | ?:[\\/]*) + ac_cv_path_JW="$JW" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_JW="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_path_JW" && ac_cv_path_JW="no" + ;; +esac +fi +JW=$ac_cv_path_JW + +if test -n "$JW"; then + echo "$as_me:$LINENO: result: $JW" >&5 +echo "${ECHO_T}$JW" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test x$JW = xno; then + HAVE_JW="no" +else + HAVE_JW="yes" +fi + + + + + + + + + + + + + + + + +ac_config_files="$ac_config_files Makefile src/Makefile src/const.py src/docgen/Makefile src/filters/Makefile src/plugins/Makefile src/data/Makefile src/data/templates/Makefile src/po/Makefile doc/Makefile doc/gramps-manual/Makefile doc/gramps-manual/C/Makefile doc/extending-gramps/Makefile doc/extending-gramps/C/Makefile omf-install/Makefile gramps.spec gramps.sh" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overriden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if cmp -s $cache_file confcache; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then we branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +cat >confdef2opt.sed <<\_ACEOF +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\),-D\1=\2,g +t quote +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\),-D\1=\2,g +t quote +d +: quote +s,[ `~#$^&*(){}\\|;'"<>?],\\&,g +s,\[,\\&,g +s,\],\\&,g +s,\$,$$,g +p +_ACEOF +# We use echo to avoid assuming a particular line-breaking character. +# The extra dot is to prevent the shell from consuming trailing +# line-breaks from the sub-command output. A line-break within +# single-quotes doesn't work because, if this script is created in a +# platform that uses two characters for line-breaks (e.g., DOS), tr +# would break. +ac_LF_and_DOT=`echo; echo .` +DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'` +rm -f confdef2opt.sed + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# NLS nuisances. +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + +(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && + { $as_unset LANG || test "${LANG+set}" != set; } || + { LANG=C; export LANG; } +(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && + { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || + { LC_ALL=C; export LC_ALL; } +(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && + { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || + { LC_TIME=C; export LC_TIME; } +(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && + { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || + { LC_CTYPE=C; export LC_CTYPE; } +(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && + { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || + { LANGUAGE=C; export LANGUAGE; } +(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && + { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || + { LC_COLLATE=C; export LC_COLLATE; } +(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && + { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || + { LC_NUMERIC=C; export LC_NUMERIC; } +(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && + { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || + { LC_MESSAGES=C; export LC_MESSAGES; } + + +# Name of the executable. +as_me=`(basename "$0") 2>/dev/null || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conftest.sh + echo "exit 0" >>conftest.sh + chmod +x conftest.sh + if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conftest.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.53. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to ." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.53, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + shift + set dummy "$ac_option" "$ac_optarg" ${1+"$@"} + shift + ;; + -*);; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_need_defaults=false;; + esac + + case $1 in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion" + exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;; +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + shift + CONFIG_FILES="$CONFIG_FILES $1" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + shift + CONFIG_HEADERS="$CONFIG_HEADERS $1" + ac_need_defaults=false;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/const.py" ) CONFIG_FILES="$CONFIG_FILES src/const.py" ;; + "src/docgen/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/docgen/Makefile" ;; + "src/filters/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/filters/Makefile" ;; + "src/plugins/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/plugins/Makefile" ;; + "src/data/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/data/Makefile" ;; + "src/data/templates/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/data/templates/Makefile" ;; + "src/po/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/po/Makefile" ;; + "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "doc/gramps-manual/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/gramps-manual/Makefile" ;; + "doc/gramps-manual/C/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/gramps-manual/C/Makefile" ;; + "doc/extending-gramps/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/extending-gramps/Makefile" ;; + "doc/extending-gramps/C/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/extending-gramps/C/Makefile" ;; + "omf-install/Makefile" ) CONFIG_FILES="$CONFIG_FILES omf-install/Makefile" ;; + "gramps.spec" ) CONFIG_FILES="$CONFIG_FILES gramps.spec" ;; + "gramps.sh" ) CONFIG_FILES="$CONFIG_FILES gramps.sh" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. +: ${TMPDIR=/tmp} +{ + tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=$TMPDIR/cs$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@AMTAR@,$AMTAR,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@RELEASE@,$RELEASE,;t t +s,@VERSIONSTRING@,$VERSIONSTRING,;t t +s,@MSGFMT@,$MSGFMT,;t t +s,@LANGUAGES@,$LANGUAGES,;t t +s,@POFILES@,$POFILES,;t t +s,@MOFILES@,$MOFILES,;t t +s,@PYTHON@,$PYTHON,;t t +s,@PYTHON_VERSION@,$PYTHON_VERSION,;t t +s,@PYTHON_PREFIX@,$PYTHON_PREFIX,;t t +s,@PYTHON_EXEC_PREFIX@,$PYTHON_EXEC_PREFIX,;t t +s,@PYTHON_PLATFORM@,$PYTHON_PLATFORM,;t t +s,@pythondir@,$pythondir,;t t +s,@pkgpythondir@,$pkgpythondir,;t t +s,@pyexecdir@,$pyexecdir,;t t +s,@pkgpyexecdir@,$pkgpyexecdir,;t t +s,@BINSH@,$BINSH,;t t +s,@PYTHON22@,$PYTHON22,;t t +s,@ZIP@,$ZIP,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CCDEPMODE@,$CCDEPMODE,;t t +s,@CPP@,$CPP,;t t +s,@HAVE_GNOME_CONFIG@,$HAVE_GNOME_CONFIG,;t t +s,@SCROLLKEEPER_REQUIRED@,$SCROLLKEEPER_REQUIRED,;t t +s,@SCROLLKEEPER_CONFIG@,$SCROLLKEEPER_CONFIG,;t t +s,@DISABLE_SCROLLKEEPER@,$DISABLE_SCROLLKEEPER,;t t +s,@JW@,$JW,;t t +s,@HAVE_JW@,$HAVE_JW,;t t +s,@GNOMEHELP@,$GNOMEHELP,;t t +s,@P15_INCLUDES@,$P15_INCLUDES,;t t +s,@P20_INCLUDES@,$P20_INCLUDES,;t t +s,@P21_INCLUDES@,$P21_INCLUDES,;t t +s,@P22_INCLUDES@,$P22_INCLUDES,;t t +s,@INTLLIBS@,$INTLLIBS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { case "$ac_dir" in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy="$ac_dir" +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || + mkdir "$as_incr_dir" || + { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; } + ;; + esac +done; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { case $dirpart/$fdir in + [\\/]* | ?:[\\/]* ) as_incr_dir=;; + *) as_incr_dir=.;; +esac +as_dummy=$dirpart/$fdir +for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do + case $as_mkdir_dir in + # Skip DOS drivespec + ?:) as_incr_dir=$as_mkdir_dir ;; + *) + as_incr_dir=$as_incr_dir/$as_mkdir_dir + test -d "$as_incr_dir" || + mkdir "$as_incr_dir" || + { { echo "$as_me:$LINENO: error: cannot create $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; } + ;; + esac +done; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + exec 5>/dev/null + $SHELL $CONFIG_STATUS || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/gramps2/configure.in b/gramps2/configure.in new file mode 100644 index 000000000..3b8dd3bee --- /dev/null +++ b/gramps2/configure.in @@ -0,0 +1,293 @@ +dnl Process this file with autoconf to produce a configure script. +dnl May need to run automake && aclocal first +AC_INIT(src/gramps.py) +AM_INIT_AUTOMAKE(gramps, 0.9.0pre1) +RELEASE=rc4 + +VERSIONSTRING=$VERSION +if test x"$RELEASE" != "x" +then + VERSIONSTRING="$VERSION-$RELEASE" +fi + +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) +AC_SUBST(RELEASE) +AC_SUBST(VERSIONSTRING) + +AC_PATH_PROG(MSGFMT, msgfmt) +AC_SUBST(MSGFMT) + +LANGUAGES="sv de fr es it pt_BR ru da_DK cs" +AC_SUBST(LANGUAGES) + +DISTLANGS= +POFILES= +MOFILES= +for lang in $LANGUAGES; do + POFILES="$POFILES $lang.po" + MOFILES="$MOFILES $lang.mo" +done +AC_SUBST(POFILES) +AC_SUBST(MOFILES) + +dnl Checks for programs. +dnl We first only check for python >= 1.5 +AM_PATH_PYTHON(2.2) + +dnl override automatic python detection with our own place +pythondir=\${prefix}/share +pyexecdir=\${prefix}/share +pkgpythondir=\${prefix}/share/\${PACKAGE} +pkgpyexecdir=\${prefix}/share/\${PACKAGE} + +AC_PATH_PROG(BINSH, sh) + +changequote(<<, >>)dnl +PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[:3]"` +changequote([, ])dnl + +if test "$PYTHON_VERSION" != "2.2" +then + AC_PATH_PROG(PYTHON22, python2.2) +else + PYTHON22=$PYTHON +fi + +AC_PATH_PROG(ZIP, zip) + +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +AC_PROG_CC + +AC_CHECK_HEADER(libintl.h) + +AC_CHECK_LIB(c,textdomain,LIBS="", + [ AC_CHECK_LIB(intl,textdomain, + LIBS="-lintl", + AC_MSG_ERROR("Could not find internationalization libraries")) + ]) + +dnl Check for programs + +AC_CHECK_PROG(HAVE_GNOME_CONFIG, gnome-config, "YES", "NO") +GNOMEHELP=`gnome-config --prefix` + +dnl Check if python bindings for gtk are installed + +AC_MSG_CHECKING(Python bindings for sax/xml) +changequote(,) +cat > conftest.py < conftest.py < conftest.py < conftest.py < conftest.py < 0.3) but basic scrollkeeper instructions +dnl == use 0.1.4 example so we'll just check for that +dnl ====================================================== +SCROLLKEEPER_REQUIRED=0.1.4 +AC_SUBST(SCROLLKEEPER_REQUIRED) + +dnl First see that *some* version of scrollkeeper is installed +AC_PATH_PROG(SCROLLKEEPER_CONFIG, scrollkeeper-config, no) +if test x$SCROLLKEEPER_CONFIG = xno; then + AC_MSG_ERROR(Couldn't find scrollkeeper-config. Please install the scrollkeeper package.) + DISABLE_SCROLLKEEPER=1 + AC_SUBST(DISABLE_SCROLLKEEPER) +fi + +dnl ====================================================== +dnl == GNOME modified DTD's need jw, not db2html +dnl ====================================================== +AC_PATH_PROG(JW, jw, no) +if test x$JW = xno; then + HAVE_JW="no" +else + HAVE_JW="yes" +fi +AC_SUBST(HAVE_JW) + +dnl ====================================================== +dnl == end of modern doc tests +dnl ====================================================== + + +AC_SUBST(BINSH) +AC_SUBST(PYTHON) +AC_SUBST(PYTHON_VERSION) +AC_SUBST(GNOMEHELP) +AC_SUBST(LIBS) + +AC_SUBST(P15_INCLUDES) +AC_SUBST(P20_INCLUDES) +AC_SUBST(P21_INCLUDES) +AC_SUBST(P22_INCLUDES) +AC_SUBST(INTLLIBS) + +AC_OUTPUT([ +Makefile +src/Makefile +src/const.py +src/docgen/Makefile +src/filters/Makefile +src/plugins/Makefile +src/data/Makefile +src/data/templates/Makefile +src/po/Makefile +doc/Makefile +doc/gramps-manual/Makefile +doc/gramps-manual/C/Makefile +doc/extending-gramps/Makefile +doc/extending-gramps/C/Makefile +omf-install/Makefile +gramps.spec +gramps.sh]) diff --git a/gramps2/doc/Makefile.am b/gramps2/doc/Makefile.am new file mode 100644 index 000000000..a24f2349f --- /dev/null +++ b/gramps2/doc/Makefile.am @@ -0,0 +1,11 @@ +# Process this file with automake to produce Makefile.in + +SUBDIRS = gramps-manual extending-gramps + +man_IN_FILES = gramps.1.in +man_MANS = ${man_IN_FILES:.1.in=.1} + +EXTRA_DIST = $(man_MANS) $(man_IN_FILES) sgmldocs.make + +gramps.1: $(top_builddir)/config.status gramps.1.in + cd $(top_builddir) && CONFIG_FILES=doc/$@ $(SHELL) ./config.status diff --git a/gramps2/doc/Makefile.in b/gramps2/doc/Makefile.in new file mode 100644 index 000000000..93ac62ae5 --- /dev/null +++ b/gramps2/doc/Makefile.in @@ -0,0 +1,409 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to produce Makefile.in +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ + +SUBDIRS = gramps-manual extending-gramps + +man_IN_FILES = gramps.1.in +man_MANS = ${man_IN_FILES:.1.in=.1} + +EXTRA_DIST = $(man_MANS) $(man_IN_FILES) sgmldocs.make +subdir = doc +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +NROFF = nroff +MANS = $(man_MANS) + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +man1dir = $(mandir)/man1 +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(MANS) +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-recursive + +install-man: install-man1 + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-info: uninstall-info-recursive + +uninstall-man: uninstall-man1 + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive distclean distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-man1 install-recursive install-strip installcheck \ + installcheck-am installdirs installdirs-am \ + installdirs-recursive maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive tags tags-recursive uninstall \ + uninstall-am uninstall-info-am uninstall-info-recursive \ + uninstall-man uninstall-man1 uninstall-recursive + + +gramps.1: $(top_builddir)/config.status gramps.1.in + cd $(top_builddir) && CONFIG_FILES=doc/$@ $(SHELL) ./config.status +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/doc/extending-gramps/C/Makefile.am b/gramps2/doc/extending-gramps/C/Makefile.am new file mode 100644 index 000000000..31cb3cd32 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/Makefile.am @@ -0,0 +1,10 @@ +SGML_FILES = + +figs = + +docname = extending-gramps +lang = C +omffile = extending-gramps-C.omf +sgml_ents = +include ${top_srcdir}/doc/sgmldocs.make +dist-hook: app-dist-hook diff --git a/gramps2/doc/extending-gramps/C/Makefile.in b/gramps2/doc/extending-gramps/C/Makefile.in new file mode 100644 index 000000000..fcac383c3 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/Makefile.in @@ -0,0 +1,240 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +SGML_FILES = + +figs = + +docname = extending-gramps +lang = C +omffile = extending-gramps-C.omf +sgml_ents = +subdir = doc/extending-gramps/C +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/extending-gramps/C/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: +tags: TAGS +TAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="${top_distdir}" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic uninstall uninstall-am uninstall-info-am + +include ${top_srcdir}/doc/sgmldocs.make +dist-hook: app-dist-hook +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/doc/extending-gramps/C/extending-gramps-C.omf b/gramps2/doc/extending-gramps/C/extending-gramps-C.omf new file mode 100644 index 000000000..4f518e90b --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps-C.omf @@ -0,0 +1,14 @@ + + + + + Writing GRAMPS Extensions + + + GNOME|Applications + + + + + + diff --git a/gramps2/doc/extending-gramps/C/extending-gramps.sgml b/gramps2/doc/extending-gramps/C/extending-gramps.sgml new file mode 100644 index 000000000..3704fc45c --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps.sgml @@ -0,0 +1,774 @@ + +]> + + + +
+ + + Writing Extentions for gramps + + 2001 + Donald N. Allingham + + + + + + + + + + + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation + License, 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 here. + + + 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. + + + + + + + + + + + + + + + + + + + + This is version 1.0 of the Writing Extentions for gramps manual. + + + + + + + Introduction + + gramps was intended from the start to + allow the user to extend it through a plugin system. Five types of + plugins are supported - filters, reports, tools, import filters, + and export filters. In a way, an export filter can be viewed as a + special type of report, and an import filter can be viewed as a + special type of tool. + + + All plugins are written in the python + language. + + + Filters + + A filter is a plugin that be used to temporarily display or hide + individuals in the People View. The + filter is the simplest form of plugin, which only needs to + determine if a person meets or fails to meet its criteria. It + operates on a single person at a time. + + + Filters should never alter a database. + + + + Reports + + A report is a plugin that generates output. The output may be in + either a interactive, graphical form, or as an output + file. Report plugins are passed a reference to the internal + database and a reference to the active person, which allows the + plugn to operate on a single person, the entire database, or + anything in between. + + + Plugins that conform to the reportplugin interface appear in the + + Reports + + menu and in the Report Selection dialog + box. + + + A report should never alter the database. + + + + Tools + + A tool is a plugin that alters the database. It may perform + something as small changing the case of some text to something + as complex as merging redundant individuals. Tools plugins are + passed a reference to the internal database, the active person, + and a callback function. The callback function is used to notify + the main program if it needs to update the display with any + modified information. + + + Plugins that conform to the tool plugin interface appear in the + + Tools + + menu and in the Tool Selection dialog + box. + + + A tool is allowed (and usually expected) to alter the database. + + + + Import Filters + + An import filter is a plugin that adds information from another + source to the database. It is similar to a tool, but is called + differently to allow gramps to distinguish it from a tool. + + + Plugins that conform to the import filter calling syntax appear + in the + + File + Import + + menu. + + + An import filter is allowed to modify the database. + + + + Export Filters + + An export filter is a plugin that translates the gramps database + into the format expected by another program. Since it generates + an output file, it is similar to a report generator. However, + its calling syntax is different, so that gramps knows how to + distiguish it from a report generator. + + + Plugins that conform to the export filter calling syntax appear + in the + + File + Export + + menu. + + + An export filter should not alter the database. + + + + + + + + Writing Filters + + Users can create their own filters and add them to + gramps. By adding the filter to the + user's private filter directory (~/.gramps/filters), the filter will + be automatically recognized the next time that the program is + started. + + + Creating a filter + + Each filter is a class derived from the + Filter.Filter class. The + __init__ task may be overridden, but if so, + should call the __init__ function on the + Filter.Filter class. The parent class + provides the variable self.text, which + contains the text string passed as the qualifier. This string + provides additional information provided by the user. For + example, if the filter is used to match names, the qualifier + would be used to provide the name that is being compared + against. + + + All filter classes must define a match + function. The function takes one argument (other than + self), which is an object of type + Person to compare against. The function + should return a 1 if the person matches the filter, or a zero if + the person does not. + + + Each filter must be registered, so that + gramps knows about it. This is + accomplished by calling the + Filter.register_filter function. This + function takes three arguments - the filter class, a + description, and flag that indicates if the qualifier string is + needed. The description string appears in the pull down + interface within gramps, and helps + the user choose the appropriate filter. The qualifier flag tells + gramps whether or not the filter + needs a qualifier string. If this flag is 0, + gramps will disable the entry of a + qualifier string. + +
+ Sample filter implementation + + +import Filter +import string + +# class definition + +class SubString(Filter.Filter): + + def match(self,person): + name = person.getPrimaryName().getName() + return string.find(name,self.text) >= 0 + +Filter.register_filter(SubString, + description="Names that contain a substring", + qualifier=1) + + +
+
+
+ + + + + Writing Reports + + Users can create their own report generators and add them to + gramps. By adding the report generator + to the user's private plugin directory (~/.gramps/plugins), the report + generator will be automatically recognized the next time that the + program is started. + + + Creating a report generator + + Fewer restrictions are made on report generators than on + filters. The report generator is passed the current + gramps database and the active + person. The generator needs to take special care to make sure + that it does not alter the database in anyway. + + + A report generator is a function that takes two arguments + — a database (of type RelDataBase) + and the currently selected person (of type + Person). When called, this task should + generate the desired report. + + + This function's implementation can be as simple as generating + output without the user's intervention, or it could display a + graphical interface to allow the user to select options and + customize a report. + + + As with filters, the report generator must be registered before + gramps will understand it. The report + generator is registered using the + Plugins.register_report. This function + takes five arguments. + + + + + The report generation task This task + that generates the report. + + + + + The report category The category in + which the report is grouped in the + Reports menu and + in the Report Selection dialog. + + + + + The report name + The name of the report. + + + + + A text description of the report The + description appears in the report selection tool to provide + the user with a description of what the tools does. + + + + + A graphic logo in XPM format This may + be either a path to a filename, or a list of strings + containting the XPM data. If a filename is specified, care + must be taken to make sure the file location is relocatable + and can be determined at runtime. + + + + + While only the task and report name are required, it is + recommended to provide all five parameters. + +
+ Sample report implementation + + +import Plugins + +def report(database,person): + ... actual code ... + +Plugins.register_report( + task=report, + category="Category", + name="Report Name", + description="A text descripition of the report generator", + xpm="%s/myfile.xpm" % os.path.dirname(__file__) +) + +
+
+ + A little help - Format Interfaces + + gramps provides some help with + writing reports. Several generic python classes exist that aid + in the writing of report generators. These classes provide an + abstract interface for a type of document, such as a drawing, + word processor document, or a spreadsheet. From these core + classes, gramps derives interfaces to + various document formats. This means that by coding to the + generic word processing class (TextDoc), a + report generator can instant access to multiple file formats + (such as HTML, OpenOffice, and AbiWord). + + + This scheme of deriving a output format from a generic base + class also makes it easier to add new formats. Creating a new + derivied class targeting a different format (such as + KWord or + LaTeX) makes it easy for existing + report generators to use the new formats. + + +
+ + + + + Writing Tools + + Users can create their own tools and add them to + gramps. By adding the tool to the + user's private plugin directory (~/.gramps/plugins), the tool will be + automatically recognized the next time that + gramps is started. + + + Unlike a report generator, a tool is allowed to modify the + database. The tool is passed the current + gramps database, the active person, + and a callback function. The callback function should be called + with a non-zero argument upon completion of the tool if the + database has been altered. + + + As with filters and report generators, tools must be registered + before gramps will understand it. The + tool is registered using the + Plugins.register_tool. This function takes + four arguments. + + + + + The tool task This task + that executes the tool. + + + + + The tool category The category in which + the tool is grouped in the + Tools menu and in + the Tool Selection dialog. + + + + + The tool name + The name of the tool. + + + + + A text description of the tool The + description appears in the Tool Selection dialog to provide + the user with a description of what the tool does. + + + + + While only the task and report name are required, it is + recommended to provide all five parameters. + +
+ Sample tool implementation + + +import Plugins + +def tool(database,person,callback): + ... actual code ... + callback(1) + +Plugins.register_tool( + task=tool, + category="Category", + name="Tool Name", + description="A text descripition of the tool" +) + +
+
+ + + + + Writing Import Filters + + Import filters are similar to tools, since they are allowed to + modify the databases. An import filter is a task that accepts + three arguments — a database, the filename of the file that + is to be imported, and a callback function. + + + The database may or may not have data already in it. The import + filter cannot assume that data neither already exists nor that the + database is empty. + + + The callback function is different from the callback function used + for tools. The import filter's callback function is used to + indicate progress and update the status bar during the import + process. The function takes a value between 0.0 and 1.0, where 0.0 + represents the start of the import and 1.0 represents the + completion of the import. + + + As with the other plugin types, an import filter must be + registered with gramps. This is + accomplished by calling the + Plugins.register_import task. The + Plugins.register_import accepts two arguments + — the function the performs the import and a string + providing a brief description. This description is used as the + menu entry under the + + File + Import + + menu. + +
+ Sample Import Implementation + + +import Plugins + +def gedcom_import(database,filename,callback): + ... actual code ... + +Plugins.register_import(gedcom_import,"GEDCOM import") + + +
+
+ + + + + Writing Export Filters + + Export filters are similar to report generators. They are not + allowed to modify the database. An export filter accepts three + arguments — a database, the filename of the file that is to + be written, and a callback function. + + + The callback function is indentical from the callback function + used for import filters. The export filter's callback function is + used to indicate progress and update the status bar during the + export process. The function takes a value between 0.0 and 1.0, + where 0.0 represents the start of the export and 1.0 represents + the completion of the export. + + + As with the other plugin types, an export filter must be + registered with gramps. This is + accomplished by calling the + Plugins.register_export task. The + Plugins.register_export accepts two arguments + — the function the performs the import and a string + providing a brief description. This description is used as the + menu entry under the + + File + Export + + menu. + +
+ Sample Export Implementation + + +import Plugins + +def gedcom_export(database,filename,callback): + ... actual code ... + +Plugins.register_export(gedcom_export,"GEDCOM export") + + +
+
+ + Common tasks + + While this manual does not document the + gramps database interface, this section + shows a few common tasks. + + + Printing names of people + + This example shows how to display the name of people in the + database. It assumes that the database is called + db. To get a list of people, it calls the + getPersonMap method, which returns a map of + gramps ID to + Person objects. Calling the + valus method of the returned map returns a + list of people. For each person, the primary name is extracted, + and then the Name object's + getName method is called to build a + presentable name from the individual name components. + +
+ Displaying names + + +for person in db.getPersonMap().values(): + name = person.getPrimaryName() + print name.getName() + + +
+
+ + Displaying the events of person + + This example shows how to display the public events associated + with a person. It assumes that the person is called + person. + +
+ Displaying Event Information + + +for event in person.getEventList(): + if event.getPrivacy() == 0: + print "Event:",event.getName() + print "Date:",event.getDate() + print "Place:",event.getPlaceName() + + +
+
+ + Print the members of each family + + This example shows how to display the parents and children of + each family in the database. It assumes that the database is called + db. + +
+ Displaying Family Information + + +for family in db.getFamilyMap().values: + print "-------------------" + print "Family ID:",family.getId() + father = family.getFather() + if father != None: + print "Father:",father.getPrimaryName().getName() + mother = family.getMother() + if mother != None: + print "Mother:",mother.getPrimaryName().getName() + for child in family.getChildList(): + print "Child:",child.getPrimaryName().getName() + + +
+
+ + Display the marriages/relationships of a person + + This example shows how to display the families and relationships + in which the person is considered a spouse or parent. It assumes + that the person is called person. + + + Relationships between people can be complex. Because someone is + male, does not necessarily mean that the person will be + considered the "Father" of a relationship. In relationships of + type "Partners", the "father" and "mother" of the relationship + should be of the same gender. So to determine the spouse of a + person, it is usually best to compare the person against what is + returned by getFather and + getMother to find the one that is not + equal. It should also be noted that the + getFather and + getMother methods will return None if noone + has been associated with that role in the family. + +
+ Displaying Relationship Information + + +for family in person.getFamilyList(): + print "-------------------" + print "Family ID:",family.getId() + print "Relationship Type:",family.getRelationship() + father = family.getFather() + if father != None and father != person: + print "Spouse:",father.getPrimaryName().getName() + mother = family.getMother() + if mother != None and mother != person: + print "Spouse:",mother.getPrimaryName().getName() + + +
+
+
+ + + + + Authors + + gramps was written by Don Allingham + (dallingham@users.sourceforge.net). To find more + information about gramps, please visit + the gramps + web page. + + + This manual was written by Don Allingham + (dallingham@users.sourceforge.net). + + + + + + + + + License + + 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. + + + A copy of the GNU General Public License is + included as an appendix to the GNOME Users + Guide. You may also obtain a copy of the + GNU General Public License from the Free + Software Foundation by visiting their Web site or by writing to +
+ Free Software Foundation, Inc. 59 Temple Place - + Suite 330 Boston, MA + 02111-1307 USA +
+
+
+
+ + + + + + + + + diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/index.html b/gramps2/doc/extending-gramps/C/extending-gramps/index.html new file mode 100644 index 000000000..42274a813 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/index.html @@ -0,0 +1,345 @@ + +Writing Extentions for gramps

Writing Extentions for gramps

Copyright © 2001 by Donald N. Allingham


+ + + +

Introduction

+

gramps was intended from the start to + allow the user to extend it through a plugin system. Five types of + plugins are supported - filters, reports, tools, import filters, + and export filters. In a way, an export filter can be viewed as a + special type of report, and an import filter can be viewed as a + special type of tool. +

+

All plugins are written in the python + language. +

+
+ + + + +
+ + + + + + + + + + + + + + +

  Next >>>
  Writing Filters
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/ln7.html b/gramps2/doc/extending-gramps/C/extending-gramps/ln7.html new file mode 100644 index 000000000..507e5597e --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/ln7.html @@ -0,0 +1,133 @@ + +
Writing Extentions for gramps

Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation + License, 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 here. +

+

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. +

+


 Home 
 Up 
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/caution.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/caution.gif new file mode 100644 index 000000000..542232911 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/caution.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/home.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/home.gif new file mode 100644 index 000000000..55e1d5993 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/home.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/important.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/important.gif new file mode 100644 index 000000000..8793ff2b1 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/important.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/next.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/next.gif new file mode 100644 index 000000000..ceb93e120 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/next.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/note.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/note.gif new file mode 100644 index 000000000..45fe08649 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/note.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/prev.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/prev.gif new file mode 100644 index 000000000..0894d9ecb Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/prev.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/tip.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/tip.gif new file mode 100644 index 000000000..025819548 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/tip.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-blank.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-blank.gif new file mode 100644 index 000000000..6c65e3a19 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-blank.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-minus.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-minus.gif new file mode 100644 index 000000000..40ebe61e4 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-minus.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-plus.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-plus.gif new file mode 100644 index 000000000..3e9e7d55a Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/toc-plus.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/up.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/up.gif new file mode 100644 index 000000000..603c4ce24 Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/up.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/warning.gif b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/warning.gif new file mode 100644 index 000000000..9c1104c2b Binary files /dev/null and b/gramps2/doc/extending-gramps/C/extending-gramps/stylesheet-images/warning.gif differ diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/t1.html b/gramps2/doc/extending-gramps/C/extending-gramps/t1.html new file mode 100644 index 000000000..42274a813 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/t1.html @@ -0,0 +1,345 @@ + +Writing Extentions for gramps

Writing Extentions for gramps

Copyright © 2001 by Donald N. Allingham


+ + + +

Introduction

+

gramps was intended from the start to + allow the user to extend it through a plugin system. Five types of + plugins are supported - filters, reports, tools, import filters, + and export filters. In a way, an export filter can be viewed as a + special type of report, and an import filter can be viewed as a + special type of tool. +

+

All plugins are written in the python + language. +

+
+ + + + +
+ + + + + + + + + + + + + + +

  Next >>>
  Writing Filters
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/x131.html b/gramps2/doc/extending-gramps/C/extending-gramps/x131.html new file mode 100644 index 000000000..59d008e61 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/x131.html @@ -0,0 +1,282 @@ + +Writing Tools
Writing Extentions for gramps
<<< PreviousNext >>>

Writing Tools

+

Users can create their own tools and add them to + gramps. By adding the tool to the + user's private plugin directory (~/.gramps/plugins), the tool will be + automatically recognized the next time that + gramps is started. +

+

Unlike a report generator, a tool is allowed to modify the + database. The tool is passed the current + gramps database, the active person, + and a callback function. The callback function should be called + with a non-zero argument upon completion of the tool if the + database has been altered. +

+

As with filters and report generators, tools must be registered + before gramps will understand it. The + tool is registered using the + Plugins.register_tool. This function takes + four arguments. +

+

  • The tool task This task + that executes the tool. +

    +
  • The tool category The category in which + the tool is grouped in the + Tools menu and in + the Tool Selection dialog. +

    +
  • The tool name + The name of the tool. +

    +
  • A text description of the tool The + description appears in the Tool Selection dialog to provide + the user with a description of what the tool does. +

    +
+

While only the task and report name are required, it is + recommended to provide all five parameters. +

+
+

<<< PreviousHomeNext >>>
Writing Reports Writing Import Filters
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/x162.html b/gramps2/doc/extending-gramps/C/extending-gramps/x162.html new file mode 100644 index 000000000..790ff3932 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/x162.html @@ -0,0 +1,219 @@ + +Writing Import Filters
Writing Extentions for gramps
<<< PreviousNext >>>

Writing Import Filters

+

Import filters are similar to tools, since they are allowed to + modify the databases. An import filter is a task that accepts + three arguments a database, the filename of the file that + is to be imported, and a callback function. +

+

The database may or may not have data already in it. The import + filter cannot assume that data neither already exists nor that the + database is empty. +

+

The callback function is different from the callback function used + for tools. The import filter's callback function is used to + indicate progress and update the status bar during the import + process. The function takes a value between 0.0 and 1.0, where 0.0 + represents the start of the import and 1.0 represents the + completion of the import. +

+

As with the other plugin types, an import filter must be + registered with gramps. This is + accomplished by calling the + Plugins.register_import task. The + Plugins.register_import accepts two arguments + the function the performs the import and a string + providing a brief description. This description is used as the + menu entry under the + + + + + + +File+ ++ + + + + + ->Import+ ++ + + + + menu. +

+
+

<<< PreviousHomeNext >>>
Writing Tools Writing Export Filters
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/x177.html b/gramps2/doc/extending-gramps/C/extending-gramps/x177.html new file mode 100644 index 000000000..6654c0a36 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/x177.html @@ -0,0 +1,180 @@ + +Writing Export Filters
Writing Extentions for gramps
<<< Previous 

Writing Export Filters

+

Export filters are similar to report generators. They are not + allowed to modify the database. An export filter accepts three + arguments a database, the filename of the file that is to + be written, and a callback function. +

+

The callback function is indentical from the callback function + used for import filters. The export filter's callback function is + used to indicate progress and update the status bar during the + export process. The function takes a value between 0.0 and 1.0, + where 0.0 represents the start of the export and 1.0 represents + the completion of the export. +

+

As with the other plugin types, an export filter must be + registered with gramps. This is + accomplished by calling the + Plugins.register_export task. The + Plugins.register_export accepts two arguments + the function the performs the import and a string + providing a brief description. This description is used as the + menu entry under the + + + + + + +File+ ++ + + + + + ->Export+ ++ + + + + menu. +

+

<<< PreviousHome 
Writing Import Filters  
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/x57.html b/gramps2/doc/extending-gramps/C/extending-gramps/x57.html new file mode 100644 index 000000000..52c5b09db --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/x57.html @@ -0,0 +1,276 @@ + +Writing Filters
Writing Extentions for gramps
<<< PreviousNext >>>

Writing Filters

+

Users can create their own filters and add them to + gramps. By adding the filter to the + user's private filter directory (~/.gramps/filters), the filter will + be automatically recognized the next time that the program is + started. +

+

Creating a filter

+

Each filter is a class derived from the + Filter.Filter class. The + __init__ task may be overridden, but if so, + should call the __init__ function on the + Filter.Filter class. The parent class + provides the variable self.text, which + contains the text string passed as the qualifier. This string + provides additional information provided by the user. For + example, if the filter is used to match names, the qualifier + would be used to provide the name that is being compared + against. +

+

All filter classes must define a match + function. The function takes one argument (other than + self), which is an object of type + Person to compare against. The function + should return a 1 if the person matches the filter, or a zero if + the person does not. +

+

Each filter must be registered, so that + gramps knows about it. This is + accomplished by calling the + Filter.register_filter function. This + function takes three arguments - the filter class, a + description, and flag that indicates if the qualifier string is + needed. The description string appears in the pull down + interface within gramps, and helps + the user choose the appropriate filter. The qualifier flag tells + gramps whether or not the filter + needs a qualifier string. If this flag is 0, + gramps will disable the entry of a + qualifier string. +

+
+
+

<<< PreviousHomeNext >>>
Writing Extentions for gramps Writing Reports
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/extending-gramps/x83.html b/gramps2/doc/extending-gramps/C/extending-gramps/x83.html new file mode 100644 index 000000000..1faa64d78 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/extending-gramps/x83.html @@ -0,0 +1,369 @@ + +Writing Reports
Writing Extentions for gramps
<<< PreviousNext >>>

Writing Reports

+

Users can create their own report generators and add them to + gramps. By adding the report generator + to the user's private plugin directory (~/.gramps/plugins), the report + generator will be automatically recognized the next time that the + program is started. +

+

Creating a report generator

+

Fewer restrictions are made on report generators than on + filters. The report generator is passed the current + gramps database and the active + person. The generator needs to take special care to make sure + that it does not alter the database in anyway. +

+

A report generator is a function that takes two arguments + a database (of type RelDataBase) + and the currently selected person (of type + Person). When called, this task should + generate the desired report. +

+

This function's implementation can be as simple as generating + output without the user's intervention, or it could display a + graphical interface to allow the user to select options and + customize a report. +

+

As with filters, the report generator must be registered before + gramps will understand it. The report + generator is registered using the + Plugins.register_report. This function + takes five arguments. +

+

  • The report generation task This task + that generates the report. +

    +
  • The report category The category in + which the report is grouped in the + Reports menu and + in the Report Selection dialog. +

    +
  • The report name + The name of the report. +

    +
  • A text description of the report The + description appears in the report selection tool to provide + the user with a description of what the tools does. +

    +
  • A graphic logo in XPM format This may + be either a path to a filename, or a list of strings + containting the XPM data. If a filename is specified, care + must be taken to make sure the file location is relocatable + and can be determined at runtime. +

    +
+

While only the task and report name are required, it is + recommended to provide all five parameters. +

+
+
+

A little help - Format Interfaces

+

gramps provides some help with + writing reports. Several generic python classes exist that aid + in the writing of report generators. These classes provide an + abstract interface for a type of document, such as a drawing, + word processor document, or a spreadsheet. From these core + classes, gramps derives interfaces to + various document formats. This means that by coding to the + generic word processing class (TextDoc), a + report generator can instant access to multiple file formats + (such as HTML, OpenOffice, and AbiWord). +

+

This scheme of deriving a output format from a generic base + class also makes it easier to add new formats. Creating a new + derivied class targeting a different format (such as + KWord or + LaTeX) makes it easy for existing + report generators to use the new formats. +

+
+

<<< PreviousHomeNext >>>
Writing Filters Writing Tools
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/index.html b/gramps2/doc/extending-gramps/C/index.html new file mode 100644 index 000000000..42274a813 --- /dev/null +++ b/gramps2/doc/extending-gramps/C/index.html @@ -0,0 +1,345 @@ + +Writing Extentions for gramps

Writing Extentions for gramps

Copyright © 2001 by Donald N. Allingham


+ + + +

Introduction

+

gramps was intended from the start to + allow the user to extend it through a plugin system. Five types of + plugins are supported - filters, reports, tools, import filters, + and export filters. In a way, an export filter can be viewed as a + special type of report, and an import filter can be viewed as a + special type of tool. +

+

All plugins are written in the python + language. +

+
+ + + + +
+ + + + + + + + + + + + + + +

  Next >>>
  Writing Filters
\ No newline at end of file diff --git a/gramps2/doc/extending-gramps/C/omf_timestamp b/gramps2/doc/extending-gramps/C/omf_timestamp new file mode 100644 index 000000000..e69de29bb diff --git a/gramps2/doc/extending-gramps/Makefile.am b/gramps2/doc/extending-gramps/Makefile.am new file mode 100644 index 000000000..dbed85073 --- /dev/null +++ b/gramps2/doc/extending-gramps/Makefile.am @@ -0,0 +1,4 @@ +# Process this file with automake to produce Makefile.in + +SUBDIRS = C + diff --git a/gramps2/doc/extending-gramps/Makefile.in b/gramps2/doc/extending-gramps/Makefile.in new file mode 100644 index 000000000..1a6b4eceb --- /dev/null +++ b/gramps2/doc/extending-gramps/Makefile.in @@ -0,0 +1,352 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to produce Makefile.in +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ + +SUBDIRS = C +subdir = doc/extending-gramps +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/extending-gramps/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive distclean distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive tags tags-recursive uninstall \ + uninstall-am uninstall-info-am uninstall-info-recursive \ + uninstall-recursive + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/doc/gramps-manual/C/Makefile.am b/gramps2/doc/gramps-manual/C/Makefile.am new file mode 100644 index 000000000..dde918710 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/Makefile.am @@ -0,0 +1,53 @@ +SGML_FILES = gramps-manual.sgml + +figs = \ + figures/addmedia.png \ + figures/druidpg1.png \ + figures/editbookmarks.png \ + figures/ep-address.png \ + figures/ep-altname.png \ + figures/ep-attributes.png \ + figures/ep-event.png \ + figures/ep-gallery.png \ + figures/ep-general.png \ + figures/ep-internet.png \ + figures/ep-lds.png \ + figures/ep-notes.png \ + figures/familyview.png \ + figures/filter.png \ + figures/globalmedia.png \ + figures/gotobookmark.png \ + figures/localmedia.png \ + figures/mainwin.png \ + figures/mediaview.png \ + figures/opendb.png \ + figures/pedegreesel.png \ + figures/pedegreeview.png \ + figures/peoplelist.png \ + figures/placelist.png \ + figures/prefs-bars.png \ + figures/prefs-colors.png \ + figures/prefs-dates.png \ + figures/prefs-disp.png \ + figures/prefs-find.png \ + figures/prefs-gen.png \ + figures/prefs-guess.png \ + figures/prefs-ids.png \ + figures/prefs-main.png \ + figures/prefs-media.png \ + figures/prefs-report.png \ + figures/prefs-research.png \ + figures/prefs-revision.png \ + figures/reportsel.png \ + figures/revcontrol.png \ + figures/savecomment.png \ + figures/sourcelist.png \ + figures/sourcerefsel.png \ + figures/toolsel.png + +docname = gramps-manual +lang = C +omffile = gramps-manual-C.omf +sgml_ents = +include $(top_srcdir)/doc/sgmldocs.make +dist-hook: app-dist-hook diff --git a/gramps2/doc/gramps-manual/C/Makefile.in b/gramps2/doc/gramps-manual/C/Makefile.in new file mode 100644 index 000000000..e946dd85d --- /dev/null +++ b/gramps2/doc/gramps-manual/C/Makefile.in @@ -0,0 +1,461 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# To use this template: +# 1) Define: figs, docname, lang, omffile, sgml_ents although figs, +# omffile, and sgml_ents may be empty in your Makefile.am which +# will "include" this one +# 2) Figures must go under figures/ and be in PNG format +# 3) You should only have one document per directory +# +# Note that this makefile forces the directory name under +# $prefix/share/gnome/help/ to be the same as the SGML filename +# of the document. This is required by GNOME. eg: +# $prefix/share/gnome/help/fish_applet/C/fish_applet.sgml +# ^^^^^^^^^^^ ^^^^^^^^^^^ +# Definitions: +# figs A list of screenshots which will be included in EXTRA_DIST +# Note that these should reside in figures/ and should be .png +# files, or you will have to make modifications below. +# docname This is the name of the SGML file: .sgml +# lang This is the document locale +# omffile This is the name of the OMF file. Convention is to name +# it -.omf. +# sgml_ents This is a list of SGML entities which must be installed +# with the main SGML file and included in EXTRA_DIST. +# eg: +# figs = \ +# figures/fig1.png \ +# figures/fig2.png +# docname = scrollkeeper-manual +# lang = C +# omffile=scrollkeeper-manual-C.omf +# sgml_ents = fdl.sgml +# include $(top_srcdir)/help/sgmldocs.make +# dist-hook: app-dist-hook +# +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +SGML_FILES = gramps-manual.sgml + +figs = \ + figures/addmedia.png \ + figures/druidpg1.png \ + figures/editbookmarks.png \ + figures/ep-address.png \ + figures/ep-altname.png \ + figures/ep-attributes.png \ + figures/ep-event.png \ + figures/ep-gallery.png \ + figures/ep-general.png \ + figures/ep-internet.png \ + figures/ep-lds.png \ + figures/ep-notes.png \ + figures/familyview.png \ + figures/filter.png \ + figures/globalmedia.png \ + figures/gotobookmark.png \ + figures/localmedia.png \ + figures/mainwin.png \ + figures/mediaview.png \ + figures/opendb.png \ + figures/pedegreesel.png \ + figures/pedegreeview.png \ + figures/peoplelist.png \ + figures/placelist.png \ + figures/prefs-bars.png \ + figures/prefs-colors.png \ + figures/prefs-dates.png \ + figures/prefs-disp.png \ + figures/prefs-find.png \ + figures/prefs-gen.png \ + figures/prefs-guess.png \ + figures/prefs-ids.png \ + figures/prefs-main.png \ + figures/prefs-media.png \ + figures/prefs-report.png \ + figures/prefs-research.png \ + figures/prefs-revision.png \ + figures/reportsel.png \ + figures/revcontrol.png \ + figures/savecomment.png \ + figures/sourcelist.png \ + figures/sourcerefsel.png \ + figures/toolsel.png + + +docname = gramps-manual +lang = C +omffile = gramps-manual-C.omf +sgml_ents = + +docdir = $(datadir)/gnome/help/$(docname)/$(lang) + +doc_DATA = index.html + +sgml_files = $(sgml_ents) $(docname).sgml + +omf_dir = $(top_srcdir)/omf-install + +EXTRA_DIST = $(sgml_files) $(doc_DATA) $(omffile) $(figs) + +CLEANFILES = omf_timestamp + +# when doing a distclean, we also want to clear out html files: +CONFIG_CLEAN_FILES = index.html $(docname)/*.html $(docname)/stylesheet-images/*.gif +subdir = doc/gramps-manual/C +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +DIST_SOURCES = +DATA = $(doc_DATA) + +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/doc/sgmldocs.make $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/gramps-manual/C/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: +docDATA_INSTALL = $(INSTALL_DATA) +install-docDATA: $(doc_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(docdir) + @list='$(doc_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f"; \ + $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f; \ + done + +uninstall-docDATA: + @$(NORMAL_UNINSTALL) + @list='$(doc_DATA)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(docdir)/$$f"; \ + rm -f $(DESTDIR)$(docdir)/$$f; \ + done +tags: TAGS +TAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + $(mkinstalldirs) $(distdir)/figures + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="${top_distdir}" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile $(DATA) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(docdir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: install-docDATA + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-docDATA uninstall-info-am uninstall-local + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-docDATA \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic uninstall uninstall-am \ + uninstall-docDATA uninstall-info-am uninstall-local + + +all: index.html omf + +omf: omf_timestamp + +omf_timestamp: $(omffile) + -for file in $(omffile); do \ + scrollkeeper-preinstall $(docdir)/$(docname).sgml $$file $(omf_dir)/$$file; \ + done + touch omf_timestamp + +index.html: $(docname)/index.html + -cp $(docname)/index.html . + +# The weird srcdir trick is because the db2html from the Cygnus RPMs +# cannot handle relative filenames. +# The t1 test is for certain versions of jw that create cryptic +# html pages, o fwhich the index is called "t1". Also, the jw +# script from docbook-utils 0.6.9 does not copy the template +# stylesheet-images directory like the db2html script does, so +# we give it a little help (at least for now) + +$(docname)/index.html: $(docname).sgml + -srcdir=`cd $(srcdir) && pwd`; \ + if test "$(HAVE_JW)" = 'yes' ; then \ + if test -f /usr/share/sgml/docbook/dsssl-stylesheets/images/next.gif ; then \ + mkdir -p $$srcdir/$(docname)/stylesheet-images ; \ + cp /usr/share/sgml/docbook/dsssl-stylesheets/images/*.gif $$srcdir/$(docname)/stylesheet-images/ ; \ + fi; \ + jw -c /etc/sgml/catalog $$srcdir/$(docname).sgml -o $$srcdir/$(docname); \ + else \ + db2html $$srcdir/$(docname).sgml; \ + fi + if test -f $(docname)/t1.html; then \ + cd $(srcdir)/$(docname) && cp t1.html index.html; \ + cd $(srcdir); \ + fi + +$(docname).sgml: $(sgml_ents) + -ourdir=`cd . && pwd`; \ + cd $(srcdir); \ + cp $(sgml_ents) $$ourdir + +app-dist-hook: index.html + -$(mkinstalldirs) $(distdir)/$(docname)/stylesheet-images + -$(mkinstalldirs) $(distdir)/figures + -cp $(srcdir)/$(docname)/*.html $(distdir)/$(docname) + -for file in $(srcdir)/$(docname)/*.css; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + cp $$file $(distdir)/$(docname)/$$basefile ; \ + done + -for file in $(srcdir)/$(docname)/stylesheet-images/*.gif; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + cp $$file $(distdir)/$(docname)/stylesheet-images/$$basefile ; \ + done + -if [ -e topic.dat ]; then \ + cp $(srcdir)/topic.dat $(distdir); \ + fi + +install-data-am: index.html omf + -$(mkinstalldirs) $(DESTDIR)$(docdir)/stylesheet-images + -$(mkinstalldirs) $(DESTDIR)$(docdir)/figures + -cp $(srcdir)/$(sgml_files) $(DESTDIR)$(docdir) + -for file in $(srcdir)/$(docname)/*.html $(srcdir)/$(docname)/*.css; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/$$basefile; \ + done + -for file in $(srcdir)/figures/*.png; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/figures/$$basefile; \ + done + -for file in $(srcdir)/$(docname)/stylesheet-images/*.gif; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/stylesheet-images/$$basefile; \ + done + -if [ -e $(srcdir)/topic.dat ]; then \ + $(INSTALL_DATA) $(srcdir)/topic.dat $(DESTDIR)$(docdir); \ + fi + +$(docname).ps: $(srcdir)/$(docname).sgml + -srcdir=`cd $(srcdir) && pwd`; \ + db2ps $$srcdir/$(docname).sgml + +$(docname).rtf: $(srcdir)/$(docname).sgml + -srcdir=`cd $(srcdir) && pwd`; \ + db2ps $$srcdir/$(docname).sgml + +uninstall-local: + -for file in $(srcdir)/$(docname)/stylesheet-images/*.gif; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + rm -f $(docdir)/stylesheet-images/$$basefile; \ + done + -for file in $(srcdir)/figures/*.png; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + rm -f $(docdir)/figures/$$basefile; \ + done + -for file in $(srcdir)/$(docname)/*.html $(srcdir)/$(docname)/*.css; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + rm -f $(DESTDIR)$(docdir)/$$basefile; \ + done + -for file in $(sgml_files); do \ + rm -f $(DESTDIR)$(docdir)/$$file; \ + done + -rmdir $(DESTDIR)$(docdir)/stylesheet-images + -rmdir $(DESTDIR)$(docdir)/figures + -rmdir $(DESTDIR)$(docdir) +dist-hook: app-dist-hook +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/doc/gramps-manual/C/figures/addmedia.png b/gramps2/doc/gramps-manual/C/figures/addmedia.png new file mode 100644 index 000000000..312823bcc Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/addmedia.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/druidpg1.png b/gramps2/doc/gramps-manual/C/figures/druidpg1.png new file mode 100644 index 000000000..517490d48 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/druidpg1.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/editbookmarks.png b/gramps2/doc/gramps-manual/C/figures/editbookmarks.png new file mode 100644 index 000000000..e02bed7b0 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/editbookmarks.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-address.png b/gramps2/doc/gramps-manual/C/figures/ep-address.png new file mode 100644 index 000000000..4b31b8f6f Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-address.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-altname.png b/gramps2/doc/gramps-manual/C/figures/ep-altname.png new file mode 100644 index 000000000..2aaa1a528 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-altname.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-attributes.png b/gramps2/doc/gramps-manual/C/figures/ep-attributes.png new file mode 100644 index 000000000..73a15083d Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-attributes.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-event.png b/gramps2/doc/gramps-manual/C/figures/ep-event.png new file mode 100644 index 000000000..6d43d6c04 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-event.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-gallery.png b/gramps2/doc/gramps-manual/C/figures/ep-gallery.png new file mode 100644 index 000000000..0a0810a9b Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-gallery.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-general.png b/gramps2/doc/gramps-manual/C/figures/ep-general.png new file mode 100644 index 000000000..212b067fa Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-general.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-internet.png b/gramps2/doc/gramps-manual/C/figures/ep-internet.png new file mode 100644 index 000000000..072f88645 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-internet.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-lds.png b/gramps2/doc/gramps-manual/C/figures/ep-lds.png new file mode 100644 index 000000000..ef7ef2990 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-lds.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/ep-notes.png b/gramps2/doc/gramps-manual/C/figures/ep-notes.png new file mode 100644 index 000000000..739d5ae5b Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/ep-notes.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/familyview.png b/gramps2/doc/gramps-manual/C/figures/familyview.png new file mode 100644 index 000000000..fc10f5cbb Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/familyview.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/filter.png b/gramps2/doc/gramps-manual/C/figures/filter.png new file mode 100644 index 000000000..5b9a8faf5 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/filter.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/globalmedia.png b/gramps2/doc/gramps-manual/C/figures/globalmedia.png new file mode 100644 index 000000000..e4304f10e Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/globalmedia.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/gotobookmark.png b/gramps2/doc/gramps-manual/C/figures/gotobookmark.png new file mode 100644 index 000000000..f6c724d93 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/gotobookmark.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/localmedia.png b/gramps2/doc/gramps-manual/C/figures/localmedia.png new file mode 100644 index 000000000..b7a6f54cd Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/localmedia.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/mainwin.png b/gramps2/doc/gramps-manual/C/figures/mainwin.png new file mode 100644 index 000000000..36fab7a46 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/mainwin.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/mediaview.png b/gramps2/doc/gramps-manual/C/figures/mediaview.png new file mode 100644 index 000000000..3080d73fb Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/mediaview.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/opendb.png b/gramps2/doc/gramps-manual/C/figures/opendb.png new file mode 100644 index 000000000..839c61815 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/opendb.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/pedegreesel.png b/gramps2/doc/gramps-manual/C/figures/pedegreesel.png new file mode 100644 index 000000000..bb675e0bd Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/pedegreesel.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/pedegreeview.png b/gramps2/doc/gramps-manual/C/figures/pedegreeview.png new file mode 100644 index 000000000..f29b00efb Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/pedegreeview.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/peoplelist.png b/gramps2/doc/gramps-manual/C/figures/peoplelist.png new file mode 100644 index 000000000..df634a556 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/peoplelist.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/placelist.png b/gramps2/doc/gramps-manual/C/figures/placelist.png new file mode 100644 index 000000000..7569313af Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/placelist.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-bars.png b/gramps2/doc/gramps-manual/C/figures/prefs-bars.png new file mode 100644 index 000000000..cd8bad394 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-bars.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-colors.png b/gramps2/doc/gramps-manual/C/figures/prefs-colors.png new file mode 100644 index 000000000..1c1fe960e Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-colors.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-dates.png b/gramps2/doc/gramps-manual/C/figures/prefs-dates.png new file mode 100644 index 000000000..fd21ddbea Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-dates.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-disp.png b/gramps2/doc/gramps-manual/C/figures/prefs-disp.png new file mode 100644 index 000000000..fbbf42268 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-disp.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-find.png b/gramps2/doc/gramps-manual/C/figures/prefs-find.png new file mode 100644 index 000000000..f0f31dcf0 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-find.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-gen.png b/gramps2/doc/gramps-manual/C/figures/prefs-gen.png new file mode 100644 index 000000000..6bfce4793 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-gen.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-guess.png b/gramps2/doc/gramps-manual/C/figures/prefs-guess.png new file mode 100644 index 000000000..5ad52ac3f Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-guess.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-ids.png b/gramps2/doc/gramps-manual/C/figures/prefs-ids.png new file mode 100644 index 000000000..5522b155a Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-ids.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-main.png b/gramps2/doc/gramps-manual/C/figures/prefs-main.png new file mode 100644 index 000000000..f18cd467a Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-main.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-media.png b/gramps2/doc/gramps-manual/C/figures/prefs-media.png new file mode 100644 index 000000000..8a165cfb9 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-media.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-report.png b/gramps2/doc/gramps-manual/C/figures/prefs-report.png new file mode 100644 index 000000000..613214d76 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-report.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-research.png b/gramps2/doc/gramps-manual/C/figures/prefs-research.png new file mode 100644 index 000000000..c7b80e812 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-research.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/prefs-revision.png b/gramps2/doc/gramps-manual/C/figures/prefs-revision.png new file mode 100644 index 000000000..f52b63faa Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/prefs-revision.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/reportsel.png b/gramps2/doc/gramps-manual/C/figures/reportsel.png new file mode 100644 index 000000000..eb016fd6e Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/reportsel.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/revcontrol.png b/gramps2/doc/gramps-manual/C/figures/revcontrol.png new file mode 100644 index 000000000..a6046ad22 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/revcontrol.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/savecomment.png b/gramps2/doc/gramps-manual/C/figures/savecomment.png new file mode 100644 index 000000000..f16abbf4d Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/savecomment.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/sourcelist.png b/gramps2/doc/gramps-manual/C/figures/sourcelist.png new file mode 100644 index 000000000..1d4c0e364 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/sourcelist.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/sourcerefsel.png b/gramps2/doc/gramps-manual/C/figures/sourcerefsel.png new file mode 100644 index 000000000..68a782ddc Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/sourcerefsel.png differ diff --git a/gramps2/doc/gramps-manual/C/figures/toolsel.png b/gramps2/doc/gramps-manual/C/figures/toolsel.png new file mode 100644 index 000000000..c4142f161 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/figures/toolsel.png differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual-C.omf b/gramps2/doc/gramps-manual/C/gramps-manual-C.omf new file mode 100644 index 000000000..057a9f63d --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual-C.omf @@ -0,0 +1,14 @@ + + + + + GRAMPS User Manual + + + GNOME|Applications + + + + + + diff --git a/gramps2/doc/gramps-manual/C/gramps-manual.sgml b/gramps2/doc/gramps-manual/C/gramps-manual.sgml new file mode 100644 index 000000000..61993dd57 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual.sgml @@ -0,0 +1,1863 @@ + +]> + + + +
+ + + GRAMPS User Manual + + 2001 + Donald N. Allingham + + + + + + + + + + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation + License, 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 here. + + + 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. + + + + + + + + + + + + + + + + + + + + This is version 1.1 of the GRAMPS manual. + + + + + + + + + Introduction + + 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. + + + To run GRAMPS, select + + Programs + Applications + gramps + + from the Main Menu, or type + gramps on the command line. + + + This document describes version &version; of + GRAMPS. + + + + + + + + Running GRAMPS for the first time. + + The first time you run the program, + GRAMPS will display its Getting Started + screens. + +
+ Getting Started screen, page 1 + + Getting Started screen, page 1 + + + +
+ + GRAMPS will guide you through a few pages + that prompt you for some setup information. The information it requests + includes information about yourself and your preferences. + + + Although GRAMPS requests information about + your, this information is used only so that it can create valid GEDCOM + output files. A valid GEDCOM file requires information about the file"s + creator. If you chose, you may leave the information empty. + +
+ + + Getting Started + + Starting GRAMPS opens the + Main window, shown in . You will be prompted to either open an + existing database, or to create a new + database. GRAMPS requires that a + database always be open. + +
+ GRAMPS Main Window + + GRAMPS Main Window + + + +
+ + Importing data + + If you already have a family file created using another + genealogy program you can import your GEDCOM file into GRAMPS. + To do this you select File + Import Import from + GEDCOM . The GEDCOM + Import box will open. Select New + Database and click the + Browse... button to select your saved + GEDCOM file (filename.ged). Click + OK to select the file and then click + OK to import the file. The + GEDCOM Import Status will tell you what + the importer is doing and a little bit about your file (file + location, which program created it, the version, Encoding, + Number of Families, Number of People, and the Number of Errors). + Once the Importer is done, you can click + Close and start editing/adding to your + file. + + + + Entering Data + + If you have never used a genealogy program or you do not have a + GEDCOM file to import, you can start creating your database + right away. From the main window click the Add + Person button and the Edit + Person dialog will open. Enter in the information + you have on the first person. Start with their general + information (Name, Birth and Death Date/Place) and then move on + to the Names, + Events, + Attributes, + Addresses, Notes, + Gallery, and + Internet tabs and fill in the known + information you have. Some of the information you enter has a + Source button and/or a + Note button. These buttons are there to + add more information (Source button to + add the source of where you acquired the information and the + Note button to add more detail to the + information) + + +
+ + + + + People View + + The People View window is the initial view seen on the main + window. It displays the name, gender, birth date, and death + date of all individuals in the database. At any time, you can + return to this view either by pressing the + People button at the top of the screen, or + by choosing the + + View + People + + entry from the menus. + +
+ People View + + People View + + + +
+ + Selecting and Editing Individuals + + The People View lists the individuals in the database. An + individual can be selected as the active person by clicking on + an entry in the list. Once a person has been selected as the + active person, the person's name appears in the status bar in + the lower left hand corner of the window. + + + Once the active person has been selected, pressing the + Edit Person button will display the + Edit Person dialog allowing you to edit + the individual's personal information. If the Edit + Person button is pressed without an active person + being set, a blank Edit Person dialog is + presented, allowing you to enter a new person. + + + Double-clicking on a entry in the list will set the active + person and bring up the individual in the Edit + Person dialog. + + + Pressing the Add Person button will + display a blank Edit Person dialog, + allowing you to add a new person to the database. + + + If the Delete Person button is pressed, + the active person and all of the personal information related to + the active person are removed from the database. + + + + Applying Filters + + GRAMPS allows you to apply filters to + the People View. When a filter is applied, the People View will + only display the entries matching the filter. All of the entries + remain in the database, but some entries may be temporarily hidden. + + + There are up to three parts to a filter. The first part is the + selection of the filter to be applied. A filter is selected from + the option menu directly above the People View. The second part + is an optional argument. This qualifier provides more specific + information for the filter. Many filters do not require the + argument, and it will not be displayed if it is not needed. If + the argument is required, a text box with a descriptive label + will appear. The third part of the filter is the invert + selection. When this option is selected, + GRAMPS will display the entries that + do not match the filter. + +
+ Filter that requires an argument + + Filter that requires an argument + + + +
+ + A filter is not applied until the Apply + button is pressed. The filter will remain in effect until the + next time the Apply button is pressed. + +
+ + Sorting + + Four columns are shown in the People View display. The entries + in the list can be sorted by three of the fields: Name, Birth + Date, or Death Date. Clicking on the column label will cause + the list to be re-sorted by that column. Arrows on the label + indicate whether the list is sorted by ascending or descending + order. + + + If the list is already sorted by a particular column, clicking + on the same column label will switch the sorting order. For + example, if the list is currently sorted in ascending order by + Name, clicking on the Name column header will re-sort the list + in descending order. + + +
+ + Editing a person's data + + A person's personal information can be edited in the + Edit Person dialog. + + + General Information Tab +
+ General Information Tab + + General Information Tab + + + +
+ + The General Information tab contains the basic information about + the person. This includes the person's name, gender, birth + information, and death information. + + + If images have been associated with the person, the primary + image is displayed on the right side of the window. + +
+ + Alternate Names Tab +
+ Alternate Names Tab + + Alternate Names Tab + + + +
+ + It is possible for people to use more than one name during their + lifetime. These may be legal name changes, or just informal + names. An example would be a person changing his or her name due + to marriage or adoption. GRAMPS + allows multiple alternate names to be specified for each person. + + + The Alternate Names tab allows additional + names to be added or removed from list. Clicking the + Add button allows a new name to be added + to the list. The Edit/View allows the + selected alternate name to be edited. The + Delete button removes the selected name. + +
+ + Events Tab + + The Events tab allows information about + various events in a person's life to be + recorded. GRAMPS provides a list of + common events, but allows you to name an event anything that you + choose. + + + An event consists of the name of an event (such as "Baptism" or + "Education"), a date or date range on which the event occurred, + the place where the event occurred, and a description of the + event. A note or a source may also be attached to the event. + +
+ Events Tab + + Events Tab + + + +
+ + The Event tab displays information about + the currently selected event at the top of the window. Below + this information is a list of the events that have been + previously entered. Clicking on one of the events in the list + selects the event, and displays its information at the top of + the window. + + + An event may be added by clicking the Add + button. This displays a form that allows you to enter the + information about the particular event. The + Edit/View button allows to view or to + alter the information of the currently displayed event. The + Delete button allows you to delete the + currently displayed event. + +
+ + Attributes Tab + + Attributes are similar to events, but are for information items + that do not necessarily have the concept of a place or a + date. An example would be a person's Social Security Number or + national origin. Attributes consist of an attribute name and its + value. + + + Like events, attributes may also have a note, source, privacy + marker, and confidence level associated with them. + +
+ Attributes Tab + + Attributes Tab + + + +
+ + The Attribute tab displays information + about the currently selected attribute at the top of the + window. Below this information is a list of the attributes that + have been previously entered. Clicking on one of the attributes + in the list selects the attribute, and displays its information at + the top of the window. + + + An attribute may be added by clicking the + Add button. This displays a form that + allows you to enter the information about the particular + attribute. The Edit/View button allows to + view or to alter the information of the currently displayed + attribute. The Delete button allows you to + delete the currently displayed attribute. + +
+ + Addresses Tab + + Addresses are used to record information about where a person + has lived. Addresses are different from + GRAMPS' concept of a place. An + address, as GRAMPS sees, it consists + of an equivalent of a mailing address and the date or date range + when the person lived at the address. + + + Like events and attributes, addresses may also have a note, + source, privacy marker, and confidence level associated with + them. + +
+ Addresses Tab + + Addresses Tab + + + +
+ + The Address tab displays information + about the currently selected address at the top of the + window. Below this information is a list of the addresses that + have been previously entered. Clicking on one of the addresses + in the list selects the address, and displays its information at + the top of the window. + + + An address may be added by clicking the + Add button. This displays a form that + allows you to enter the information about the particular + address. The Edit/View button allows to + view or to alter the information of the currently displayed + address. The Delete button allows you to + delete the currently displayed address. + +
+ + Notes Tab + + In addition to the notes that may be attached to any particular + event, attribute, or address, GRAMPS + has a generic note attached to the person. + +
+ Notes Tab + + Notes Tab + + + +
+ + The note window is a free-form edit window, allowing you to + enter any information that you want. + +
+ + Gallery Tab + + The Gallery tab allows you to associate + files (known in GRAMPS as media + objects) with a particular person. These files are typically + images or photographs, but may be of any file type, such as (but + not limited to) sound files and word processing documents. + + + + GRAMPS provides a central repository + for all media objects in the Media View. This allows the same + media object to appear in multiple galleries. Adding a media + object to a gallery actually adds the object to the Media View, + and makes a local reference in the gallery. + + + While each media object can have a note and attributes attached + to it, each gallery can add its own notes and attributes to the + reference in its gallery. This allows media objects to have + global and local properties. For example, a photo of a family + reunion may have many people in it. A global note may describe + the picture in general, identifying the place and date. When + this object is added to a gallery, you can attach a note to the + reference in the gallery adding some specific information, such + as "Aunt Martha is the third person from the right in the + second row". Clicking the Edit + Properties allows you to edit the local properties. + +
+ Local Media Properties + + Local Media Properties + + + +
+ + The first object in the gallery is considered to be the primary + image. If this object is an image, it will appear on the + General Information tab, and will be the + primary image used by report generators. An image can be made + the default at any time by selecting the thumbnail image and + dragging it to the first position in the gallery. In this same + manner, the order of the images can be changed using the same + drag and drop technique. + + + Objects may be added to the gallery in several ways. By clicking + the Add Media Object button, a dialog box + is presented which allows you to choose an object from the file + system. This method adds a new object to the Media View and + creates a reference in the gallery. Objects may also be added + by either dragging and dropping from one gallery to another, or + by dragging from the Media View to a gallery. In this case, a + new media object is not created, but a reference to an existing + media object is made in the gallery, sharing the same media + object between galleries. Finally, new objects may be added to a + gallery and the Media View by dragging and dropping from a file + manager (such as Nautilus or + Konqueror) or a web browser (such as + Galeon, + Mozilla, or + Konqueror) into a gallery. + + + Media objects can be removed from a gallery by clicking the + Delete Media Object button. This action + only removes the reference to the current gallery. It does not + remove the media object from the Media View or from any other + galleries that are referencing it. + + + Right clicking on a selected object brings up a menu. + + Menu options + + View in default viewer + + + Allows you to view an object image using GNOME's default + viewer for the file type. + + + + + Edit with the GIMP + + + Launches the gimp program, + allowing you to edit the image. This option only shows up + if the media object is an image. + + + + + Edit Object Properties + + + Allows you to change the attributes and note attached to the + media object. + + + + + Convert to local copy + + + This option is only displayed if the media is a reference + to a file that is not controlled by + GRAMPS. Selecting the option + causes GRAMPS to make its own + copy of the media object. + + + + +
+ + Internet Tab + + Frequently, information about a person is available on the + internet, frequently on someone else's web site. With multiple + people researching the same family, it is desirable to keep track + of internet sites that contain information about someone in your + database. This allows you to keep track of the web sites you + can periodically check them for any addition information. + +
+ Internet Tab + + Internet Tab + + + +
+ + The Internet tab displays information about + the currently selected internet address at the top of the window. Below + this information is a list of the internet address that have been + previously entered. Clicking on one of the events in the list + selects the event, and displays its information at the top of + the window. + + + Clicking on the internet address displayed at the top part of + the window will cause GRAMPS to attempt + to display the site using the GNOME default browser. + + + An internet address may be added by clicking on the + Add button. This displays a form that + allows you to enter the information about the internet + address. This information consists of the web address (URL) and + a description of the location. The + Edit/View button allows to view or alter + the information of the currently displayed internet address. The + Delete button allows you to delete the + currently displayed internet address. + +
+ + LDS Tab + + If you have chosen to enable support for the LDS (Latter Day Saints) + ordinances, the LDS tab is visible, and can + be selected. This tab allows you to enter specific information used + by the Church of Jesus Christ of Latter Day Saints. + +
+ LDS Tab + + LDS Tab + + + +
+
+
+ + Family View + + The Family View window displays the spouses, parents, and children + of the active person. At any time, you can return to this view + either by pressing the Family button at the + top of the screen, or by choosing the + + View + Family View + + entry from the menus. + +
+ Family View + + Family View + + + +
+ + In the Family View, the family information related to the active + person is displayed. This information falls into two categories: + families in which the person is a child, and families in which the + person is a spouse or parent. + + + Relationships to Parents + + On the right hand side of the window displays the parents of the + active person. By default, a birth relationship is + assumed. GRAMPS supports multiple + family relationships for each person. For example, a person may + have natural birth parents and adopted parents. In this case, an + option menu will appear below the parents names, allowing you to + choose which set of parents you wish to view. + + + Pressing the Add/Edit Parents + allows you to choose the active person's parents and specify the + person's relationship to the parents. + + + Pressing the Delete Parents does not + remove the parents from the database, but instead deletes the + relationship between the active person and the currently displayed + parents. + + + To right of the names of the parents are two "arrow" + buttons. Selecting the button next to the father changes the + father to the active person, and displays the fathers + information in the Family View window. Similarly, selecting the + button next to the mother changes the mother to the active + person. + + + To the left of the parents' names are buttons indicating the + relationship to the active person. These are typically labeled + "Father" and "Mother", but in some cases may simply be labeled + "Parent". Pressing one of these buttons will display the + Edit Person for the corresponding person. + + + + Marriage/Relationship Information + + On the left side of the window, below the active person's name, + is the information related to the person's marriages and + relationships. If the person has one or no relationships, the + spouse will appear within a non-editable text box. If more than + one relationship exists, the text box will be replaced with an + option menu that allows you to select the relationship to view. + + + Between the active person and the relationship information is a + button with two arrows. Pressing this button will exchange the + active person and spouse on the display. The currently displayed + spouse will become the active person, and the family information + on the right hand side of the screen will change to reflect + this. + + + Pressing the Spouse next to the spouse's + name will display the currently displayed spouse's information + in an Edit Person dialog, allowing you + change the information + + + Pressing the Add located below the entry + for the spouse's name allows a new relationship to be + added. This gives you the opportunity to select and existing + person or to add a new person as the new spouse. The type of + relationship can also be specified. All relationship types, + except "Partners" require that the spouses be of opposite + sex. The "Partners" relationship type requires that the spouses + be of the same sex. + + + Pressing the Edit button allows you to + edit the information related to the marriage. The information + includes events, attributes, and images. + + + The Remove button removes the current + spouse from the relationship. If no children exist in the + relationship, the entire relationship is removed. If children + exist in the relationship, the current spouse is removed, + and the children remain in a family with the active person as the + only parent. + + + + Children of a Relationship + + The bottom of the window contains the list of children related + to the active person and the currently selected spouse. Clicking + on an entry in the list makes that child the active child. + + + Clicking the Add New Child creates a new + child and adds him or her as a child of the current + relationship. Clicking the Add Existing + Child allows you to select an existing person and + assign the person as a child of the current + relationship. Clicking the Remove Child + removes the active child from the current relationship, but does + not delete the person from the database. + + + Double clicking on an entry in the list brings up the + Edit Person dialog for the child. + + + You are able to make the selected child the active person by + clicking the arrow button next to the child list. The + highlighted child in the child list becomes the active person. + + +
+ + Pedigree View + + The Pedigree View window displays the active person, the active + person's parents, and the active parent's grandparents in a + somewhat graphical manner. At any time, you can return to this + view either by pressing the Pedigree button at the top of the + screen, or by choosing the + + View + Pedigree + + entry from the menus. + +
+ Pedigree View + + Pedigree View + + + +
+ + Moving the mouse over a displayed name will display additional + information about a person, including their date of birth and date + of death. Double-clicking the box will display the Edit + Person dialog box for the person. Holding down the + Shift key while double clicking will will make that person the + active person. + + + Navigation around the tree can be accomplished several + ways. Clicking on the arrow next to the active person will display + a menu listing the children of the active person. Selecting a + person from this list will change the active person to the + selected child, effectively shifting the pedigree view to the + left, or down one generation. Clicking one of the arrow buttons on + the left side of the screen will make the select either the active + person's father (top button) or mother (bottom button), + effectively shifting the pedigree view to the right, or up one + generation. If the active person does not have any children, then + the button on the left-hand side of the screen will not + appear. Similarly, if the active person does have a father or + mother, the corresponding button on the right-hand side of the + screen will not appear. + + + + As a quick short cut, double clicking on a line between two people + will make the person on the right-hand side of the line the active + person. shows navigation using this + method. When the mouse is over one of the lines connecting + individuals, the line widens and becomes highlighted. In this + case, double clicking on the line would make Hjalmar Smith the + active person. + +
+ + + Source View + + The Source View window displays the different sources that have + been entered into the database. At any time, you can return to + this view either by pressing the Sources + button at the top of the screen, or by choosing the + + View + Sources + + entry from the menus. + +
+ Source list + + Source View + + + +
+ + From this screen you are able to Add and Edit sources. Currently, + deleting of sources is not available. This will be implemented in + a future version. + +
+ + + Place View + + The Place View window displays the different sources that have + been entered into the database. At any time, you can return to + this view either by pressing the Places + button at the top of the screen, or by choosing the + + View + Places + + entry from the menus. + +
+ Place View + + Place View + + + +
+ + From this screen you are able to Add, Edit, and Delete places. + +
+ + + Media View + + The Media View window displays the files associated with the + database. Typically, these files are images, but + GRAMPS allows you to attach any type of + file to the database. GRAMPS refers to + attached files as media objects. You can access the Media View at + any time by either pressing the Media + button at the top of the screen, or by choosing the + + View + Media + + entry from the menus. + +
+ Media View + + Media View + + + +
+ + Media Objects + + Media objects can be either local or external to a + GRAMPS database. If + GRAMPS is told to import an object as + a local object, it will make its own copy of the file in the + database directory. If the object is not imported as a local + object, the original file is used. + + + There are advantages and disadvantages to both methods. If the + object is local, then if the original file is moved or deleted, + then GRAMPS will still have its own + copy. However, this is at the price of having two copies of the + file. If the file is not imported as a local object, then a copy + is not made, saving disk space. However, altering or deleting + the original copy will affect the + GRAMPS database. + + + + Adding a Media Object + + Media objects can be imported in several ways. Adding an object + to any gallery adds the object to the Media View. The gallery is + will actually contain a reference to the object in the Media + View. + + + Objects may also be added using the Add Media + Object button. This will add the object to the Media + View, but not to any gallery. When you select the file to be + added, a preview will be displayed in the preview window. If the + file is an image, the image will be displayed. Otherwise, an + icon representing the file type will be displayed. In the dialog + box, you may choose to either import the object as a local + object, or leave it as an external object. +
+ Add Media Object Dialog Box + + Add Media Object Dialog Box + + + +
+
+ + Finally, you may drag-and-drop an object from either a file + manager or a web browser. If the object is dropped into a + gallery, then a reference is made in the gallery, and the object + appears in the Media View. If the object is dropped directly + into the Media View, then it appears in the Media View, but will + not appear in a gallery. Currently, all objects imported via + drag-and-drop are imported as external (not local) objects. + +
+ + Making a Reference to a Media Object + + Once an object is in the Media View, it is possible to make a + reference to it in any gallery. You may place the object in as + many galleries as you like, and only one copy of the file will + exist. + + + To make a reference to a media object in a gallery, you may + simply drag-and-drop the object from the Media View directly to + a gallery. The object will then appear in the + gallery. Similarly, you may drag-and-drop from one gallery to + another gallery, and a new object reference is created in the + target gallery. + + + + Changing a Media Object's Properties + + Media objects have global and local properties. The title of the + object is a global property. It may only be changed from the + Media View, and it will affect all references. An object also + has a global note and a set of user defined global attributes. + A reference in a gallery may a have a local note and local + attributes as well. All references share the global properties, + but each gallery has its own set of notes a attributes. + + + The global note can be used to provide a general + description. For example, in a family reunion image, you may + wish to use the global note to indicate the place, date, and + occasion of the photograph. In a local note in Aunt Martha's + gallery, you may wish to add a local note indicating that + "Aunt Martha is the third person from the right in the + second row". + + + The global properties may be changed by selecting the + Edit Media Object button. +
+ Edit a Media Object's Global Properties + + Edit a Media Object's Global Properties + + + +
+
+
+
+ + + Bookmarking People + + GRAMPS supports two mechanisms to + quickly find people - the home person and bookmarks. + + + Home Person + + The home person is the default person of the database. Upon + loading the database, GRAMPS will set + the active person to the default person. At any time, clicking + the Home button will return the active + person to the home person. + + + The home person can be set by choosing + + Settings + Set Default Person + . + + + + Bookmarks + + Bookmarks work similar to bookmarks in HTML browsers. They + allow you to quickly jump to a person, making that person the + active person. This allows you to avoid searching for them + every time you want to add/change something in their information. + +
+ Using Bookmarks + + Using Bookmarks + + + +
+ + Choosing + + Bookmarks + Add Bookmark + + adds the current active person to the bookmark list. The person + will then appear in the bookmark list, allowing you to quickly + select the person. + + + Choosing + + Bookmarks + Go to Bookmark + + displays a sub-menu which allows you to choose a person who was + previously bookmarked. Selecting a person from this menu will + make that person the active person. + + + Choosing + + Bookmarks + Edit Bookmarks + + displays a dialog box that allows you to reorder or delete + bookmarks in the list. + +
+ Editing Bookmarks + + Editing Bookmarks + + + +
+
+
+ + + Using Revision Control + + Revision control allows you to keep a history of the changes that + you have made to your database. Instead of needing to keep + multiple sets of back up files, a single revision control database + is maintained. At any point, you can revert back to a previously + saved version. + + + GRAMPS uses the standard + RCS system to handle revisions. + + + Revision control is enabled in the Revision Control tab of the + preferences dialog. Once enabled, every save is logged into the + revision control database. If you have enabled prompting for a + comment, then a dialog box will be displayed on every save asking + you to provide a comment about the changes you have made. +
+ Providing a revision control comment + + Providing a revision control comment + + + +
+
+ + Reverting to a previous version + + If revision control has been enabled, you have the option of + reverting to a previous version of the database. Selecting the + check box will allow you to select a previous version. +
+ Opening a database + + Opening a database + + + +
+
+ + If the check box has be selected, GRAMPS + will display a dialog box that will allow you to choose which version + you would like to view. The dialog box displays the version number, the + date the version was saved, who saved the database, and any comment supplied + when the database was saved. +
+ Choosing a revision + + Choosing a revision + + + +
+
+ + Choosing a previous revision does not replace your current + database. If you do not save the retrieved database, it will not + replace the current version. If for some reason you accidentally + save the retrieved database when you did not want to replace the + current version, you can always use the revision control + mechanism to get back the version you replaced. + + + Revision control is applied only to the database itself, not to + any media objects have been associated with the database. + +
+
+ + + + + Customization + + To change the application settings, select + + Settings + Preferences... + . This opens the + Preferences dialog, shown in . + + + + Preferences Dialog +
+ Preferences Dialog + + Preferences Dialog + + + +
+ + GRAMPS groups is options into + categories visible in the left hand side of the + dialog. Selecting one of these entries will display the + corresponding settings in the right hand side of the dialog. + +
+ + General Database options +
+ General Database options + + General Database Options + + + +
+ + The General Database page contains basic information to + control the operation of GRAMPS. + + + General Database options + + Automatically load last database + + + With this selected it will automatically load your last + database. + + + + + Do not compress XML data file + + + GRAMPS normally compresses its + data file to conserve disk space. If you do not wish to + have the file compressed, selecting this option will cause + GRAMPS to leave the file + uncompressed. This may be desirable if other applications + need to process the generated XML file. + + + + + Autosave interval (minutes) + + + If this value is set to a non-zero value, GRAMPS + will save an autosave file every few minutes, depending on the + value set. If for some reason the execution of GRAMPS + is interrupted, you can recover to the last autosave point. + + + + + Default database directory + + + This value indicates the default directory for loading and saving + databases. + + + + +
+ + Dates and Calendars +
+ Dates and Calendars + + Dates and Calendars + + + +
+ + The Dates and Calendars page allows you to change the + display and entry formats of dates. + + + + + Dates and Calendars options + + Display Formats + + + Allows you to choose your preferences for displaying dates + and names. Options exist for several different date + formats. Names can be displayed with either the given name + or the surname first. This option typically does not + affect lists that are sorted by last name, in which case + the surname is displayed first. + + + + + Entry Formats + + + Numerical date formats can be ambiguous. Some people enter + the day, month, and year (European style), while others + prefer month, day, year (American style). Selecting the + option here informs GRAMPS how + it should interpret numerical dates. + + + + + Calendars + + + GRAMPS can support calendars + other than the typical Gregorian calendar. If enabled, + GRAMPS will display a menu + allowing you to specify the calendar that a date + represents. Calendars currently supported are Gregorian, + Hebrew, Julian, and French Republican. + + + + +
+ + Media Options +
+ Media Options + + Media Options + + + +
+
+ + GRAMPS ID Options +
+ GRAMPS ID Options + + GRAMPS ID Options + + + +
+
+ + Revision Control Options +
+ Revision Control Options + + Revision Control Options + + + +
+
+ + General Display Options +
+ General Display Options + + General Display Options + + + +
+
+ + Tool and Status Bar Options +
+ Tool and Status Bar Options + + Tools and Status Bar Options + + + +
+
+ + List Color Options +
+ List Color Options + + List Color Options + + + +
+
+ + Find Options +
+ Find Options + + Find Options + + + +
+
+ + Report Options +
+ Report Options + + Report Options + + + +
+ + Many of the reports that GRAMPS + produces can be generated in different file formats and + different paper sizes. Selecting a Preferred Output + Format and a Preferred Output + Format tells the report generator your + preferences. It should be noted that a report generator might + not support all possible formats. + +
+ + Researcher Information +
+ Researcher Information + + Researcher Information + + + +
+ + This is where you are able to change the information you entered + when you started GRAMPS for the first time and was asked to + enter in some information. (This information shows up in your + GEDCOM files as being the researcher/author of the file) + +
+ + Data Guessing Options +
+ Data Guessing Options + + Data Guessing Options + + + +
+ + +
+
+ + + + + Generating Reports + + GRAMPS can produce a wide variety of + reports. A new report generator can be written by the user without + modifying the main program. For this reason, there may be more + reports available than are documented by this manual. + +
+ Report Generation Dialog + + Report Generation Dialog + + + +
+ + Unlike many genealogy programs, GRAMPS + does not directly print reports. Instead, + GRAMPS produces reports in formats that + are understood by other programs. These formats include + OpenOffice, AbiWord, PDF, and HTML, among others. This allows the + generated reports to be modified after they are generated, stored + for use at a later time, or e-mailed to another person. + + + After selecting the report you would like generated there are + options you must select. In the Save As option specify your file + name (use /full path/filename to specify a different directory + than in your Default Report Directory preference in the + preferences). The next step is to select the Report Format. + After choosing the Format you can select the style you would like + to use for your report (this does not apply to the HTML format). + You can Add/Edit/Delete a style for that particular report by + clicking the Style Editor button. + Selecting one of those options you can then change the font (font + face, size, color, and options) for each Paragraph Style along + with the Paragraph Options (Alignment, background color, margins, + and borders). Once you are satisfied with the style you are ready + to proceed with the generation of your report. The next step is + to choose the options (if any for that specific report) and then + Choose the Template (for HTML format only) and click OK. Your + report will now be in default report directory (unless otherwise + specified). + + + Using HTML templates + + Many programs exist to convert GEDCOM files into HTML files that + can be viewed in a web browser. Most of these programs generate + HTML files according to their own predefined style. Since most + people have a style that they prefer, they are left with the + option of modifying hundreds of files by hand. + + + To solve this problem, GRAMPS allows + the user to specify a template to be used for generating HTML + files. At the time the report is generated, if HTML is selected + as the target format, the user can select an HTML template to be + used. Since the template is chosen at report generation time, a + different template may be chosen each time, allowing the user to + change the appearance of the generated files at any time. + Nearly any existing HTML file can be used as an HTML template + for GRAMPS. + + + When a file has been established as the HTML template file, + GRAMPS uses the template for each + file that it generates. GRAMPS starts + each file by copying data from the template until it reaches the + HTML comment, which it uses as a marker. At that point, + GRAMPS inserts its data into the + output file. GRAMPS the continues + reading the until it reaches a second comment that tells it to + resume copying from the template. + + + GRAMPS uses the string + <!-- START --> to indicate where it + should start inserting its information, and the string + <!-- STOP --> to indicate where it + should resume copying data from the template. The effect is + that GRAMPS will create a new + document, replacing everything between the <!-- + START --> and <!-- STOP + --> comments with the report information. + + + The comment markers should be at the beginning of a line in the + HTML template file. Adding the comments to an existing HTML + document will not affect the original HTML document in any way. + + + If no HTML template is specified, or if the specified template + cannot be read, GRAMPS will use a + default, predefined template. + +
+ Sample HTML Template Example + +<HTML> +<HEAD> +<TITLE> +This is my Title +</TITLE> +</HEAD> +<BODY BGCOLOR="#FFFFFF"> +<P> +This is a simple template. This text will appear in the HTML output. +</P> +<!-- START --> +<P> +This is where GRAMPS will place its report information. Any +information between the two comments, including this paragraph, +will not appear in the GRAMPS generated output. +</P> +<!-- STOP --> +<P> +This text, since it appears after the stop comment, will also +appear in every GRAMPS generated file. +</P> +</BODY> +</HTML> + +
+
+
+ + + + + Running Tools + + GRAMPS supports standard and user + written tools. These tools can operate on the database to perform + a specified task. + +
+ Tool Selection Dialog + + Tool Selection Dialog + + + +
+ + Analysis and Exploration + + Compare individual events + + + Aids in the analysis of data by allowing the development of + custom filters that can be applied to the database to find + similar events. + + + + + Interactive descendant browser + + + Provides a browsable hierarchy based on the active person. + + + + + + Data Processing + + Check and repair database + + + Checks the database for integrity problems, fixing the + problems that it can. + + + + + Extract information from names + + + Searches the entire database and attempts to extract titles + and nicknames that may be embedded in a person's given name + field. + + + + + Merge people + + + Searches the entire database, looking for individual entries + that may represent the same person. + + + + + Rename personal event types + + + Allows all the events of a certain name to be renamed to a + new name. + + + + + Reorder GRAMPS ID's + + + Reorders the GRAMPS ID's according to GRAMPS' default rules. + + + + + + Utilities + + Generate SoundEx codes + + + Generates SoundEx codes for names. + + + + + Relationship calculator + + + Calculates the relationship between two people. + + + + +
+ + + + + + + Authors + + GRAMPS was written by Don Allingham + (dallingham@users.sourceforge.net). To find more + information about GRAMPS, please visit + the GRAMPS + Web page. + + + This manual was written by Don Allingham + (dallingham@users.sourceforge.net), Larry Allingham + (llkla@erinet.com), and Shawn Ann Griffith + (shawnann1@home.com). + + + + + + + + + + License + + 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. + + + A copy of the GNU General Public License is + included as an appendix to the GNOME Users + Guide. You may also obtain a copy of the + GNU General Public License from the Free + Software Foundation by visiting their Web site or by writing to +
+ Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307 + USA +
+
+
+
diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/index.html b/gramps2/doc/gramps-manual/C/gramps-manual/index.html new file mode 100644 index 000000000..0e1d66245 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/index.html @@ -0,0 +1,222 @@ + +GRAMPS User Manual

GRAMPS User Manual

Copyright © 2001 by Donald N. Allingham


+ + + + + + +

Introduction

+

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. +

+

To run GRAMPS, select + ->Programs+ ++ ->Applications+ ++ ->gramps+ ++ + + + + + + from the Main Menu, or type + gramps on the command line. +

+

This document describes version 0.7.3 of + GRAMPS. +

+
+ + + + + + + + + + + +

  Next >>>
  Running GRAMPS for the first time.
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/ln7.html b/gramps2/doc/gramps-manual/C/gramps-manual/ln7.html new file mode 100644 index 000000000..603ce59c6 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/ln7.html @@ -0,0 +1,133 @@ + +
GRAMPS User Manual

Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation + License, 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 here. +

+

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. +

+


 Home 
 Up 
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/caution.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/caution.gif new file mode 100644 index 000000000..542232911 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/caution.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/home.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/home.gif new file mode 100644 index 000000000..55e1d5993 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/home.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/important.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/important.gif new file mode 100644 index 000000000..8793ff2b1 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/important.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/next.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/next.gif new file mode 100644 index 000000000..ceb93e120 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/next.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/note.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/note.gif new file mode 100644 index 000000000..45fe08649 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/note.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/prev.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/prev.gif new file mode 100644 index 000000000..0894d9ecb Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/prev.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/tip.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/tip.gif new file mode 100644 index 000000000..025819548 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/tip.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-blank.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-blank.gif new file mode 100644 index 000000000..6c65e3a19 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-blank.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-minus.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-minus.gif new file mode 100644 index 000000000..40ebe61e4 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-minus.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-plus.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-plus.gif new file mode 100644 index 000000000..3e9e7d55a Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/toc-plus.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/up.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/up.gif new file mode 100644 index 000000000..603c4ce24 Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/up.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/warning.gif b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/warning.gif new file mode 100644 index 000000000..9c1104c2b Binary files /dev/null and b/gramps2/doc/gramps-manual/C/gramps-manual/stylesheet-images/warning.gif differ diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/t1.html b/gramps2/doc/gramps-manual/C/gramps-manual/t1.html new file mode 100644 index 000000000..0e1d66245 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/t1.html @@ -0,0 +1,222 @@ + +GRAMPS User Manual

GRAMPS User Manual

Copyright © 2001 by Donald N. Allingham


+ + + + + + +

Introduction

+

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. +

+

To run GRAMPS, select + ->Programs+ ++ ->Applications+ ++ ->gramps+ ++ + + + + + + from the Main Menu, or type + gramps on the command line. +

+

This document describes version 0.7.3 of + GRAMPS. +

+
+ + + + + + + + + + + +

  Next >>>
  Running GRAMPS for the first time.
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/x129.html b/gramps2/doc/gramps-manual/C/gramps-manual/x129.html new file mode 100644 index 000000000..7c1a96b23 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/x129.html @@ -0,0 +1,355 @@ + +Editing a person's data
GRAMPS User Manual
<<< Previous 

Editing a person's data

+

A person's personal information can be edited in the + Edit Person dialog. +

+
+ +

Events Tab

+

The Events tab allows information about + various events in a person's life to be + recorded. GRAMPS provides a list of + common events, but allows you to name an event anything that you + choose. +

+

An event consists of the name of an event (such as "Baptism" or + "Education"), a date or date range on which the event occurred, + the place where the event occurred, and a description of the + event. A note or a source may also be attached to the event. +

+
+

The Event tab displays information about + the currently selected event at the top of the window. Below + this information is a list of the events that have been + previously entered. Clicking on one of the events in the list + selects the event, and displays its information at the top of + the window. +

+

An event may be added by clicking the Add + button. This displays a form that allows you to enter the + information about the particular event. The + Edit/View button allows to view or to + alter the information of the currently displayed event. The + Delete button allows you to delete the + currently displayed event. +

+
+

<<< PreviousHome 
People View  
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/x28.html b/gramps2/doc/gramps-manual/C/gramps-manual/x28.html new file mode 100644 index 000000000..fad114536 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/x28.html @@ -0,0 +1,181 @@ + +Running GRAMPS for the first time.
GRAMPS User Manual
<<< PreviousNext >>>


<<< PreviousHomeNext >>>
GRAMPS User Manual Getting Started
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/x41.html b/gramps2/doc/gramps-manual/C/gramps-manual/x41.html new file mode 100644 index 000000000..7f093481a --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/x41.html @@ -0,0 +1,306 @@ + +Getting Started
GRAMPS User Manual
<<< PreviousNext >>>

Getting Started

+

Starting GRAMPS opens the + Main window, shown in . You will be prompted to either open an + existing database, or to create a new + database. GRAMPS requires that a + database always be open. +

+
+ +

Entering Data

+

If you have never used a genealogy program or you do not have a + GEDCOM file to import, you can start creating your database + right away. From the main window click the Add + Person button and the Edit + Person dialog will open. Enter in the information + you have on the first person. Start with their general + information (Name, Birth and Death Date/Place) and then move on + to the Names, + Events, + Attributes, + Addresses, Notes, + Gallery, and + Internet tabs and fill in the known + information you have. Some of the information you enter has a + Source button and/or a + Note button. These buttons are there to + add more information (Source button to + add the source of where you acquired the information and the + Note button to add more detail to the + information) +

+
+

<<< PreviousHomeNext >>>
Running GRAMPS for the first time. People View
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/gramps-manual/x84.html b/gramps2/doc/gramps-manual/C/gramps-manual/x84.html new file mode 100644 index 000000000..321eb135d --- /dev/null +++ b/gramps2/doc/gramps-manual/C/gramps-manual/x84.html @@ -0,0 +1,334 @@ + +People View
GRAMPS User Manual
<<< PreviousNext >>>

People View

+

The People View window is the initial view seen on the main + window. It displays the name, gender, birth date, and death + date of all individuals in the database. At any time, you can + return to this view either by pressing the + People button at the top of the screen, or + by choosing the + + + + + + + + +View+ ++ + + + + + + + ->People+ + ++ + + + + + + entry from the menus. +

+
+

Selecting and Editing Individuals

+

The People View lists the individuals in the database. An + individual can be selected as the active person by clicking on + an entry in the list. Once a person has been selected as the + active person, the person's name appears in the status bar in + the lower left hand corner of the window. +

+

Once the active person has been selected, pressing the + Edit Person button will display the + Edit Person dialog allowing you to edit + the individual's personal information. If the Edit + Person button is pressed without an active person + being set, a blank Edit Person dialog is + presented, allowing you to enter a new person. +

+

Double-clicking on a entry in the list will set the active + person and bring up the individual in the Edit + Person dialog. +

+

Pressing the Add Person button will + display a blank Edit Person dialog, + allowing you to add a new person to the database. +

+

If the Delete Person button is pressed, + the active person and all of the personal information related to + the active person are removed from the database. +

+
+

Applying Filters

+

GRAMPS allows you to apply filters to + the People View. When a filter is applied, the People View will + only display the entries matching the filter. All of the entries + remain in the database, but some entries may be temporarily hidden. +

+

There are up to three parts to a filter. The first part is the + selection of the filter to be applied. A filter is selected from + the option menu directly above the People View. The second part + is an optional argument. This qualifier provides more specific + information for the filter. Many filters do not require the + argument, and it will not be displayed if it is not needed. If + the argument is required, a text box with a descriptive label + will appear. The third part of the filter is the invert + selection. When this option is selected, + GRAMPS will display the entries that + do not match the filter. +

+
+

A filter is not applied until the Apply + button is pressed. The filter will remain in effect until the + next time the Apply button is pressed. +

+
+ +

<<< PreviousHomeNext >>>
Getting Started Editing a person's data
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/index.html b/gramps2/doc/gramps-manual/C/index.html new file mode 100644 index 000000000..0e1d66245 --- /dev/null +++ b/gramps2/doc/gramps-manual/C/index.html @@ -0,0 +1,222 @@ + +GRAMPS User Manual

GRAMPS User Manual

Copyright © 2001 by Donald N. Allingham


+ + + + + + +

Introduction

+

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. +

+

To run GRAMPS, select + ->Programs+ ++ ->Applications+ ++ ->gramps+ ++ + + + + + + from the Main Menu, or type + gramps on the command line. +

+

This document describes version 0.7.3 of + GRAMPS. +

+
+ + + + + + + + + + + +

  Next >>>
  Running GRAMPS for the first time.
\ No newline at end of file diff --git a/gramps2/doc/gramps-manual/C/omf_timestamp b/gramps2/doc/gramps-manual/C/omf_timestamp new file mode 100644 index 000000000..e69de29bb diff --git a/gramps2/doc/gramps-manual/Makefile.am b/gramps2/doc/gramps-manual/Makefile.am new file mode 100644 index 000000000..dbed85073 --- /dev/null +++ b/gramps2/doc/gramps-manual/Makefile.am @@ -0,0 +1,4 @@ +# Process this file with automake to produce Makefile.in + +SUBDIRS = C + diff --git a/gramps2/doc/gramps-manual/Makefile.in b/gramps2/doc/gramps-manual/Makefile.in new file mode 100644 index 000000000..563986e5e --- /dev/null +++ b/gramps2/doc/gramps-manual/Makefile.in @@ -0,0 +1,352 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Process this file with automake to produce Makefile.in +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ + +SUBDIRS = C +subdir = doc/gramps-manual +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/gramps-manual/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive distclean distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-generic \ + mostlyclean-recursive tags tags-recursive uninstall \ + uninstall-am uninstall-info-am uninstall-info-recursive \ + uninstall-recursive + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/doc/gramps.1 b/gramps2/doc/gramps.1 new file mode 100644 index 000000000..326bc4e93 --- /dev/null +++ b/gramps2/doc/gramps.1 @@ -0,0 +1,49 @@ +.TH gramps 1 "0.9.0pre1" "man page by Brandon L. Griffith" "" +.SH "NAME" +.LP +gramps \- Genealogical Research and Analysis Management Programming System +.SH "SYNTAX" +.LP +gramps [\fIDatabase\fP] +.br +Currently \fBgramps\fR does not require any command line arguments. +However, if provided, it is the path to either a gramps database or a GEDCOM +file to be imported. +.SH "DESCRIPTION" +.LP +Gramps is an open source genealogy program. It is written in Python, using the GTK/GNOME interface. +.br +Gramps should seem familiar to anyone who has used other geneology programs before such as \fIFamily Tree Maker for Windows(TM)\fR or the GNU Geneweb. +.br +It supports importing of the ever popular GEDCOM format which is used world wide by almost all other geneology software. +.SH "Concepts" +Supports a python\-based plugin system, allowing import and export writers, report generators, tools, and display filters to be added without modification of the main program. +.LP +Data is stored in an gzip'ed XML format +.LP +Instead of generating direct printer output, report generators target other systems, such as \fIOpen Office\fR, \fIAbiWord\fR, HTML or LaTeX to allow the user to modify the format to suit his or her needs. +.SH "FILES" +.LP +\fI${PREFIX}/bin/gramps\fP +.br +\fI${PREFIX}/share/gramps\fP +.br +\fI${HOME}/.gramps\fP +.SH "Authors" +Donald Allingham \fI\fR +.br +\fIhttp://gramps.sourceforge.net\fR +.LP +This manpage was written by: +.br +Brandon L. Griffith \fI\fR +.br +Any ammendants or errors should be reported to him. +.br +It was originally written for inclusion in the Debian GNU/Linux system. +.SH "DOCUMENTATION" +See also the file \fBgramps.sgml\fR +.br +On a Debian system this can be found in \fI/usr/doc/gramps\fR +.br +Or in the doc directory of the official source distribution. diff --git a/gramps2/doc/gramps.1.in b/gramps2/doc/gramps.1.in new file mode 100644 index 000000000..fae3c52a1 --- /dev/null +++ b/gramps2/doc/gramps.1.in @@ -0,0 +1,49 @@ +.TH gramps 1 "@VERSION@" "man page by Brandon L. Griffith" "" +.SH "NAME" +.LP +gramps \- Genealogical Research and Analysis Management Programming System +.SH "SYNTAX" +.LP +gramps [\fIDatabase\fP] +.br +Currently \fBgramps\fR does not require any command line arguments. +However, if provided, it is the path to either a gramps database or a GEDCOM +file to be imported. +.SH "DESCRIPTION" +.LP +Gramps is an open source genealogy program. It is written in Python, using the GTK/GNOME interface. +.br +Gramps should seem familiar to anyone who has used other geneology programs before such as \fIFamily Tree Maker for Windows(TM)\fR or the GNU Geneweb. +.br +It supports importing of the ever popular GEDCOM format which is used world wide by almost all other geneology software. +.SH "Concepts" +Supports a python\-based plugin system, allowing import and export writers, report generators, tools, and display filters to be added without modification of the main program. +.LP +Data is stored in an gzip'ed XML format +.LP +Instead of generating direct printer output, report generators target other systems, such as \fIOpen Office\fR, \fIAbiWord\fR, HTML or LaTeX to allow the user to modify the format to suit his or her needs. +.SH "FILES" +.LP +\fI${PREFIX}/bin/gramps\fP +.br +\fI${PREFIX}/share/gramps\fP +.br +\fI${HOME}/.gramps\fP +.SH "Authors" +Donald Allingham \fI\fR +.br +\fIhttp://gramps.sourceforge.net\fR +.LP +This manpage was written by: +.br +Brandon L. Griffith \fI\fR +.br +Any ammendants or errors should be reported to him. +.br +It was originally written for inclusion in the Debian GNU/Linux system. +.SH "DOCUMENTATION" +See also the file \fBgramps.sgml\fR +.br +On a Debian system this can be found in \fI/usr/doc/gramps\fR +.br +Or in the doc directory of the official source distribution. diff --git a/gramps2/doc/gramps.dtd b/gramps2/doc/gramps.dtd new file mode 100644 index 000000000..6bd69e7c1 --- /dev/null +++ b/gramps2/doc/gramps.dtd @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gramps2/doc/gramps.sgml b/gramps2/doc/gramps.sgml new file mode 100644 index 000000000..3f2beee0d --- /dev/null +++ b/gramps2/doc/gramps.sgml @@ -0,0 +1,793 @@ + +]> + + + + + + + + + +
+ + + gramps User Manual + + 2001 + Donald N. Allingham + + + + + + + + + + + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation + License, 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 here. + + + 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. + + + + + + + + + + + + + + + + + + + + This is version 1.0 of the gramps manual. + + + + + + + + + Introduction + + + 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. + + + To run gramps, select + + Programs + Applications + gramps + + from the Main Menu, or type + gramps on the command line. + + + gramps is included in the + gramps package, which is part of the + GNOME desktop environment. This document describes version + &version; of gramps. + + + + + + + + Using gramps + + gramps is a genealogy program. + This section describes basic usage of + gramps. + + + + + Running gramps for the first time. + + This section should discuss the start up druid. + + + + + Main Window + + Starting gramps opens the + Main window, shown in . The window is at first empty. + + +
+ gramps Main Window + + gramps Main Window + + + +
+ +
+
+ + + + Person List + + The Person List window is the initial view seen on the main + window. It displays the name, gender, birth date, and death + date of all individuals in the database. At any time, you can + return to the this view either by pressing the People button at + the top of the screen, or by choosing the + + View + Person List + + entry from the menus. + + + Selecting and Editing Individuals + + The Person List view lists the individuals in the database. A + individual can be selected as the active person by clicking on + an entry in the list. Once a person has been selected as the active + person, the person's name appears in the status bar in the lower + left hand corner of the window. + + + Once the active person has been selected, pressing the Edit + Person button will display the Edit Person dialog allowing you + to edit the individual's personal information. If the Edit + Person button is pressed without an active person being set, a + blank Edit Person dialog is presented, allowing you to enter a + new person. Double-clicking on a entry will set the active + person and bring up the individual in the Edit Person dialog. + + + Pressing the Add Person button will display a blank Edit Person + dialog, allowing you to add a new person to the database. + + + If the Delete Person button is pressed, the active person and + all of the personal information related to the active person are + removed from the database. + + + + Applying Filters + + gramps allows you to apply filters to + the Person List. When a filter is applied, the Person List will + only display the entries matching the filter. All of the entries + remain in the database, but are temporarily hidden. + + + There are three parts to a filter. The first part is the + selection of the filter to be applied. A filter is selected from + the option menu directly above the Person List. The second part + is an option qualifier. This qualifier provides more specific + information for the filter. Many filters do not require the + qualifier, and it will be grayed out if not needed. The third + part of the filter is the invert selection. When this option is + selected, gramps will display the + entries that do not match the filter. + + + A filter is not applied until the Apply button is pressed. The + filter will remain in effect until the next time the Apply + button is pressed. + + + + Sorting + + Four columns are shown in the Person List display. The entries in + the list can be sorted by three of the field: Name, Birth Date, or + Death Date. Clicking on the column label will cause the list to + be resorted by that column. Arrows on the label indicate whether + the list is sort by ascending or descending order. + + + If the list is already sorted by a particular column, clicking on + the same column label will switch sorting order. For example, if + the list is currently sorted in ascending order by Name, clicking + on the Name column header will resort the list in descending order. + + + + + + + Family View + + The Family View window displays the spouses, parents, and children + of the active person. At any time, you can return to the this view + either by pressing the Family button at the top of the screen, or + by choosing the + + View + Family View + + entry from the menus. + + + This section should describe the family view. + + + + + Pedegree View + + The Pedegree View window displays the active person, the active + person's parents, and the active parent's grandparents in a somewhat + graphical manner. At any time, you can return to the this view + either by pressing the Pedegree button at the top of the screen, or + by choosing the + + View + Pedgree + + entry from the menus. + + + This section should describe the pedegree view. + + + + + Source List + + The Source List window displays the different sources which have been + entered into the database. At any time, you can return to the this view + either by pressing the Sources button at the top of the screen, or + by choosing the + + View + Sources + + entry from the menus. + + + This section should describe the source list. + + + + + + + Customization + + To change the application settings, select + + Settings + Preferences... + . This opens the + Preferences dialog, shown in . + + +
+ Preferences Dialog + + Preferences Dialog + + + +
+ + + + +
+ + + + + Generating Reports + + gramps can produce a wide variety of + reports. New report generators can be written by the user without + modifying the main program. For this reason, there may be more + reports available than are documented by this manual + + + Unlike many genealogy programs, gramps + does not directly print reports. Instead, + gramps produces reports in formats that + are understood by other programs. These formats include OpenOffice, + AbiWord, PDF, and HTML, among others. This allows the generated + reports to be modified after they are generated, stored for use + later, or emailed to another person. + + + Using HTML templates + + Many programs exist to convert GEDCOM files into HTML files that + can be viewed in a web browser. Most of these programs generate + HTML files according to their own predefined style. Since most + people have a style that they prefer, they are left with the option + of modifying hundreds of files by hand. + + + To solve this problem, gramps allows the + user to specify a template to be used for generating HTML files. At + the time the report is generated, if HTML is selected as the target + format, the user can select an HTML template to be used. Since the + template is chosen at report generation time, a different template + may be chosen each time, allowing the user to change the appearence + of the generated files at any time. Nearly any existing HTML file + can be used as an HTML template for + gramps. + + + When a file has been established as the HTML template file, + gramps uses the template for each file + that it generates. gramps starts each + file by copying data from the template until it reaches an HTML + comment uses as a marker. At that point, + gramps inserts its data into the output + file. gramps the continues reading the + until it reaches a second comment that tells it to resume copying + from the template. + + + gramps uses the string <!-- + START --> to indicate where it should start inserting + its information, and the string <!-- STOP + --> to indicate where it should resume copying data + from the template. The effect is that + gramps will create a new document, + replacing everything between the <!-- START + --> and <!-- STOP --> comments + with the report information. + + + The comment markers should be at the beginning of a line in the HTML + template file. Adding the comments to an existing HTML document will + not affect the original HTML document in any way. + + + If no HTML template is specified, or if the specified template + cannot be read, gramps will use a + default, predefined template. + + +
+ Sample HTML Template Example + +<HTML> +<HEAD> +<TITLE> +This is my Title +</TITLE> +</HEAD> +<BODY BGCOLOR="#FFFFFF"> +<P> +This is a simple template. This text will appear in the html output. +</P> +<!-- START --> +<P> +This is where gramps will place its report information. Any +information between the two comments, including this paragraph, +will not appear in the gramps generated output. +</P> +<!-- STOP --> +<P> +This text, since it appears after the stop comment, will also +appear in every gramps generated file. +</P> +</BODY> +</HTML> + +
+
+
+ +
+ + + + + Writing Filters + + Users can create their own filters and add them to + gramps. By adding the filter to the + user's private filter directory + (~/.gramps/filters), + the filter will be automatically + recognized the next time that the program is started. + + + Creating a filter + + Filters are written in the python + 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. + + + 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 three functions — + create, need_qualifier, + and get_name. + + + The create 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. + + + The need_qualifier 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 + need_qualifier indicates, a text string is + always passed to the filter and the create + function. The value returned by + need_qualifier indicates to the program + whether or not the qualifier field in the display should be + enabled or disabled. + + + The get_name function is used to provide a + description for the filter. This description is entered into + filter selection menus. If the filter is intended to be used by + others, it should be prepared for internationalization. This is + accomplished by importing the intl module, + add defining _ to be + intl.gettext. The string returned by + get_name should be passed through the + _ function to allow for conversion to the + target langauge. + + + All filters must be derived from the + Filter.Filter class. The + __init__ task may be overridden, but if so, + should call the __init__ function on the + Filter.Filter class. The parent class + provides the variable self.text, which + contains the text string passed as the qualifier. + + + All filter classes must define a match + function. The function takes one argument (other than + self), which is an object of type + Person to compare against. The function + should return a 1 if the person matches the filter, or a zero if + the person does not. + +
+ Sample filter implementation + +import Filter +import string +import intl +_ = intl.gettext + +# class definition + +class SubString(Filter.Filter): + + def match(self,person): + name = person.getPrimaryName().getName() + return string.find(name,self.text) >= 0 + +# module functions + +def get_name(s): + return _("Names that contain a substring") + +def create(text): + return SubString(text) + +def need_qualifier(): + return 1 + +
+
+
+ + + + + Writing Reports + + Users can create their own report generators and add them to + gramps. By adding the report generator + to the user's private filter directory (~/.gramps/plugins), the report + generator filter will be automatically recognized the next time + that the program is started. + + + Creating a report generator + + Like filters, report generators are written in the + python language. Fewer restrictions + are made on report generators than on filters. The report + generator is passed the current gramps + database and the active person. The generator needs to take + special care to make sure that it does not alter the database in + anyway. + + + The function get_name is used to provide the + name of the the report generator. As with a filter definition, + this string should support internationalization via the + intl module. The returned string consists of + two parts, separated by a forward slash. The first part of the + string is the category of the report generator. + gramps 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. + + + A report generator module must supply the + report function, and can optionally define + the get_description and + get_xpm_data functions. The + report takes two arguments — a database + (of type RelDataBase) and the currently + selected person (of type Person). The + report is reponsible for generating the + actual report. + + + If the get_description 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. + + + If the get_xpm_data 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. + +
+ Sample report implementation + +import intl +_ = intl.gettext + +def report(database,person): + ... actual code ... + +def get_description(): + return "A detailed text description of what the report generator does" + +def get_name(): + return _("Category/report name") + +def get_xpm_image(): + return [ + "... XPM image data" + ] + +
+
+ + A little help - Format Interfaces + + gramps provides some help with writing + reports. Several generic python classes exist that aid in the + writing of report generators. These classes provide an abstract + interface for a type of document, such as a drawing, word + processor document, or a spreadsheet. From these core classes, + gramps derives interfaces to various + document formats. This means that by coding to the generic word + processing class (TextDoc), a report + generator can instant access to multiple file formats (such as + HTML, OpenOffice, and AbiWord). + + + This scheme of deriving a output format from a generic base class + also makes it easier to add new formats. Creating a new + derivied class targeting a different format (such as + KWord or + LaTeX) makes it easy for existing + report generators to use the new formats. + + +
+ + + + + Writing Tools + + + + + + + + + + + + + + Known Bugs and Limitations + + This application has no known bugs. + + + + + + + + Authors + + gramps was written by Donald N. Allingham + (donaldallingham@home.com). To find more information about + gramps, please visit the gramps Web + page. + + + + This manual was written by Donald N. Allingham + (donaldallingham@home.com) and Lawrence L. Allingham + (llkla@erinet.com). + + + + + + + + + + + License + + 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. + + + A copy of the GNU General Public License is + included as an appendix to the GNOME Users + Guide. You may also obtain a copy of the + GNU General Public License from the Free + Software Foundation by visiting their Web site or by writing to +
+ Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307 + USA +
+
+
+
+ + + + + + + + + diff --git a/gramps2/doc/sgmldocs.make b/gramps2/doc/sgmldocs.make new file mode 100644 index 000000000..a5e087a5f --- /dev/null +++ b/gramps2/doc/sgmldocs.make @@ -0,0 +1,155 @@ +# To use this template: +# 1) Define: figs, docname, lang, omffile, sgml_ents although figs, +# omffile, and sgml_ents may be empty in your Makefile.am which +# will "include" this one +# 2) Figures must go under figures/ and be in PNG format +# 3) You should only have one document per directory +# +# Note that this makefile forces the directory name under +# $prefix/share/gnome/help/ to be the same as the SGML filename +# of the document. This is required by GNOME. eg: +# $prefix/share/gnome/help/fish_applet/C/fish_applet.sgml +# ^^^^^^^^^^^ ^^^^^^^^^^^ +# Definitions: +# figs A list of screenshots which will be included in EXTRA_DIST +# Note that these should reside in figures/ and should be .png +# files, or you will have to make modifications below. +# docname This is the name of the SGML file: .sgml +# lang This is the document locale +# omffile This is the name of the OMF file. Convention is to name +# it -.omf. +# sgml_ents This is a list of SGML entities which must be installed +# with the main SGML file and included in EXTRA_DIST. +# eg: +# figs = \ +# figures/fig1.png \ +# figures/fig2.png +# docname = scrollkeeper-manual +# lang = C +# omffile=scrollkeeper-manual-C.omf +# sgml_ents = fdl.sgml +# include $(top_srcdir)/help/sgmldocs.make +# dist-hook: app-dist-hook +# + +docdir = $(datadir)/gnome/help/$(docname)/$(lang) + +doc_DATA = index.html + +sgml_files = $(sgml_ents) $(docname).sgml + +omf_dir=$(top_srcdir)/omf-install + +EXTRA_DIST = $(sgml_files) $(doc_DATA) $(omffile) $(figs) + +CLEANFILES = omf_timestamp + +# when doing a distclean, we also want to clear out html files: +CONFIG_CLEAN_FILES = index.html $(docname)/*.html $(docname)/stylesheet-images/*.gif + +all: index.html omf + +omf: omf_timestamp + +omf_timestamp: $(omffile) + -for file in $(omffile); do \ + scrollkeeper-preinstall $(docdir)/$(docname).sgml $$file $(omf_dir)/$$file; \ + done + touch omf_timestamp + +index.html: $(docname)/index.html + -cp $(docname)/index.html . + + +# The weird srcdir trick is because the db2html from the Cygnus RPMs +# cannot handle relative filenames. +# The t1 test is for certain versions of jw that create cryptic +# html pages, o fwhich the index is called "t1". Also, the jw +# script from docbook-utils 0.6.9 does not copy the template +# stylesheet-images directory like the db2html script does, so +# we give it a little help (at least for now) + +$(docname)/index.html: $(docname).sgml + -srcdir=`cd $(srcdir) && pwd`; \ + if test "$(HAVE_JW)" = 'yes' ; then \ + if test -f /usr/share/sgml/docbook/dsssl-stylesheets/images/next.gif ; then \ + mkdir -p $$srcdir/$(docname)/stylesheet-images ; \ + cp /usr/share/sgml/docbook/dsssl-stylesheets/images/*.gif $$srcdir/$(docname)/stylesheet-images/ ; \ + fi; \ + jw -c /etc/sgml/catalog $$srcdir/$(docname).sgml -o $$srcdir/$(docname); \ + else \ + db2html $$srcdir/$(docname).sgml; \ + fi + if test -f $(docname)/t1.html; then \ + cd $(srcdir)/$(docname) && cp t1.html index.html; \ + cd $(srcdir); \ + fi + +$(docname).sgml: $(sgml_ents) + -ourdir=`cd . && pwd`; \ + cd $(srcdir); \ + cp $(sgml_ents) $$ourdir + +app-dist-hook: index.html + -$(mkinstalldirs) $(distdir)/$(docname)/stylesheet-images + -$(mkinstalldirs) $(distdir)/figures + -cp $(srcdir)/$(docname)/*.html $(distdir)/$(docname) + -for file in $(srcdir)/$(docname)/*.css; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + cp $$file $(distdir)/$(docname)/$$basefile ; \ + done + -for file in $(srcdir)/$(docname)/stylesheet-images/*.gif; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + cp $$file $(distdir)/$(docname)/stylesheet-images/$$basefile ; \ + done + -if [ -e topic.dat ]; then \ + cp $(srcdir)/topic.dat $(distdir); \ + fi + +install-data-am: index.html omf + -$(mkinstalldirs) $(DESTDIR)$(docdir)/stylesheet-images + -$(mkinstalldirs) $(DESTDIR)$(docdir)/figures + -cp $(srcdir)/$(sgml_files) $(DESTDIR)$(docdir) + -for file in $(srcdir)/$(docname)/*.html $(srcdir)/$(docname)/*.css; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/$$basefile; \ + done + -for file in $(srcdir)/figures/*.png; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/figures/$$basefile; \ + done + -for file in $(srcdir)/$(docname)/stylesheet-images/*.gif; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(docdir)/stylesheet-images/$$basefile; \ + done + -if [ -e $(srcdir)/topic.dat ]; then \ + $(INSTALL_DATA) $(srcdir)/topic.dat $(DESTDIR)$(docdir); \ + fi + +$(docname).ps: $(srcdir)/$(docname).sgml + -srcdir=`cd $(srcdir) && pwd`; \ + db2ps $$srcdir/$(docname).sgml + +$(docname).rtf: $(srcdir)/$(docname).sgml + -srcdir=`cd $(srcdir) && pwd`; \ + db2ps $$srcdir/$(docname).sgml + +uninstall-local: + -for file in $(srcdir)/$(docname)/stylesheet-images/*.gif; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + rm -f $(docdir)/stylesheet-images/$$basefile; \ + done + -for file in $(srcdir)/figures/*.png; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + rm -f $(docdir)/figures/$$basefile; \ + done + -for file in $(srcdir)/$(docname)/*.html $(srcdir)/$(docname)/*.css; do \ + basefile=`echo $$file | sed -e 's,^.*/,,'`; \ + rm -f $(DESTDIR)$(docdir)/$$basefile; \ + done + -for file in $(sgml_files); do \ + rm -f $(DESTDIR)$(docdir)/$$file; \ + done + -rmdir $(DESTDIR)$(docdir)/stylesheet-images + -rmdir $(DESTDIR)$(docdir)/figures + -rmdir $(DESTDIR)$(docdir) diff --git a/gramps2/gramps.sh.in b/gramps2/gramps.sh.in new file mode 100644 index 000000000..a8ad8d11f --- /dev/null +++ b/gramps2/gramps.sh.in @@ -0,0 +1,48 @@ +#! /bin/sh +# @configure_input@ +# +# 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 +# + +prefix=@prefix@ + +export GRAMPSDIR=@datadir@/@PACKAGE@ +export PYTHONPATH=$GRAMPSDIR +export GRAMPSI18N=@prefix@/share/locale + +preload="" + +# +# Mandrake has a tendency to build dynamic libraries without the proper +# dependencies in them. This causes havoc with the python gtk libraries. +# Preload the know problem libraries so that gramps does not fail under +# Mandrake +# +for l in /usr/X11R6/lib/libX11.so +do + if [ -f $l ]; then + preload="$preload $l" + fi +done + +if [ "$preload" != "" ]; then + export LD_PRELOAD="$preload" +fi + +@PYTHON@ $GRAMPSDIR/gramps.py $* diff --git a/gramps2/gramps.spec b/gramps2/gramps.spec new file mode 100644 index 000000000..ae1e06bfa --- /dev/null +++ b/gramps2/gramps.spec @@ -0,0 +1,95 @@ +%define ver 0.9.0pre1 +%define rel rc4 +%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: _gladegnomemodule.so +Requires: pyexpat.so + +BuildRequires: scrollkeeper >= 0.1.4 +BuildRequires: automake >= 1.6 +BuildRequires: autoconf >= 2.52 + +%description +gramps (Genealogical Research and Analysis Management Programming +System) is a GNOME based genealogy program supporting a Python +based plugin system. + +%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 INSTALL + +%{prefix}/bin/gramps + +%{_datadir}/gnome/help/gramps-manual/C/* +%{_datadir}/gnome/help/extending-gramps/C/* + +%{_datadir}/gnome/apps/Applications/gramps.desktop +%{_datadir}/pixmaps/gramps.png +%{_datadir}/locale/*/LC_MESSAGES/gramps.mo + +%{_datadir}/gramps/*.xpm +%{_datadir}/gramps/*.jpg +%{_datadir}/gramps/*.png +%{_datadir}/gramps/*.py +%{_datadir}/gramps/*.pyo +%{_datadir}/gramps/*.glade +%{_datadir}/gramps/*.so +%{_datadir}/gramps/docgen/*.py +%{_datadir}/gramps/docgen/*.pyo +%{_datadir}/gramps/filters/*.py +%{_datadir}/gramps/filters/*.pyo +%{_datadir}/gramps/plugins/*.py +%{_datadir}/gramps/plugins/*.pyo +%{_datadir}/gramps/plugins/*.glade +%{_datadir}/gramps/data/gedcom.xml +%{_datadir}/gramps/data/templates/*.tpkg +%{_datadir}/gramps/data/templates/*.xml + +%{prefix}/man/man1/gramps.1* + +%{_datadir}/omf/gramps + +%post +if which scrollkeeper-update>/dev/null 2>&1; then scrollkeeper-update; fi + +%postun +if which scrollkeeper-update>/dev/null 2>&1; then scrollkeeper-update; fi + +%changelog +* Fri Jun 14 2002 Donald Peterson +- add scrollkeeper dependencies and some file cleanup diff --git a/gramps2/gramps.spec.in b/gramps2/gramps.spec.in new file mode 100644 index 000000000..38b9c751c --- /dev/null +++ b/gramps2/gramps.spec.in @@ -0,0 +1,95 @@ +%define ver @VERSION@ +%define rel @RELEASE@ +%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: _gladegnomemodule.so +Requires: pyexpat.so + +BuildRequires: scrollkeeper >= 0.1.4 +BuildRequires: automake >= 1.6 +BuildRequires: autoconf >= 2.52 + +%description +gramps (Genealogical Research and Analysis Management Programming +System) is a GNOME based genealogy program supporting a Python +based plugin system. + +%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 INSTALL + +%{prefix}/bin/gramps + +%{_datadir}/gnome/help/gramps-manual/C/* +%{_datadir}/gnome/help/extending-gramps/C/* + +%{_datadir}/gnome/apps/Applications/gramps.desktop +%{_datadir}/pixmaps/gramps.png +%{_datadir}/locale/*/LC_MESSAGES/gramps.mo + +%{_datadir}/gramps/*.xpm +%{_datadir}/gramps/*.jpg +%{_datadir}/gramps/*.png +%{_datadir}/gramps/*.py +%{_datadir}/gramps/*.pyo +%{_datadir}/gramps/*.glade +%{_datadir}/gramps/*.so +%{_datadir}/gramps/docgen/*.py +%{_datadir}/gramps/docgen/*.pyo +%{_datadir}/gramps/filters/*.py +%{_datadir}/gramps/filters/*.pyo +%{_datadir}/gramps/plugins/*.py +%{_datadir}/gramps/plugins/*.pyo +%{_datadir}/gramps/plugins/*.glade +%{_datadir}/gramps/data/gedcom.xml +%{_datadir}/gramps/data/templates/*.tpkg +%{_datadir}/gramps/data/templates/*.xml + +%{prefix}/man/man1/gramps.1* + +%{_datadir}/omf/gramps + +%post +if which scrollkeeper-update>/dev/null 2>&1; then scrollkeeper-update; fi + +%postun +if which scrollkeeper-update>/dev/null 2>&1; then scrollkeeper-update; fi + +%changelog +* Fri Jun 14 2002 Donald Peterson +- add scrollkeeper dependencies and some file cleanup diff --git a/gramps2/install-sh b/gramps2/install-sh new file mode 100644 index 000000000..178cdac7d --- /dev/null +++ b/gramps2/install-sh @@ -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 diff --git a/gramps2/py-compile b/gramps2/py-compile new file mode 100755 index 000000000..0429357ab --- /dev/null +++ b/gramps2/py-compile @@ -0,0 +1,84 @@ +#!/bin/sh + +# py-compile - Compile a Python program +# Copyright 2000, 2001 Free Software Foundation, Inc. + +# 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, 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# called as "py-compile [--basedir DIR] PY_FILES ... + +# GRAMPS-SPECIFIC COMMENTS: +# This is a modified version of the py-compile script distributed with +# GNU automake 1.6. The only difference is that this file has had the +# normal byte-compiling section removed since Gramps only uses optimized +# versions of byte-compiled code. +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 + +# 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 || : + + diff --git a/gramps2/src/.cvsignore b/gramps2/src/.cvsignore new file mode 100644 index 000000000..7fba86ca0 --- /dev/null +++ b/gramps2/src/.cvsignore @@ -0,0 +1,5 @@ +Makefile +*.pyc +*.pyo +gramps.strings +glade.c diff --git a/gramps2/src/.thumbnails/logo.png b/gramps2/src/.thumbnails/logo.png new file mode 100644 index 000000000..a1bc37cf9 Binary files /dev/null and b/gramps2/src/.thumbnails/logo.png differ diff --git a/gramps2/src/.xvpics/family48.png b/gramps2/src/.xvpics/family48.png new file mode 100644 index 000000000..5b54f3102 Binary files /dev/null and b/gramps2/src/.xvpics/family48.png differ diff --git a/gramps2/src/.xvpics/icon-people02d-24x24.png b/gramps2/src/.xvpics/icon-people02d-24x24.png new file mode 100644 index 000000000..b40d17e61 Binary files /dev/null and b/gramps2/src/.xvpics/icon-people02d-24x24.png differ diff --git a/gramps2/src/.xvpics/icon-people02d-48x48.png b/gramps2/src/.xvpics/icon-people02d-48x48.png new file mode 100644 index 000000000..b40d17e61 Binary files /dev/null and b/gramps2/src/.xvpics/icon-people02d-48x48.png differ diff --git a/gramps2/src/.xvpics/people48.png b/gramps2/src/.xvpics/people48.png new file mode 100644 index 000000000..a91135c5c Binary files /dev/null and b/gramps2/src/.xvpics/people48.png differ diff --git a/gramps2/src/.xvpics/people48.xpm b/gramps2/src/.xvpics/people48.xpm new file mode 100644 index 000000000..8d66cad4b Binary files /dev/null and b/gramps2/src/.xvpics/people48.xpm differ diff --git a/gramps2/src/.xvpics/place.png b/gramps2/src/.xvpics/place.png new file mode 100644 index 000000000..fc8316601 Binary files /dev/null and b/gramps2/src/.xvpics/place.png differ diff --git a/gramps2/src/AUTHORS b/gramps2/src/AUTHORS new file mode 100644 index 000000000..afc5ea57a --- /dev/null +++ b/gramps2/src/AUTHORS @@ -0,0 +1,2 @@ +Don Allingham +Don Peterson diff --git a/gramps2/src/AddMedia.py b/gramps2/src/AddMedia.py new file mode 100644 index 000000000..889d90e21 --- /dev/null +++ b/gramps2/src/AddMedia.py @@ -0,0 +1,151 @@ +# +# 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 +# + +""" +Provides the interface to allow a person to add a media object to the database. +""" + +#------------------------------------------------------------------------- +# +# Standard python modules +# +#------------------------------------------------------------------------- +import os + +#------------------------------------------------------------------------- +# +# internationalization +# +#------------------------------------------------------------------------- + +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +from gnome.ui import GnomeErrorDialog +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import RelImage +import RelLib + +#------------------------------------------------------------------------- +# +# AddMediaObject +# +#------------------------------------------------------------------------- +class AddMediaObject: + """ + Displays the Add Media Dialog window, allowing the user to select + a media object from the file system, while providing a description. + """ + + def __init__(self,db,update): + """ + Creates and displays the dialog box + + db - the database in which the new object is to be stored + update - a function to call to update the display + """ + self.db = db + self.glade = gtk.glade.XML(const.imageselFile,"imageSelect") + self.window = self.glade.get_widget("imageSelect") + self.description = self.glade.get_widget("photoDescription") + self.image = self.glade.get_widget("image") + self.file_text = self.glade.get_widget("fname") + self.update = update + self.temp_name = "" + + self.glade.signal_autoconnect({ + "on_savephoto_clicked" : self.on_savephoto_clicked, + "on_name_changed" : self.on_name_changed, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + self.window.editable_enters(self.description) + self.window.show() + + def on_savephoto_clicked(self,obj): + """ + Callback function called with the save button is pressed. + A new media object is created, and added to the database. + """ + filename = self.glade.get_widget("photosel").get_full_path(0) + description = self.description.get_text() + external = self.glade.get_widget("private") + + if os.path.exists(filename) == 0: + msgstr = _("%s is not a valid file name or does not exist.") + GnomeErrorDialog(msgstr % filename) + return + + type = Utils.get_mime_type(filename) + if description == "": + description = os.path.basename(filename) + + mobj = RelLib.Photo() + mobj.setDescription(description) + mobj.setMimeType(type) + self.db.addObject(mobj) + + if external.get_active() == 0: + path = self.db.getSavePath() + name = RelImage.import_media_object(filename,path,mobj.getId()) + mobj.setLocal(1) + else: + name = filename + mobj.setPath(name) + + Utils.modified() + self.update() + Utils.destroy_passed_object(obj) + + def on_name_changed(self,obj): + """ + Called anytime the filename text window changes. Checks to + see if the file exists. If it does, the imgae is loaded into + the preview window. + """ + filename = self.file_text.get_text() + basename = os.path.basename(filename) + (root,ext) = os.path.splitext(basename) + old_title = self.description.get_text() + + if old_title == '' or old_title == self.temp_name: + self.description.set_text(root) + self.temp_name = root + + if os.path.isfile(filename): + type = Utils.get_mime_type(filename) + if type[0:5] == 'image': + image = RelImage.scale_image(filename,const.thumbScale) + self.image.load_imlib(image) + else: + self.image.load_file(Utils.find_icon(type)) diff --git a/gramps2/src/AddSpouse.py b/gramps2/src/AddSpouse.py new file mode 100644 index 000000000..dd06b9892 --- /dev/null +++ b/gramps2/src/AddSpouse.py @@ -0,0 +1,382 @@ +# +# 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 +# +""" +The AddSpouse module provides the AddSpouse class that allows the user to +add a new spouse to the active person. +""" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# internationalization +# +#------------------------------------------------------------------------- +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import RelLib +import const +import Sorter +import Utils +import GrampsCfg + +#------------------------------------------------------------------------- +# +# AddSpouse +# +#------------------------------------------------------------------------- +class AddSpouse: + """ + Displays the AddSpouse dialog, allowing the user to create a new + family with the passed person as one spouse, and another person to + be selected. + """ + def __init__(self,db,person,update,addperson): + """ + Displays the AddSpouse dialog box. + + db - database to which to add the new family + person - the current person, will be one of the parents + update - function that updates the family display + addperson - function that adds a person to the person view + """ + self.db = db + self.update = update + self.person = person + self.addperson = addperson + + self.glade = gtk.glade.XML(const.gladeFile, "spouseDialog") + + self.rel_combo = self.glade.get_widget("rel_combo") + self.relation_type = self.glade.get_widget("rel_type") + self.spouse_list = self.glade.get_widget("spouse_list") + self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.spouse_list.set_model(self.model) + self.selection = self.spouse_list.get_selection() + self.selection.connect('changed',self.select_row) + + self.relation_def = self.glade.get_widget("reldef") + self.ok = self.glade.get_widget('spouse_ok') + + colno = 0 + for title in [ (_('Name'),3,200), + (_('ID'),1,50), + (_('Birth Date'),4,50), + ('',0,50), + ('',0,0)]: + renderer = gtk.CellRendererText () + column = gtk.TreeViewColumn (title[0], renderer, text=colno) + colno = colno + 1 + column.set_clickable (gtk.TRUE) + if title[0] == '': + column.set_clickable(gtk.TRUE) + column.set_visible(gtk.FALSE) + else: + column.set_resizable(gtk.TRUE) + column.set_sort_column_id(title[1]) + column.set_min_width(title[2]) + self.spouse_list.append_column(column) + if colno == 1: + column.clicked() + + self.ok.set_sensitive(0) + + self.rel_combo.set_popdown_strings(const.familyRelations) + title = _("Choose Spouse/Partner of %s") % GrampsCfg.nameof(person) + self.glade.get_widget("spouseTitle").set_text(title) + + self.glade.signal_autoconnect({ + "on_select_spouse_clicked" : self.select_spouse_clicked, + "on_new_spouse_clicked" : self.new_spouse_clicked, + "on_rel_type_changed" : self.relation_type_changed, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + self.relation_type.set_text(_("Married")) + self.relation_type_changed(None) + + def select_row(self,obj): + """ + Called with a row has be unselected. Used to ensable the OK button + when a row has been selected. + """ + + model,iter = self.selection.get_selected() + if iter: + self.ok.set_sensitive(1) + else: + self.ok.set_sensitive(0) + + def new_spouse_clicked(self,obj): + """ + Called when the spouse to be added does not exist, and needs + to be created and added to the database + """ + import QuickAdd + + relation = const.save_frel(self.relation_type.get_text()) + if relation == "Partners": + if self.person.getGender() == RelLib.Person.male: + gen = "male" + else: + gen = "female" + elif self.person.getGender() == RelLib.Person.male: + gen = "female" + else: + gen = "male" + + QuickAdd.QuickAdd(self.db,gen,self.update_list) + + def update_list(self,person): + """ + Updates the potential spouse list after a person has been added + to database. Called by the QuickAdd class when the dialog has + been closed. + """ + self.addperson(person) + self.update_data(person.getId()) + + def select_spouse_clicked(self,obj): + """ + Called when the spouse to be added already exists and has been + selected from the list. + """ + + model,iter = self.selection.get_selected() + if not iter: + return + + row = model.get_path(iter) + id = self.entries[row[0]] + spouse = self.db.getPerson(id) + + # don't do anything if the marriage already exists + for f in self.person.getFamilyList(): + if spouse == f.getMother() or spouse == f.getFather(): + Utils.destroy_passed_object(obj) + return + + Utils.modified() + family = self.db.newFamily() + self.person.addFamily(family) + spouse.addFamily(family) + + if self.person.getGender() == RelLib.Person.male: + family.setMother(spouse) + family.setFather(self.person) + else: + family.setFather(spouse) + family.setMother(self.person) + + family.setRelationship(const.save_frel(self.relation_type.get_text())) + Utils.destroy_passed_object(obj) + self.update(family) + + def relation_type_changed(self,obj): + self.update_data() + + def update_data(self,person = None): + """ + Called whenever the relationship type changes. Rebuilds the + the potential spouse list. + """ + + text = self.relation_type.get_text() + self.relation_def.set_text(const.relationship_def(text)) + + # determine the gender of the people to be loaded into + # the potential spouse list. If Partners is selected, use + # the same gender as the current person. + gender = self.person.getGender() + if text == _("Partners"): + if gender == RelLib.Person.male: + sgender = const.female + else: + sgender = const.male + else: + if gender == RelLib.Person.male: + sgender = const.male + else: + sgender = const.female + + index = 0 + + self.entries = [] + self.model.clear() + for key in self.db.getPersonKeys(): + data = self.db.getPersonDisplay(key) + if data[2] == sgender: + continue + iter = self.model.append() + self.entries.append(key) + self.model.set(iter,0,data[0],1,data[1],2,data[3],3,data[5],4,data[6]) + if person == key: + self.selection.select_iter(iter) + +#------------------------------------------------------------------------- +# +# SetSpouse +# +#------------------------------------------------------------------------- +class SetSpouse: + """ + Displays the AddSpouse dialog, allowing the user to create a new + family with the passed person as one spouse, and another person to + be selected. + """ + def __init__(self,db,person,family,update,addperson): + """ + Displays the AddSpouse dialog box. + + db - database to which to add the new family + person - the current person, will be one of the parents + update - function that updates the family display + addperson - function that adds a person to the person view + """ + self.db = db + self.update = update + self.person = person + self.family = family + self.addperson = addperson + + self.glade = gtk.glade.XML(const.gladeFile, "spouseDialog") + + self.rel_combo = self.glade.get_widget("rel_combo") + self.relation_type = self.glade.get_widget("rel_type") + self.spouse_list = self.glade.get_widget("spouseList") + self.relation_def = self.glade.get_widget("reldef") + + self.rel_combo.set_popdown_strings(const.familyRelations) + title = _("Choose Spouse/Partner of %s") % GrampsCfg.nameof(person) + self.glade.get_widget("spouseTitle").set_text(title) + + self.glade.signal_autoconnect({ + "on_select_spouse_clicked" : self.select_spouse_clicked, + "on_new_spouse_clicked" : self.new_spouse_clicked, + "on_rel_type_changed" : self.relation_type_changed, + "on_combo_insert_text" : Utils.combo_insert_text, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + self.relation_type.set_text(_("Married")) + + def new_spouse_clicked(self,obj): + """ + Called when the spouse to be added does not exist, and needs + to be created and added to the database + """ + import QuickAdd + + relation = const.save_frel(self.relation_type.get_text()) + if relation == "Partners": + if self.person.getGender() == RelLib.Person.male: + gen = "male" + else: + gen = "female" + elif self.person.getGender() == RelLib.Person.male: + gen = "female" + else: + gen = "male" + QuickAdd.QuickAdd(self.db,gen,self.update_list) + + def update_list(self,person): + self.addperson(person) + self.relation_type_changed(self.relation_type) + + def select_spouse_clicked(self,obj): + """ + Called when the spouse to be added already exists and has been + selected from the list. + """ + if len(self.spouse_list.selection) == 0: + return + row = self.spouse_list.selection[0] + spouse = self.db.getPerson(self.spouse_list.get_row_data(row)) + + # don't do anything if the marriage already exists + for f in self.person.getFamilyList(): + if spouse == f.getMother() or spouse == f.getFather(): + Utils.destroy_passed_object(obj) + return + + Utils.modified() + if self.family.getFather() == self.person: + self.family.setMother(spouse) + else: + self.family.setFather(spouse) + + spouse.addFamily(self.family) + + reltype = self.relation_type.get_text() + self.family.setRelationship(const.save_frel(reltype)) + Utils.destroy_passed_object(obj) + self.update(self.family) + + def relation_type_changed(self,obj): + """ + Called whenever the relationship type changes. Rebuilds the + the potential spouse list. + """ + text = obj.get_text() + self.relation_def.set_text(const.relationship_def(text)) + + # determine the gender of the people to be loaded into + # the potential spouse list. If Partners is selected, use + # the same gender as the current person. + gender = self.person.getGender() + if text == _("Partners"): + if gender == RelLib.Person.male: + sgender = const.female + else: + sgender = const.male + else: + if gender == RelLib.Person.male: + sgender = const.male + else: + sgender = const.female + + index = 0 + self.spouse_list.clear() + self.spouse_list.freeze() + for key in self.db.getPersonKeys(): + data = self.db.getPersonDisplay(key) + if data[2] == sgender: + continue + + self.spouse_list.append([data[0],data[3],data[5],data[6]]) + self.spouse_list.set_row_data(index,key) + index = index + 1 + self.spouse_list.thaw() diff --git a/gramps2/src/AddrEdit.py b/gramps2/src/AddrEdit.py new file mode 100644 index 000000000..3ae80f316 --- /dev/null +++ b/gramps2/src/AddrEdit.py @@ -0,0 +1,157 @@ +# +# 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 +# +""" +The AddrEdit module provides the AddressEditor class. This provides a +mechanism for the user to edit address information. +""" + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import Date +import RelLib +import Sources + +from DateEdit import DateEdit +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# AddressEditor class +# +#------------------------------------------------------------------------- +class AddressEditor: + """ + Displays a dialog that allows the user to edit an address. + """ + def __init__(self,parent,addr): + """ + Displays the dialog box. + + parent - The class that called the Address editor. + addr - The address that is to be edited + """ + # Get the important widgets from the glade description + self.top = gtk.glade.XML(const.dialogFile, "addr_edit") + self.window = self.top.get_widget("addr_edit") + self.addr_start = self.top.get_widget("address_start") + self.street = self.top.get_widget("street") + self.city = self.top.get_widget("city") + self.state = self.top.get_widget("state") + self.country = self.top.get_widget("country") + self.postal = self.top.get_widget("postal") + self.note_field = self.top.get_widget("addr_note") + self.priv = self.top.get_widget("priv") + self.slist = self.top.get_widget("slist") + + self.parent = parent + self.addr = addr + + name = parent.person.getPrimaryName().getName() + text = _("Address Editor for %s") % name + self.top.get_widget("addrTitle").set_text(text) + + if self.addr: + self.srcreflist = self.addr.getSourceRefList() + self.addr_start.set_text(self.addr.getDate()) + self.street.set_text(self.addr.getStreet()) + self.city.set_text(self.addr.getCity()) + self.state.set_text(self.addr.getState()) + self.country.set_text(self.addr.getCountry()) + self.postal.set_text(self.addr.getPostal()) + self.priv.set_active(self.addr.getPrivacy()) + self.note_field.set_point(0) + self.note_field.insert_defaults(self.addr.getNote()) + self.note_field.set_word_wrap(1) + else: + self.srcreflist = [] + + self.sourcetab = Sources.SourceTab(self.srcreflist,self.parent, + self.top, self.slist, + self.top.get_widget('add_btn'), + self.top.get_widget('del_btn')) + + date_stat = self.top.get_widget("date_stat") + self.date_check = DateEdit(self.addr_start,date_stat) + + self.top.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_addr_edit_ok_clicked" : self.ok_clicked, + }) + + def ok_clicked(self,obj): + """ + Called when the OK button is pressed. Gets data from the + form and updates the Address data structure. + """ + date = self.addr_start.get_text() + street = self.street.get_text() + city = self.city.get_text() + state = self.state.get_text() + country = self.country.get_text() + postal = self.postal.get_text() + note = self.note_field.get_chars(0,-1) + priv = self.priv.get_active() + + if self.addr == None: + self.addr = RelLib.Address() + self.parent.plist.append(self.addr) + self.addr.setSourceRefList(self.srcreflist) + + self.update(date,street,city,state,country,postal,note,priv) + self.parent.redraw_addr_list() + Utils.destroy_passed_object(obj) + + def check(self,get,set,data): + """Compares a data item, updates if necessary, and sets the + parents lists_changed flag""" + if get() != data: + set(data) + self.parent.lists_changed = 1 + + def update(self,date,street,city,state,country,postal,note,priv): + """Compares the data items, and updates if necessary""" + d = Date.Date() + d.set(date) + + if self.addr.getDate() != d.getDate(): + self.addr.setDate(date) + self.parent.lists_changed = 1 + + self.check(self.addr.getStreet,self.addr.setStreet,street) + self.check(self.addr.getCountry,self.addr.setCountry,country) + self.check(self.addr.getCity,self.addr.setCity,city) + self.check(self.addr.getState,self.addr.setState,state) + self.check(self.addr.getPostal,self.addr.setPostal,postal) + self.check(self.addr.getNote,self.addr.setNote,note) + self.check(self.addr.getPrivacy,self.addr.setPrivacy,priv) + diff --git a/gramps2/src/AttrEdit.py b/gramps2/src/AttrEdit.py new file mode 100644 index 000000000..a0dc436f8 --- /dev/null +++ b/gramps2/src/AttrEdit.py @@ -0,0 +1,151 @@ +# +# 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 +# +""" +The AttrEdit module provides the AddressEditor class. This provides a +mechanism for the user to edit address information. +""" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import Sources +import AutoComp + +from RelLib import Attribute + +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# AttributeEditor class +# +#------------------------------------------------------------------------- +class AttributeEditor: + """ + Displays a dialog that allows the user to edit an attribute. + """ + def __init__(self,parent,attrib,title,list): + """ + Displays the dialog box. + + parent - The class that called the Address editor. + attrib - The attribute that is to be edited + title - The title of the dialog box + list - list of options for the pop down menu + """ + + self.parent = parent + self.attrib = attrib + self.top = gtk.glade.XML(const.dialogFile, "attr_edit") + self.window = self.top.get_widget("attr_edit") + self.type_field = self.top.get_widget("attr_type") + self.slist = self.top.get_widget("slist") + self.value_field = self.top.get_widget("attr_value") + self.note_field = self.top.get_widget("attr_note") + self.attrib_menu = self.top.get_widget("attr_menu") + self.source_field = self.top.get_widget("attr_source") + self.priv = self.top.get_widget("priv") + + if attrib: + self.srcreflist = self.attrib.getSourceRefList() + else: + self.srcreflist = [] + + self.sourcetab = Sources.SourceTab(self.srcreflist,self.parent,self.top, + self.slist, + self.top.get_widget('add_src'), + self.top.get_widget('del_src')) + + title = _("Attribute Editor for %s") % title + self.top.get_widget("attrTitle").set_text(title) + + AutoComp.AutoEntry(self.attrib_menu.entry,list) + + if attrib != None: + self.type_field.set_text(attrib.getType()) + self.value_field.set_text(attrib.getValue()) + self.priv.set_active(attrib.getPrivacy()) + + self.note_field.get_buffer().set_text(attrib.getNote()) + + self.top.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_attr_edit_ok_clicked" : self.on_ok_clicked, + "on_add_src_clicked" : self.add_source, + "on_del_src_clicked" : self.del_source, + }) + + def add_source(self,obj): + pass + + def del_source(self,obj): + pass + + def on_ok_clicked(self,obj): + """ + Called when the OK button is pressed. Gets data from the + form and updates the Attribute data structure. + """ + type = self.type_field.get_text() + value = self.value_field.get_text() + + buf = self.note_field.get_buffer() + note = buf.get_text(buf.get_start_iter(),buf.get_end_iter(),gtk.FALSE) + priv = self.priv.get_active() + + if self.attrib == None: + self.attrib = Attribute() + self.parent.alist.append(self.attrib) + + self.attrib.setSourceRefList(self.srcreflist) + self.update(type,value,note,priv) + + self.parent.redraw_attr_list() + Utils.destroy_passed_object(obj) + + def check(self,get,set,data): + """Compares a data item, updates if necessary, and sets the + parents lists_changed flag""" + if get() != data: + set(data) + self.parent.lists_changed = 1 + + def update(self,type,value,note,priv): + """Compares the data items, and updates if necessary""" + ntype = const.save_pattr(type) + self.check(self.attrib.getType,self.attrib.setType,ntype) + self.check(self.attrib.getValue,self.attrib.setValue,value) + self.check(self.attrib.getNote,self.attrib.setNote,note) + self.check(self.attrib.getPrivacy,self.attrib.setPrivacy,priv) + diff --git a/gramps2/src/AutoComp.py b/gramps2/src/AutoComp.py new file mode 100644 index 000000000..438ee8605 --- /dev/null +++ b/gramps2/src/AutoComp.py @@ -0,0 +1,264 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002 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 +# + +""" +Adds autocompletion to a GtkEntry box, using the passed list of +strings as the possible completions. This work was adapted from code +written by David Hampton. +""" + +__author__ = "David R. Hampton, Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# python modules +# +#------------------------------------------------------------------------- +import string + +#------------------------------------------------------------------------- +# +# GNOME modules +# +#------------------------------------------------------------------------- +import gtk + +#------------------------------------------------------------------------- +# +# AutoCompBase +# +#------------------------------------------------------------------------- +class AutoCompBase: + + def __init__(self,widget,plist,source=None): + """ + Creates a autocompleter for the specified GNOME/GTK widget, using the + list of strings as the completion values. The AutoCompBase class + should never be instantiated on its own. Instead, classes should be + derived from it. + + widget - widget instance the completer is assocated with + plist - List of completion strings + source - If not None, uses the completion values of an already existing AutoCompBase instance + """ + if source: + self.nlist = source.nlist + else: + self.nlist = [] + self.nlist = map((lambda n: (string.lower(n),n)),plist) + self.nlist.sort() + self.nl = "xzsdkdjecsc" + self.l = 0 + + def insert_text(self,entry,new_text,new_text_len,i_dont_care): + """ + Sets up a delayed (0.005 sec) handler for text completion. Text + completion cannot be handled directly in this routine because, for + some reason, the select_region() function doesn't work when called + from signal handlers. Go figure. + + Thanks to iain@nodata.demon.co.uk (in mail from 1999) for the idea + to use a timer to get away from the problems with signal handlers + and the select_region function. + """ + + # One time setup to clear selected region when user moves on + if (not entry.get_data("signal_set")): + entry.set_data("signal_set",1) + entry.connect("focus-out-event", self.lost_focus, entry) + + # Nuke the current timer if the user types fast enough + timer = entry.get_data("timer"); + if (timer): + gtk.timeout_remove(timer) + + # Setup a callback timer so we can operate outside of a signal handler + timer = gtk.timeout_add(5, self.timer_callback, entry) + entry.set_data("timer", timer); + + def lost_focus(self,entry,a,b): + """ + The entry box entry field lost focus. Go clear any selection. Why + this form of a select_region() call works in a signal handler and + the other form doesn't is a mystery. + """ + #entry.select_region(0, 0) + pass + + def timer_callback(self,entry): + """ + Perfroms the actual task of completion. This method should be + overridden in all subclasses + """ + pass + +#------------------------------------------------------------------------- +# +# AutoCombo +# +#------------------------------------------------------------------------- +class AutoCombo(AutoCompBase): + """ + Allows allow completion of the GtkCombo widget with the entries + in the passed string list. This class updates the drop down window + with the values that currently match the substring in the text box. + """ + + def __init__(self,widget,plist,source=None): + """ + Creates a autocompleter for the a GtkCombo widget, using the + list of strings as the completion values. The + + widget - GtkCombo instance the completer is assocated with + plist - List of completion strings + source - If not None, uses the completion values of an already existing + AutoCompBase instance + """ + AutoCompBase.__init__(self,widget,plist,source) + self.entry = widget + widget.entry.connect("insert-text",self.insert_text) + button1 = widget.get_children()[1] + button1.connect("button-press-event",self.build_list) + button1.connect("button-release-event",self.setval) + self.vals = [""] + self.inb = 0 + + def setval(self,widget,event): + """Callback task called on the button release""" + + self.inb = 0 + text = self.entry.entry.get_text() + if self.nl == string.lower(text): + #self.entry.entry.set_position(self.l) + #self.entry.entry.select_region(self.l, -1) + pass + + def build_list(self,widget,event): + """Internal task that builds the popdown strings. This task is called when the + combo button that activates the dropdown menu is pressed + """ + self.inb = 1 + if self.vals[0] == "": + self.entry.set_popdown_strings([self.entry.entry.get_text()]) + else: + self.entry.set_popdown_strings(self.vals) + + def timer_callback(self,entry): + """ + The workhorse routine of file completion. This routine grabs the + current text of the entry box, and grubs through the list item + looking for any case insensitive matches. This routine relies on + public knowledge of the GtkEntry data structure, not on any private + data. + """ + # Clear any timer + timer = entry.get_data("timer"); + if timer: + gtk.timeout_remove(timer) + + if self.inb == 1: + return + + # Get the user's text + typed = entry.get_text() + if (not typed): + return + typed_lc = string.lower(typed) + + if typed_lc == self.nl: + return + + self.l = len(typed_lc) + + self.vals = [] + + # Walk the GtkList in the entry box + for nl,n in self.nlist: + # If typed text is a substring of the label text, then fill in + # the entry field with the full text (and correcting + # capitalization), and then select all the characters that + # don't match. With the user's next keystroke these will be + # replaced if they are incorrect. + if nl[0:self.l] == typed_lc: + self.vals.append(n) + + if len(self.vals) > 0: + n = self.vals[0] + self.nl = string.lower(n) + entry.set_text(n) + #entry.set_position(self.l) + #entry.select_region(self.l, -1) + else: + self.vals = [""] + +#------------------------------------------------------------------------- +# +# AutoEntry +# +#------------------------------------------------------------------------- +class AutoEntry(AutoCompBase): + """ + Allows allow completion of the GtkEntry widget with the entries + in the passed string list. + """ + def __init__(self,widget,plist,source=None): + AutoCompBase.__init__(self,widget,plist,source) + self.entry = widget + self.entry.connect("insert-text",self.insert_text) + + def timer_callback(self,entry): + """ + The workhorse routine of file completion. This routine grabs the + current text of the entry box, and grubs through the list item + looking for any case insensitive matches. This routine relies on + public knowledge of the GtkEntry data structure, not on any private + data. + """ + # Clear any timer + timer = entry.get_data("timer"); + if (timer): + gtk.timeout_remove(timer) + + # Get the user's text + typed = entry.get_text() + if (not typed): + return + typed_lc = string.lower(typed) + + if typed_lc == self.nl: + return + + self.l = len(typed_lc) + + # Walk the GtkList in the entry box + for nl,n in self.nlist: + # If typed text is a substring of the label text, then fill in + # the entry field with the full text (and correcting + # capitalization), and then select all the characters that + # don't match. With the user's next keystroke these will be + # replaced if they are incorrect. + if nl[0:self.l] == typed_lc: + self.nl = nl + entry.set_text(n) + #entry.set_position(self.l) + #entry.select_region(self.l, -1) + return + diff --git a/gramps2/src/Bookmarks.py b/gramps2/src/Bookmarks.py new file mode 100644 index 000000000..64da9c652 --- /dev/null +++ b/gramps2/src/Bookmarks.py @@ -0,0 +1,177 @@ +# +# 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" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk +import gnome.ui + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import Utils +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# Bookmarks +# +#------------------------------------------------------------------------- +class Bookmarks : + "Handle the bookmarks interface for Gramps" + + def __init__(self,bookmarks,menu,callback): + """ + Creates a the bookmark editor + + bookmarks - list of People + menu - parent menu to attach users + callback - task to connect to the menu item as a callback + """ + self.menu = menu + self.bookmarks = bookmarks + self.callback = callback + self.redraw() + + def redraw(self): + """Create the pulldown menu""" + if len(self.bookmarks) > 0: + self.myMenu = gtk.Menu() + for person in self.bookmarks: + self.add_to_menu(person) + 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): + """appends the person to the bottom of the bookmarks""" + if person not in self.bookmarks: + Utils.modified() + self.bookmarks.append(person) + self.redraw() + + def add_to_menu(self,person): + """adds a person's name to the drop down menu""" + item = gtk.MenuItem(person.getPrimaryName().getName()) + item.connect("activate", self.callback, person) + item.show() + self.myMenu.append(item) + + def draw_window(self): + """Draws the bookmark dialog box""" + title = "%s - GRAMPS" % _("Edit Bookmarks") + self.top = gtk.Dialog(title) + self.top.set_default_size(350,250) + self.top.vbox.set_spacing(5) + self.top.vbox.pack_start(gtk.Label(_("Edit Bookmarks")),0,0,5) + self.top.vbox.pack_start(gtk.HSeparator(),0,0,5) + box = gtk.HBox() + self.top.vbox.pack_start(box,1,1,5) + self.namelist = gtk.CList(1) + slist = gtk.ScrolledWindow() + slist.add_with_viewport(self.namelist) + slist.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + box.pack_start(slist,1,1,5) + bbox = gtk.VButtonBox() + bbox.set_layout(gtk.BUTTONBOX_START) + up = gtk.Button() + up.set_label(gtk.STOCK_GO_UP) + up.set_use_stock(1) + down = gtk.Button() + down.set_label(gtk.STOCK_GO_DOWN) + down.set_use_stock(1) + delete = gtk.Button() + delete.set_label(gtk.STOCK_REMOVE) + delete.set_use_stock(1) + up.connect('clicked', self.up_clicked) + down.connect('clicked',self.down_clicked) + delete.connect('clicked',self.delete_clicked) + self.top.add_button(gtk.STOCK_OK,0) + self.top.add_button(gtk.STOCK_CANCEL,1) + bbox.add(up) + bbox.add(down) + bbox.add(delete) + box.pack_start(bbox,0,0,5) + self.top.show_all() + + def edit(self): + """ + display the bookmark editor. + + The current bookmarked people are inserted into the namelist, + attaching the person object to the corresponding row. The currently + selected row is attached to the name list. This is either 0 if the + list is not empty, or -1 if it is. + """ + self.draw_window() + index = 0 + for person in self.bookmarks: + self.namelist.append([person.getPrimaryName().getName()]) + self.namelist.set_row_data(index,person) + index = index + 1 + + if self.top.run() == 0 : + self.ok_clicked() + else: + self.cancel_clicked() + + def delete_clicked(self,obj): + """Removes the current selection from the list""" + if len(self.namelist.selection) > 0: + self.namelist.remove(self.namelist.selection[0]) + + def up_clicked(self,obj): + """Moves the current selection up one row""" + if len(self.namelist.selection) > 0: + index = self.namelist.selection[0] + self.namelist.swap_rows(index-1,index) + + def down_clicked(self,obj): + """Moves the current selection down one row""" + if len(self.namelist.selection) > 0: + index = self.namelist.selection[0] + if index != self.namelist.rows-1: + self.namelist.swap_rows(index+1,index) + + def ok_clicked(self): + """Saves the current bookmarks from the list""" + del self.bookmarks[0:] + for index in range(0,self.namelist.rows): + person = self.namelist.get_row_data(index) + if person: + self.bookmarks.append(person) + self.redraw() + self.top.destroy() + + def cancel_clicked(self): + """Closes the current window""" + self.top.destroy() diff --git a/gramps2/src/Calendar.py b/gramps2/src/Calendar.py new file mode 100644 index 000000000..56d610e60 --- /dev/null +++ b/gramps2/src/Calendar.py @@ -0,0 +1,513 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2001 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 +# +""" +Calendar conversion routines for GRAMPS. + +The original algorithms for this module came from Scott E. Lee's +C implementation. The original C source can be found at Scott's +web site at http://www.scottlee.com +""" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +_FR_SDN_OFFSET = 2375474 +_FR_DAYS_PER_4_YEARS = 1461 +_FR_DAYS_PER_MONTH = 30 +_FR_FIRST_VALID = 2375840 +_FR_LAST_VALID = 2380952 +_GR_SDN_OFFSET = 32045 +_GR_DAYS_PER_5_MONTHS = 153 +_GR_DAYS_PER_4_YEARS = 1461 +_GR_DAYS_PER_400_YEARS = 146097 +_J_SDN_OFFSET = 32083 +_J_DAYS_PER_5_MONTHS = 153 +_J_DAYS_PER_4_YEARS = 1461 + +_HALAKIM_PER_HOUR = 1080 +_HALAKIM_PER_DAY = 25920 +_HALAKIM_PER_LUNAR_CYCLE = ((29 * _HALAKIM_PER_DAY) + 13753) +_HALAKIM_PER_METONIC_CYCLE = (_HALAKIM_PER_LUNAR_CYCLE * (12 * 19 + 7)) + +_H_SDN_OFFSET = 347997 +_NEW_MOON_OF_CREATION = 31524 + +_SUNDAY = 0 +_MONDAY = 1 +_TUESDAY = 2 +_WEDNESDAY= 3 +#_THURSDAY = 4 +_FRIDAY = 5 +#_SATURDAY = 6 + +_NOON = (18 * _HALAKIM_PER_HOUR) +_AM3_11_20 = ((9 * _HALAKIM_PER_HOUR) + 204) +_AM9_32_43 = ((15 * _HALAKIM_PER_HOUR) + 589) + +#------------------------------------------------------------------------- +# +# Conversion tables +# +#------------------------------------------------------------------------- +monthsPerYear = [ + 12, 12, 13, 12, 12, 13, 12, 13, 12, + 12, 13, 12, 12, 13, 12, 12, 13, 12, 13 +] + +yearOffset = [ + 0, 12, 24, 37, 49, 61, 74, 86, 99, 111, 123, + 136, 148, 160, 173, 185, 197, 210, 222 +] + +#------------------------------------------------------------------------- +# +# Tasks +# +#------------------------------------------------------------------------- + +def french_to_sdn(y,m,d): + """Converts a French Republican Calendar date to an SDN number""" + if (y < 1 or y > 14 or m < 1 or m > 13 or d < 1 or d > 30): + return 0 + return (y*_FR_DAYS_PER_4_YEARS)/4+(m-1)*_FR_DAYS_PER_MONTH+d+_FR_SDN_OFFSET + +def sdn_to_french(sdn): + """Converts an SDN number to a French Republican Calendar date""" + if (sdn < _FR_FIRST_VALID or sdn > _FR_LAST_VALID) : + return (0,0,0) + temp = (sdn-_FR_SDN_OFFSET)*4 - 1 + year = temp/_FR_DAYS_PER_4_YEARS + dayOfYear = (temp%_FR_DAYS_PER_4_YEARS)/4 + month = (dayOfYear/_FR_DAYS_PER_MONTH)+1 + day = (dayOfYear%_FR_DAYS_PER_MONTH)+1 + return (year,month,day) + + +def sdn_to_gregorian(sdn): + """Converts an SDN number to a gregorial date""" + if sdn <= 0: + return (0,0,0) + + temp = (sdn + _GR_SDN_OFFSET) * 4 - 1 + + # Calculate the century (year/100) + century = temp / _GR_DAYS_PER_400_YEARS + + # Calculate the year and day of year (1 <= dayOfYear <= 366) + + temp = ((temp % _GR_DAYS_PER_400_YEARS) / 4) * 4 + 3 + year = (century * 100) + (temp / _GR_DAYS_PER_4_YEARS) + dayOfYear = (temp % _GR_DAYS_PER_4_YEARS) / 4 + 1 + + # Calculate the month and day of month + temp = dayOfYear * 5 - 3 + month = temp / _GR_DAYS_PER_5_MONTHS + day = (temp % _GR_DAYS_PER_5_MONTHS) / 5 + 1 + + # Convert to the normal beginning of the year + if month < 10 : + month = month + 3 + else: + year = year + 1 + month = month + 9 + + # Adjust to the B.C./A.D. type numbering + year = year - 4800 + if year <= 0: + year = year - 1 + + return (year,month,day) + +def gregorian_to_sdn(iyear,imonth,iday): + """Converts a gregorian date to an SDN number""" + # check for invalid dates + if iyear==0 or iyear<-4714 or imonth<=0 or imonth>12 or iday<=0 or iday>31: + return 0 + + # check for dates before SDN 1 (Nov 25, 4714 B.C.) + if iyear == -4714: + if imonth < 11 or imonth == 11 and iday < 25: + return 0 + + if iyear < 0: + year = iyear + 4801 + else: + year = iyear + 4800 + + # Adjust the start of the year + + if imonth > 2: + month = imonth - 3 + else: + month = imonth + 9 + year = year - 1 + + return( ((year / 100) * _GR_DAYS_PER_400_YEARS) / 4 + + ((year % 100) * _GR_DAYS_PER_4_YEARS) / 4 + + (month * _GR_DAYS_PER_5_MONTHS + 2) / 5 + + iday + - _GR_SDN_OFFSET ); + + +def sdn_to_julian(sdn): + """Converts an SDN number to a Julian date""" + if sdn <= 0 : + return (0,0,0) + + temp = (sdn + _J_SDN_OFFSET) * 4 - 1 + + # Calculate the year and day of year (1 <= dayOfYear <= 366) + year = temp / _J_DAYS_PER_4_YEARS + dayOfYear = (temp % _J_DAYS_PER_4_YEARS) / 4 + 1 + + # Calculate the month and day of month + temp = dayOfYear * 5 - 3; + month = temp / _J_DAYS_PER_5_MONTHS; + day = (temp % _J_DAYS_PER_5_MONTHS) / 5 + 1; + + # Convert to the normal beginning of the year + if month < 10: + month = month + 3 + else: + year = year + 1 + month = month - 9 + + # Adjust to the B.C./A.D. type numbering + year = year - 4800 + if year <= 0: + year = year - 1 + + return (year,month,day) + +def julian_to_sdn(iyear,imonth,iday): + """Converts a Julian calendar date to an SDN number""" + + # check for invalid dates + if iyear==0 or iyear<-4713 or imonth<=0 or imonth>12 or iday<=0 or iday>31: + return 0 + + # check for dates before SDN 1 (Jan 2, 4713 B.C.) + if iyear == -4713: + if imonth == 1 and iday == 1: + return 0 + + # Make year always a positive number + if iyear < 0: + year = iyear + 4801 + else: + year = iyear + 4800 + + # Adjust the start of the year + if imonth > 2: + month = imonth - 3 + else: + month = imonth + 9 + year = year - 1 + + return (year*_J_DAYS_PER_4_YEARS)/4 + (month*_J_DAYS_PER_5_MONTHS+2)/5 + iday - _J_SDN_OFFSET + +def Tishri1(metonicYear, moladDay, moladHalakim): + + tishri1 = moladDay + dow = tishri1 % 7 + leapYear = metonicYear == 2 or metonicYear == 5 or metonicYear == 7 or \ + metonicYear == 10 or metonicYear == 13 or metonicYear == 16 or \ + metonicYear == 18 + lastWasLeapYear = metonicYear == 3 or metonicYear == 6 or metonicYear == 8 or \ + metonicYear == 11 or metonicYear == 14 or metonicYear == 17 or \ + metonicYear == 0 + + # Apply rules 2, 3 and 4. + if ((moladHalakim >= _NOON) or + ((not leapYear) and dow == _TUESDAY and moladHalakim >= _AM3_11_20) or + (lastWasLeapYear and dow == _MONDAY and moladHalakim >= _AM9_32_43)) : + tishri1 = tishri1 + 1 + dow = dow + 1 + if dow == 7: + dow = 0 + + # Apply rule 1 after the others because it can cause an additional + # delay of one day + + if dow == _WEDNESDAY or dow == _FRIDAY or dow == _SUNDAY: + tishri1 = tishri1 + 1 + + return tishri1 + + +def MoladOfMetonicCycle(metonicCycle): + + # Start with the time of the first molad after creation. + + r1 = _NEW_MOON_OF_CREATION; + + # Calculate metonicCycle * HALAKIM_PER_METONIC_CYCLE. The upper 32 + # bits of the result will be in r2 and the lower 16 bits will be + # in r1. + + r1 = r1 + (metonicCycle * (_HALAKIM_PER_METONIC_CYCLE & 0xFFFF)) + r2 = r1 >> 16 + r2 = r2 + (metonicCycle * ((_HALAKIM_PER_METONIC_CYCLE >> 16) & 0xFFFF)) + + # Calculate r2r1 / HALAKIM_PER_DAY. The remainder will be in r1, the + # upper 16 bits of the quotient will be in d2 and the lower 16 bits + # will be in d1. + + d2 = r2 / _HALAKIM_PER_DAY + r2 = r2 - (d2 * _HALAKIM_PER_DAY) + r1 = (r2 << 16) | (r1 & 0xFFFF) + d1 = r1 / _HALAKIM_PER_DAY + r1 = r1 - ( d1 * _HALAKIM_PER_DAY) + + MoladDay = (d2 << 16) | d1 + MoladHalakim = r1 + + return (MoladDay,MoladHalakim) + +def FindTishriMolad(inputDay): + + # Estimate the metonic cycle number. Note that this may be an under + # estimate because there are 6939.6896 days in a metonic cycle not + # 6940, but it will never be an over estimate. The loop below will + # correct for any error in this estimate. */ + + metonicCycle = (inputDay + 310) / 6940 + + # Calculate the time of the starting molad for this metonic cycle. */ + + (moladDay, moladHalakim) = MoladOfMetonicCycle(metonicCycle) + + # If the above was an under estimate, increment the cycle number until + # the correct one is found. For modern dates this loop is about 98.6% + # likely to not execute, even once, because the above estimate is + # really quite close. + + while moladDay < (inputDay - 6940 + 310): + metonicCycle = metonicCycle + 1 + moladHalakim = moladHalakim + _HALAKIM_PER_METONIC_CYCLE + moladDay = moladDay + ( moladHalakim / _HALAKIM_PER_DAY) + moladHalakim = moladHalakim % _HALAKIM_PER_DAY + + # Find the molad of Tishri closest to this date. + + for metonicYear in range(0,18): + if moladDay > inputDay - 74: + break + + moladHalakim = moladHalakim + \ + (_HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear]) + moladDay = moladDay + (moladHalakim / _HALAKIM_PER_DAY) + moladHalakim = moladHalakim % _HALAKIM_PER_DAY + else: + metonicYear = metonicYear + 1 + return (metonicCycle, metonicYear, moladDay, moladHalakim) + +def FindStartOfYear(year): + + pMetonicCycle = (year - 1) / 19; + pMetonicYear = (year - 1) % 19; + (pMoladDay, pMoladHalakim) = MoladOfMetonicCycle(pMetonicCycle) + + pMoladHalakim = pMoladHalakim + (_HALAKIM_PER_LUNAR_CYCLE * yearOffset[pMetonicYear]) + pMoladDay = pMoladDay + (pMoladHalakim / _HALAKIM_PER_DAY) + pMoladHalakim = pMoladHalakim % _HALAKIM_PER_DAY + + pTishri1 = Tishri1(pMetonicYear, pMoladDay, pMoladHalakim); + + return (pMetonicCycle, pMetonicYear, pMoladDay, pMoladHalakim, pTishri1) + +def sdn_to_jewish(sdn): + """Converts an SDN number to a Julian calendar date""" + + if sdn <= _H_SDN_OFFSET : + return (0,0,0) + + inputDay = sdn - _H_SDN_OFFSET + + (metonicCycle, metonicYear, day, halakim) = FindTishriMolad(inputDay) + tishri1 = Tishri1(metonicYear, day, halakim); + + if inputDay >= tishri1: + # It found Tishri 1 at the start of the year + + pYear = (metonicCycle * 19) + metonicYear + 1 + if inputDay < tishri1 + 59: + if inputDay < tishri1 + 30: + pMonth = 1 + pDay = inputDay - tishri1 + 1 + else: + pMonth = 2 + pDay = inputDay - tishri1 - 29 + return (pYear, pMonth, pDay) + + # We need the length of the year to figure this out, so find + # Tishri 1 of the next year. */ + + halakim = halakim + (_HALAKIM_PER_LUNAR_CYCLE * monthsPerYear[metonicYear]) + day = day + (halakim / _HALAKIM_PER_DAY) + halakim = halakim % _HALAKIM_PER_DAY; + tishri1After = Tishri1((metonicYear + 1) % 19, day, halakim); + else: + # It found Tishri 1 at the end of the year. + + pYear = metonicCycle * 19 + metonicYear + if inputDay >= tishri1 - 177: + # It is one of the last 6 months of the year. + if inputDay > tishri1 - 30: + pMonth = 13 + pDay = inputDay - tishri1 + 30 + elif inputDay > tishri1 - 60: + pMonth = 12 + pDay = inputDay - tishri1 + 60 + elif inputDay > tishri1 - 89: + pMonth = 11 + pDay = inputDay - tishri1 + 89 + elif inputDay > tishri1 - 119: + pMonth = 10 + pDay = inputDay - tishri1 + 119 + elif inputDay > tishri1 - 148: + pMonth = 9 + pDay = inputDay - tishri1 + 148 + else: + pMonth = 8 + pDay = inputDay - tishri1 + 178 + return (pYear,pMonth,pDay) + else: + if monthsPerYear[(pYear - 1) % 19] == 13: + pMonth = 7 + pDay = inputDay - tishri1 + 207 + if pDay > 0: + return (pYear,pMonth,pDay) + pMonth = pMonth - 1 + pDay = pDay + 30 + if pDay > 0: + return (pYear,pMonth,pDay) + pMonth = pMonth - 1 + pDay = pDay + 30 + else: + pMonth = 6 + pDay = inputDay - tishri1 + 207 + if pDay > 0: + return (pYear,pMonth,pDay) + pMonth = pMonth - 1 + pDay = pDay + 30 + + if pDay > 0: + return (pYear,pMonth,pDay) + pMonth = pMonth - 1 + pDay = pDay + 29 + if pDay > 0: + return (pYear,pMonth,pDay) + + # We need the length of the year to figure this out, so find + # Tishri 1 of this year. */ + tishri1After = tishri1; + (metonicCycle,metonicYear,day,halakim) = FindTishriMolad(day-365) + tishri1 = Tishri1(metonicYear, day, halakim) + + yearLength = tishri1After - tishri1; + day = inputDay - tishri1 - 29; + if yearLength == 355 or yearLength == 385 : + # Heshvan has 30 days + if day <= 30: + pMonth = 2 + pDay = day + return (pYear,pMonth,pDay) + day = day - 30 + else: + # Heshvan has 29 days + if day <= 29: + pMonth = 2 + pDay = day + return (pYear,pMonth,pDay) + + day = day - 29 + + # It has to be Kislev + return (pYear,3,day) + + +def jewish_to_sdn(year, month, day): + """Converts a Jewish calendar date to an SDN number""" + if year <= 0 or day <= 0 or day > 30 : + return 0 + + if month == 1 or month == 2: + # It is Tishri or Heshvan - don't need the year length. + (metonicCycle,metonicYear,moladDay,moladHalakim,tishri1) = FindStartOfYear(year) + if month == 1: + sdn = tishri1 + day - 1 + else: + sdn = tishri1 + day + 29 + elif month == 3: + # It is Kislev - must find the year length. + + # Find the start of the year. + (metonicCycle,metonicYear,moladDay,moladHalakim,tishri1) = FindStartOfYear(year) + + # Find the end of the year. + moladHalakim = moladHalakim + (_HALAKIM_PER_LUNAR_CYCLE*monthsPerYear[metonicYear]) + moladDay = moladDay + (moladHalakim / _HALAKIM_PER_DAY) + moladHalakim = moladHalakim % _HALAKIM_PER_DAY + tishri1After = Tishri1((metonicYear + 1) % 19, moladDay, moladHalakim) + + yearLength = tishri1After - tishri1 + + if yearLength == 355 or yearLength == 385: + sdn = tishri1 + day + 59 + else: + sdn = tishri1 + day + 58 + elif month == 4 or month == 5 or month == 6: + # It is Tevet, Shevat or Adar I - don't need the year length + + (metonicCycle,metonicYear,moladDay,moladHalakim,tishri1After) = FindStartOfYear(year+1) + + if monthsPerYear[(year - 1) % 19] == 12: + lengthOfAdarIAndII = 29 + else: + lengthOfAdarIAndII = 59 + + if month == 4: + sdn = tishri1After + day - lengthOfAdarIAndII - 237 + elif month == 5: + sdn = tishri1After + day - lengthOfAdarIAndII - 208 + else: + sdn = tishri1After + day - lengthOfAdarIAndII - 178 + else: + # It is Adar II or later - don't need the year length. + (metonicCycle,metonicYear,moladDay,moladHalakim,tishri1After) = FindStartOfYear(year+1) + + if month == 7: + sdn = tishri1After + day - 207 + elif month == 8: + sdn = tishri1After + day - 178 + elif month == 9: + sdn = tishri1After + day - 148 + elif month == 10: + sdn = tishri1After + day - 119 + elif month == 11: + sdn = tishri1After + day - 89 + elif month == 12: + sdn = tishri1After + day - 60 + elif month == 13: + sdn = tishri1After + day - 30 + else: + return 0 + return sdn + _H_SDN_OFFSET diff --git a/gramps2/src/ChangeLog b/gramps2/src/ChangeLog new file mode 100644 index 000000000..e69de29bb diff --git a/gramps2/src/ChooseParents.py b/gramps2/src/ChooseParents.py new file mode 100644 index 000000000..f3a199f1d --- /dev/null +++ b/gramps2/src/ChooseParents.py @@ -0,0 +1,440 @@ +# +# 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 +# + +""" +ChooseParents interface allows users to select the paretns of an +individual. +""" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# internationalization +# +#------------------------------------------------------------------------- +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import RelLib +import const +import sort +import Utils +import GrampsCfg + +#------------------------------------------------------------------------- +# +# ChooseParents +# +#------------------------------------------------------------------------- +class ChooseParents: + """ + Displays the Choose Parents dialog box, allowing the parents + to be edited. + """ + def __init__(self,db,person,family,family_update,full_update): + """ + Creates a ChoosePerson dialog box. + + db - database associated the person + person - person whose parents we are selecting + family - current family + family_update - task that updates the family display + full_update - task that updates the main display + """ + self.db = db + self.person = person + self.family = family + self.family_update = family_update + self.full_update = full_update + self.old_type = "" + self.type = "" + + if self.family: + self.father = self.family.getFather() + self.mother = self.family.getMother() + else: + self.mother = None + self.father = None + + self.glade = gtk.glade.XML(const.gladeFile,"familyDialog") + self.top = self.glade.get_widget("familyDialog") + self.mother_rel = self.glade.get_widget("mrel") + self.father_rel = self.glade.get_widget("frel") + self.fcombo = self.glade.get_widget("prel_combo") + self.prel = self.glade.get_widget("prel") + self.title = self.glade.get_widget("chooseTitle") + self.father_list = self.glade.get_widget("father_list") + self.mother_list = self.glade.get_widget("mother_list") + self.flabel = self.glade.get_widget("flabel") + self.mlabel = self.glade.get_widget("mlabel") + self.fcombo.set_popdown_strings(const.familyRelations) + + + self.fmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.father_list.set_model(self.fmodel) + self.fselection = self.father_list.get_selection() + self.fselection.connect('changed',self.father_list_select_row) + + self.mmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.mother_list.set_model(self.mmodel) + self.mselection = self.mother_list.get_selection() + self.mselection.connect('changed',self.mother_list_select_row) + + self.build_list(self.father_list) + self.build_list(self.mother_list) + + for (f,mr,fr) in self.person.getParentList(): + if f == self.family: + self.mother_rel.set_text(_(mr)) + self.father_rel.set_text(_(fr)) + break + else: + self.mother_rel.set_text(_("Birth")) + self.father_rel.set_text(_("Birth")) + + if self.family: + self.type = self.family.getRelationship() + else: + self.type = "Married" + + self.prel.set_text(_(self.type)) + self.redraw() + + self.glade.signal_autoconnect({ + "on_save_parents_clicked" : self.save_parents_clicked, + "on_add_parent_clicked" : self.add_parent_clicked, + "on_prel_changed" : self.parent_relation_changed, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + text = _("Choose the Parents of %s") % GrampsCfg.nameof(self.person) + self.title.set_text(text) + + def build_list(self,clist): + colno = 0 + for title in [ (_('Name'),3,200), + (_('ID'),1,50), + (_('Birth Date'),4,50), + ('',0,50), + ('',0,0)]: + renderer = gtk.CellRendererText () + column = gtk.TreeViewColumn (title[0], renderer, text=colno) + colno = colno + 1 + column.set_clickable (gtk.TRUE) + if title[0] == '': + column.set_clickable(gtk.TRUE) + column.set_visible(gtk.FALSE) + else: + column.set_resizable(gtk.TRUE) + column.set_sort_column_id(title[1]) + column.set_min_width(title[2]) + clist.append_column(column) + if colno == 1: + column.clicked() + + def redraw(self): + """Redraws the potential father and mother lists""" + + self.fmodel.clear() + self.mmodel.clear() + + pkey = self.person.getId() + gender = self.person.getGender() + if self.father: + fid = self.father.getId() + else: + fid = None + if self.mother: + mid = self.mother.getId() + else: + mid = None + + for key in self.db.getPersonKeys(): + if pkey == key: + continue + if gender == const.unknown: + continue + + dinfo = self.db.getPersonDisplay(key) + if self.type == "Partners": + self.set_data(self.fmodel,self.fselection,dinfo,fid) + self.set_data(self.mmodel,self.mselection,dinfo,mid) + elif dinfo[2] == const.male: + self.set_data(self.fmodel,self.fselection,dinfo,fid) + else: + self.set_data(self.mmodel,self.mselection,dinfo,mid) + + if self.type == "Partners": + self.mlabel.set_label(_("Parent")) + self.flabel.set_label(_("Parent")) + else: + self.mlabel.set_label(_("Mother")) + self.flabel.set_label(_("Father")) + + def set_data(self,model,selection,dinfo,key): + iter = model.append() + model.set(iter,0,dinfo[0],1,dinfo[1],2,dinfo[3],3,dinfo[5],4,dinfo[6]) + if key == dinfo[1]: + selection.select_iter(iter) + + def parent_relation_changed(self,obj): + """Called everytime the parent relationship information is changegd""" + self.old_type = self.type + self.type = const.save_frel(obj.get_text()) + if self.old_type == "Partners" or self.type == "Partners": + self.redraw() + + def find_family(self,father,mother): + """ + Finds the family associated with the father and mother. + If one does not exist, it is created. + """ + if not father and not mother: + return None + + families = self.db.getFamilyMap().values() + for family in families: + if family.getFather() == father and family.getMother() == mother: + return family + elif family.getFather() == mother and family.getMother() == father: + return family + + family = self.db.newFamily() + family.setFather(father) + family.setMother(mother) + family.addChild(self.person) + + if father: + father.addFamily(family) + if mother: + mother.addFamily(family) + return family + + def mother_list_select_row(self,obj): + """Called when a row is selected in the mother list. Sets the + active mother based off the id associated with the row.""" + + model, iter = self.mselection.get_selected() + if iter: + id = model.get_value(iter,1) + self.mother = self.db.getPerson(id) + else: + self.mother = None + + def father_list_select_row(self,obj): + """Called when a row is selected in the father list. Sets the + active father based off the id associated with the row.""" + model, iter = self.fselection.get_selected() + if iter: + id = model.get_value(iter,1) + self.father = self.db.getPerson(id) + else: + self.father = None + + def save_parents_clicked(self,obj): + """ + Called with the OK button nis pressed. Saves the selected people as parents + of the main perosn. + """ + mother_rel = const.childRelations[self.mother_rel.get_text()] + father_rel = const.childRelations[self.father_rel.get_text()] + + if self.father or self.mother: + if self.mother and not self.father: + if self.mother.getGender() == RelLib.Person.male: + self.father = self.mother + self.mother = None + self.family = self.find_family(self.father,self.mother) + elif self.father and not self.mother: + if self.father.getGender() == RelLib.Person.female: + self.mother = self.father + self.father = None + self.family = self.find_family(self.father,self.mother) + elif self.mother.getGender() != self.father.getGender(): + if self.type == "Partners": + self.type = "Unknown" + if self.father.getGender() == RelLib.Person.female: + x = self.father + self.father = self.mother + self.mother = x + self.family = self.find_family(self.father,self.mother) + else: + self.type = "Partners" + self.family = self.find_family(self.father,self.mother) + else: + self.family = None + + Utils.destroy_passed_object(obj) + if self.family: + self.family.setRelationship(self.type) + self.change_family_type(self.family,mother_rel,father_rel) + self.family_update(None) + + def add_new_parent(self,person): + """Adds a new person to either the father list or the mother list, + depending on the gender of the person.""" + id = person.getId() + self.type = const.save_frel(self.prel.get_text()) + dinfo = self.db.getPersonDisplay(id) + rdata = [dinfo[0],dinfo[3],dinfo[5],dinfo[6]] + + if self.type == "Partners": + self.parent_relation_changed(self.prel) + elif person.getGender() == RelLib.Person.male: + self.father_list.insert(0,rdata) + self.father_list.set_row_data(0,id) + self.father_list.select_row(0,0) + self.father_list.sort() + self.father_list.moveto(self.father_list.selection[0],0) + else: + self.mother_list.insert(0,rdata) + self.mother_list.set_row_data(0,id) + self.mother_list.select_row(0,0) + self.mother_list.moveto(0,0) + self.mother_list.sort() + self.mother_list.moveto(self.mother_list.selection[0],0) + self.full_update() + + def add_parent_clicked(self,obj): + """Called with the Add New Person button is pressed. Calls the QuickAdd + class to create a new person.""" + + import QuickAdd + QuickAdd.QuickAdd(self.db,"male",self.add_new_parent) + + def change_family_type(self,family,mother_rel,father_rel): + """ + Changes the family type of the specified family. If the family + is None, the the relationship type shoud be deleted. + """ + if self.person not in family.getChildList(): + family.addChild(self.person) + for fam in self.person.getParentList(): + if family == fam[0]: + if mother_rel == fam[1] and father_rel == fam[2]: + return + if mother_rel != fam[1] or father_rel != fam[2]: + self.person.removeAltFamily(family) + self.person.addAltFamily(family,mother_rel,father_rel) + break + else: + self.person.addAltFamily(family,mother_rel,father_rel) + Utils.modified() + + +class ModifyParents: + def __init__(self,db,person,family,family_update,full_update): + """ + Creates a ChoosePerson dialog box. + + db - database associated the person + person - person whose parents we are selecting + family - current family + family_update - task that updates the family display + full_update - task that updates the main display + """ + self.db = db + self.person = person + self.family = family + self.family_update = family_update + self.full_update = full_update + + self.father = self.family.getFather() + self.mother = self.family.getMother() + + self.glade = gtk.glade.XML(const.gladeFile,"modparents") + self.top = self.glade.get_widget("modparents") + self.mother_rel = self.glade.get_widget("mrel") + self.father_rel = self.glade.get_widget("frel") + self.title = self.glade.get_widget("title") + self.flabel = self.glade.get_widget("flabel") + self.mlabel = self.glade.get_widget("mlabel") + + self.orig_mrel = _("Birth") + self.orig_frel = _("Birth") + for (f,mr,fr) in self.person.getParentList(): + if f == self.family: + self.orig_mrel = _(mr) + self.orig_frel = _(fr) + + self.mother_rel.set_text(self.orig_mrel) + self.father_rel.set_text(self.orig_frel) + + self.glade.signal_autoconnect({ + "on_save_parents_clicked" : self.save_parents_clicked, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + text = _("Modify the Parents of %s") % GrampsCfg.nameof(self.person) + self.title.set_text(text) + self.title.set_use_markup(gtk.TRUE) + + if self.family.getRelationship() == "Partners": + self.mlabel.set_label(_("Parent")) + self.flabel.set_label(_("Parent")) + else: + self.mlabel.set_label(_("Mother")) + self.flabel.set_label(_("Father")) + + + if self.father: + self.glade.get_widget("fname").set_text(self.father.getPrimaryName().getName()) + else: + self.father_rel.set_senstive(0) + + if self.father: + self.glade.get_widget("mname").set_text(self.mother.getPrimaryName().getName()) + else: + self.mother_rel.set_senstive(0) + + + def save_parents_clicked(self,obj): + """ + Called with the OK button nis pressed. Saves the selected people as parents + of the main perosn. + """ + mother_rel = const.childRelations[self.mother_rel.get_text()] + father_rel = const.childRelations[self.father_rel.get_text()] + + Utils.destroy_passed_object(self.top) + if mother_rel != self.orig_mrel or father_rel != self.orig_frel: + self.person.removeAltFamily(self.family) + self.person.addAltFamily(self.family,mother_rel,father_rel) + self.family_update(None) + Utils.modified() + diff --git a/gramps2/src/Date.py b/gramps2/src/Date.py new file mode 100644 index 000000000..3aa6421d0 --- /dev/null +++ b/gramps2/src/Date.py @@ -0,0 +1,1037 @@ +# +# 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 dates" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# python modules +# +#------------------------------------------------------------------------- +from re import IGNORECASE, compile +import string +import time + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import Calendar +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# Calendar Mappings +# +#------------------------------------------------------------------------- +GREGORIAN = 0 +JULIAN = 1 +HEBREW = 2 +FRENCH = 3 + +#------------------------------------------------------------------------- +# +# Month mappings +# +#------------------------------------------------------------------------- +_fmonth = [ + "Vendémiaire", "Brumaire", "Frimaire", "Nivôse", "Pluviôse", + "Ventôse", "Germinal", "Floréal", "Prairial", "Messidor", + "Thermidor", "Fructidor", "Extra", + ] + +_fmonth2num = { + "vend" : 0, "brum" : 1, "frim" : 2, "nivo" : 3, "pluv" : 4, + "vent" : 5, "germ" : 6, "flor" : 7, "prai" : 8, "mess" : 9, + "ther" :10, "fruc" :11, "extr" : 12,"comp" :12, "nivô" : 3 + } + +_hmonth = [ + "Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "AdarI", + "AdarII", "Nisan", "Iyyar", "Sivan", "Tammuz", "Av", + "Elul", + ] + +_hmonth2num = { + "tishri" : 0, "heshvan" : 1, "kislev" : 2, "tevet" : 3, + "shevat" : 4, "adari" : 5, "adarii" : 6, "nisan" : 7, + "iyyar" : 8, "sivan" : 9, "tammuz" :10, "av" : 11, + "elul" : 12,"tsh" : 0, "csh" : 1, "ksl" : 2, + "tvt" : 3, "shv" : 4, "adr" : 5, "ads" : 6, + "nsn" : 7, "iyr" : 8, "svn" : 9, "tmz" : 10, + "aav" :11, "ell" :12, + } + +_mname = [ + _("January"), _("February"), _("March"), _("April"), + _("May"), _("June"), _("July"), _("August"), + _("September"), _("October"), _("November"), _("December") + ] + +_m2num = { + string.lower(_mname[0][0:3]): 0, string.lower(_mname[1][0:3]): 1, + string.lower(_mname[2][0:3]): 2, string.lower(_mname[3][0:3]): 3, + string.lower(_mname[4][0:3]): 4, string.lower(_mname[5][0:3]): 5, + string.lower(_mname[6][0:3]): 6, string.lower(_mname[7][0:3]): 7, + string.lower(_mname[8][0:3]): 8, string.lower(_mname[9][0:3]): 9, + string.lower(_mname[10][0:3]): 10, string.lower(_mname[11][0:3]): 11 + } + +UNDEF = -999999 + +#------------------------------------------------------------------------- +# +# Date class +# +#------------------------------------------------------------------------- +class Date: + """ + The core date handling class for GRAMPs. Supports partial dates, + date ranges, and alternate calendars. + """ + formatCode = 0 + entryCode = 0 + + Error = "Illegal Date" + + fstr = _("(from|between|bet|bet.)") + tstr = _("(and|to|-)") + + fmt = compile("\s*%s\s+(.+)\s+%s\s+(.+)\s*$" % (fstr,tstr),IGNORECASE) + + def __init__(self,source=None): + if source: + self.start = SingleDate(source.start) + if source.stop: + self.stop = SingleDate(source.stop) + else: + self.stop = None + self.range = source.range + self.text = source.text + self.calendar = source.calendar + else: + self.start = SingleDate() + self.stop = None + self.range = 0 + self.text = "" + self.calendar = GREGORIAN + + def get_calendar(self): + return self.calendar + + def set_calendar(self,val): + self.calendar = val + self.start.convert_to(val) + if self.stop: + self.stop.convert_to(val) + + def get_start_date(self): + return self.start + + def get_stop_date(self): + if self.stop == None: + self.stop = SingleDate() + self.stop.calendar = self.calendar + return self.stop + + def getLowYear(self): + return self.start.getYear() + + def getHighYear(self): + if self.stop == None: + return self.start.getYear() + else: + return self.stop.getYear() + + def getYear(self): + return self.start.year + + def getYearValid(self): + return self.start.year != UNDEF + + def getMonth(self): + if self.start.month == UNDEF: + return UNDEF + return self.start.month+1 + + def getMonthValid(self): + return self.start.month != UNDEF + + def getDay(self): + return self.start.day + + def getDayValid(self): + return self.start.day != UNDEF + + def getValid(self): + """ Returns true if any part of the date is valid""" + return self.start.year != UNDEF or self.start.month != UNDEF or self.start.day != UNDEF + + + def getIncomplete(self): + return self.range == 0 and self.start.year == UNDEF or \ + self.start.month == UNDEF or self.start.day == UNDEF + + def getStopYear(self): + if self.stop == None: + self.stop = SingleDate() + self.stop.calendar = self.calendar + return self.stop.year + + def getStopMonth(self): + if self.stop == None: + self.stop = SingleDate() + self.stop.calendar = self.calendar + return self.stop.month+1 + + def getStopDay(self): + if self.stop == None: + self.stop = SingleDate() + self.stop.calendar = self.calendar + return self.stop.day + + def getText(self): + return self.text + + def greater_than(self,other): + return compare_dates(self,other) > 0 + + def less_than(self,other): + return compare_dates(self,other) < 0 + + def equal_to(self,other): + return compare_dates(self,other) == 0 + + def set(self,text): + match = Date.fmt.match(text) + try: + if match: + matches = match.groups() + self.start.set(matches[1]) + if self.stop == None: + self.stop = SingleDate() + self.stop.calendar = self.calendar + self.stop.set(matches[3]) + self.range = 1 + else: + self.start.set(text) + self.range = 0 + except Date.Error: + if text != "": + self.range = -1 + self.text = text + + def set_text(self,text): + self.range = -1 + self.text = text + + def set_range(self,val): + self.range = val + + def get_fmt(self,func): + if self.range == 0: + return func(self.start) + elif self.range == -1: + return self.text + else: + d1 = func(self.start) + d2 = func(self.stop) + return "%s %s %s %s" % ( _("from"),d1,_("to"),d2 ) + + def getDate(self): + return self.get_fmt(SingleDate.getDate) + + def getQuoteDate(self): + if self.calendar == GREGORIAN: + return self.getGregorianQuoteDate() + elif self.calendar == JULIAN: + return self.get_quote_date(_mname,_("Julian")) + elif self.calendar == HEBREW: + return self.get_quote_date(_hmonth,_("Hebrew")) + else: + return self.get_quote_date(_fmonth,_("French")) + + def getGregorianQuoteDate(self): + if self.range == 0: + return _func(self.start) + elif self.range == -1: + if self.text: + return '"%s"' % self.text + else: + return '' + else: + d1 = _func(self.start) + d2 = _func(self.stop) + return "%s %s %s %s" % ( _("from"),d1,_("to"), d2) + + def get_quote_date(self,month_map,cal_str): + if self.range == 0: + return "%s (%s)" % (self.start.display_calendar(month_map),cal_str) + elif self.range == -1: + if self.text: + return '"%s (%s)"' % (self.text,cal_str) + else: + return '' + else: + d1 = self.start.display_calendar(month_map) + d2 = self.stop.display_calendar(month_map) + return "%s %s %s %s (%s)" % ( _("from"),d1,_("to"), d2,cal_str) + + def isEmpty(self): + s = self.start + return s.year==UNDEF and s.month==UNDEF and s.day==UNDEF + + def isValid(self): + return self.range != -1 + + def isRange(self): + return self.range == 1 + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def set_format_code(code): + global _func + Date.formatCode = code + _func = SingleDate.fmtFunc[code] + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def get_format_code(): + return Date.formatCode + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +class SingleDate: + "Date handling" + + exact = 0 + about = 1 + before = 2 + after = 3 + + emname =[ + 'JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', + 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC' + ] + + em2num ={ + "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, + _("abt.") : about, _("est") : about , + _("est.") : about , _("circa") : about, + _("around") : about, _("before") : before, + _("bef") : before, _("bef.") : before, + _("after") : after, _("aft.") : after, + _("aft") : after, + # And the untranslated versions for reading saved data from XML. + "abt" : about, "about" : about, + "bef" : before, "bef." : before, + "aft." : after, "abt." : about, + "est." : about, "est" : about, + "after" : after, "before": before, + "aft" : after, + } + + modifiers = '(' + \ + _("abt\.?") + '|' + \ + _("about") + '|' + \ + _("est\.?") + '|' + \ + _("circa") + '|' + \ + _("around") + '|' + \ + _("before") + '|' + \ + _("after") + '|' + \ + _("aft\.?") + '|' + \ + _("bef\.?") + \ + '|abt|aft|after|before|bef)' + + start = "^\s*" + modifiers + "?\s*" + + fmt1 = compile(start+"(\S+)(\s+\d+\s*,)?\s*([?\d]+)?\s*$", IGNORECASE) + fmt2 = compile(start+"(\d+)\.?\s+(\S+)(\s+\d+)?\s*$", IGNORECASE) + fmt3 = compile(start+r"([?\d]+)\s*[./-]\s*([?\d]+)\s*[./-]\s*([?\d]+)\s*$", + IGNORECASE) + fmt7 = compile(start+r"([?\d]+)\s*[./-]\s*([?\d]+)\s*$", IGNORECASE) + fmt4 = compile(start+"(\S+)\s+(\d+)\s*$", IGNORECASE) + fmt5 = compile(start+"(\d+)\s*$", IGNORECASE) + fmt6 = compile(start+"(\S+)\s*$", IGNORECASE) + + def __init__(self,source=None): + if source: + self.month = source.month + self.day = source.day + self.year = source.year + self.mode = source.mode + self.calendar = source.calendar + else: + self.month = UNDEF + self.day = UNDEF + self.year = UNDEF + self.mode = SingleDate.exact + self.calendar = GREGORIAN + + def setMode(self,val): + if not val: + self.mode = SingleDate.exact + else: + try: + self.mode = SingleDate.m2v[string.lower(val)] + except KeyError: + raise Date.Error,val + + def setMonth(self,val): + if val > 14 or val < 0: + self.month = UNDEF + else: + self.month = val - 1 + + def setMonthVal(self,s): + try: + val = int(s) + self.month = val - 1 + except: + self.month = UNDEF + + def setDayVal(self,s): + try: + val = int(s) + self.day = val + except: + self.day = UNDEF + + def setYearVal(self,s): + try: + val = int(s) + self.year = val + except: + self.year = UNDEF + + def getMonth(self): + if self.month == UNDEF: + return UNDEF + return self.month + 1 + + def getMonthValid(self): + return self.month != UNDEF + + def setDay(self,val): + self.day = val + + def getDay(self): + return self.day + + def getDayValid(self): + return self.day != UNDEF + + def setYear(self,val): + self.year = val + + def getYear(self): + return self.year + + def getYearValid(self): + return self.year != UNDEF + + def getValid(self): + """ Returns true if any part of the date is valid""" + return self.year != UNDEF or self.month != UNDEF or self.day != UNDEF + + def setMonthStr(self,text): + try: + self.month = _m2num[string.lower(text[0:3])] + except KeyError: + self.setMonthStrEng(text) + + def setMonthStrEng(self,text): + try: + self.month = SingleDate.em2num[string.lower(text[0:3])] + except KeyError: + self.month = UNDEF + raise Date.Error,text + + def getMonthStr(self): + return _mname[self.month] + + def getIsoDate(self): + if self.year == UNDEF: + y = "????" + else: + y = "%04d" % self.year + if self.month == UNDEF: + if self.day == UNDEF: + m = "" + else: + m = "-??" + else: + m = "-%02d" % (self.month+1) + if self.day == UNDEF: + d = '' + else: + d = "-%02d" % self.day + return "%s%s%s" % (y,m,d) + + def _format1(self): + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF: + return "" + elif self.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + retval = _mname[self.month] + else: + try: + retval = "%s %d" % (_mname[self.month],self.year) + except: + retval = "**** %d %d %d ****" % (self.year,self.month,self.day) + elif self.month == UNDEF: + retval = str(self.year) + else: + try: + month = _mname[self.month] + except: + month = "" + if self.year == UNDEF: + retval = "%s %d, ????" % (month,self.day) + else: + retval = "%s %d, %d" % (month,self.day,self.year) + + if self.mode == SingleDate.about: + retval = _("about") + ' ' + retval + elif self.mode == SingleDate.before: + retval = _("before") + ' ' + retval + elif self.mode == SingleDate.after: + retval = _("after") + ' ' + retval + return retval + + def _format2(self): + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF : + return "" + elif self.month != UNDEF and self.month != UNDEF: + month = _mname[self.month] + if self.year == UNDEF: + 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.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + month = _mname[self.month] + retval = string.upper(month[0:3]) + else: + month = _mname[self.month] + retval = "%s %d" % (string.upper(month[0:3]),self.year) + else: + retval = str(self.year) + + if self.mode == SingleDate.about: + retval = "%s %s" % (_("abt"),retval) + elif self.mode == SingleDate.before: + retval = "%s %s" % (_("before"),retval) + elif self.mode == SingleDate.after: + retval = "%s %s" % (_("after"),retval) + + return retval + + def _format3(self): + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF : + return "" + elif self.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + month = _mname[self.month] + retval = string.upper(month[0:3]) + else: + month = _mname[self.month] + retval = "%s %d" % (string.upper(month[0:3]),self.year) + elif self.month == UNDEF: + retval = str(self.year) + else: + month = _mname[self.month] + if self.year == UNDEF: + 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 = "%s %s" % (_("ABOUT"),retval) + elif self.mode == SingleDate.before: + retval = "%s %s" % (_("BEFORE"),retval) + elif self.mode == SingleDate.after: + retval = "%s %s" % (_("AFTER"),retval) + return retval + + def _format10(self): + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF : + return "" + elif self.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + retval = _mname[self.month] + else: + month = _mname[self.month] + retval = "%s %d" % (month,self.year) + elif self.month == UNDEF: + retval = str(self.year) + else: + month = _mname[self.month] + if self.year == UNDEF: + retval = "%d. %s ????" % (self.day,month) + else: + retval = "%d. %s %d" % (self.day,month,self.year) + + if self.mode == SingleDate.about: + retval = "%s %s" % (_("ABOUT"),retval) + elif self.mode == SingleDate.before: + retval = "%s %s" % (_("BEFORE"),retval) + elif self.mode == SingleDate.after: + retval = "%s %s" % (_("AFTER"),retval) + + return retval + + def _get_mmddyyyy(self,sep): + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF : + return "" + elif self.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + retval = "%02d%s??%s??" % (self.month+1,sep,sep) + else: + retval = "%02d%s??%s%04d" % (self.month+1,sep,sep,self.year) + elif self.month == UNDEF: + retval = "??%s%02d%s%04d" % (sep,self.day,sep,self.year) + else: + if self.year == UNDEF: + retval = "%02d%s%02d%s????" % (self.month+1,sep,self.day,sep) + else: + retval = "%02d%s%02d%s%04d" % (self.month+1,sep,self.day,sep,self.year) + + if self.mode == SingleDate.about: + retval = "%s %s" % (_("ABOUT"),retval) + elif self.mode == SingleDate.before: + retval = "%s %s" % (_("BEFORE"),retval) + elif self.mode == SingleDate.after: + retval = "%s %s" % (_("AFTER"),retval) + + return retval + + def _get_yyyymmdd(self,sep): + retval = "" + + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF : + pass + elif self.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + retval = "????%s%02d%s??" % (sep,self.month+1,sep) + else: + retval = "%04d%s%02d" % (self.year,sep,self.month+1) + elif self.month == UNDEF: + retval = "%04d%s??%s%02d" % (self.year,sep,sep,self.day) + else: + if self.year == UNDEF: + retval = "????%s%02d%s%02d" % (sep,self.month+1,sep,self.day) + else: + retval = "%02d%s%02d%s%02d" % (self.year,sep,self.month+1,sep,self.day) + + if self.mode == SingleDate.about: + retval = "%s %s" % (_("ABOUT"),retval) + + if self.mode == SingleDate.before: + retval = "%s %s" % (_("BEFORE"),retval) + elif self.mode == SingleDate.after: + retval = "%s %s" % (_("AFTER"),retval) + + return retval + + def _format4(self): + return self._get_mmddyyyy("/") + + def _format5(self): + return self._get_mmddyyyy("-") + + def _format8(self): + return self._get_mmddyyyy(".") + + def _get_ddmmyyyy(self,sep): + retval = "" + + if self.month == UNDEF and self.day == UNDEF and self.year == UNDEF : + pass + elif self.day == UNDEF: + if self.month == UNDEF: + retval = str(self.year) + elif self.year == UNDEF: + retval = "??%s%02d%s??" % (sep,self.month+1,sep) + else: + retval = "??%s%02d%s%04d" % (sep,self.month+1,sep,self.year) + elif self.month == UNDEF: + retval = "%02d%s??%s%04d" % (self.day,sep,sep,self.year) + else: + if self.year == UNDEF: + retval = "%02d%s%02d%s????" % (self.day,sep,self.month+1,sep) + else: + retval = "%02d%s%02d%s%04d" % (self.day,sep,self.month+1,sep,self.year) + + if self.mode == SingleDate.about: + retval = "%s %s" % (_("ABOUT"),retval) + if self.mode == SingleDate.before: + retval = "%s %s" % (_("BEFORE"),retval) + elif self.mode == SingleDate.after: + retval = "%s %s" % (_("AFTER"),retval) + + return retval + + def _format6(self): + return self._get_ddmmyyyy("/") + + def _format7(self): + return self._get_ddmmyyyy("-") + + def _format9(self): + return self._get_ddmmyyyy(".") + + def _format11(self): + return self._get_yyyymmdd("/") + + def _format12(self): + return self._get_yyyymmdd("-") + + def _format13(self): + return self._get_yyyymmdd(".") + + #-------------------------------------------------------------------- + # + # + # + #-------------------------------------------------------------------- + fmtFunc = [ _format1, _format2, _format3, _format4, _format5, _format6, + _format7, _format8, _format9, _format10, _format11, _format12, + _format13] + + def display_calendar(self,month_map): + d = '' + if self.year==UNDEF: + if self.month == UNDEF: + d = "" + elif self.day == UNDEF: + d = month_map[self.month] + else: + d = "%02d %s" % (self.day,month_map[self.month]) + elif self.month == UNDEF: + d = str(self.year) + elif self.day == UNDEF: + d = "%s %d" % (month_map[self.month],self.year) + else: + d = "%02d %s %d" % (self.day,month_map[self.month],self.year) + if self.mode == SingleDate.about: + d = _("about") + ' ' + d + elif self.mode == SingleDate.before: + d = _("before") + ' ' + d + elif self.mode == SingleDate.after: + d = _("after") + ' ' + d + return d + + def getDate(self): + if self.calendar == GREGORIAN: + return _func(self) + elif self.calendar == JULIAN: + return self.display_calendar(_mname) + elif self.calendar == HEBREW: + return self.display_calendar(_hmonth) + else: + return self.display_calendar(_fmonth) + + def setIsoDate(self,v): + data = string.split(v) + if len(data) > 1: + self.setMode(data[0]) + v = data[1] + + vals = string.split(v,'-') + self.setYearVal(vals[0]) + if len(vals) > 1: + self.setMonthVal(vals[1]) + if len(vals) > 2: + self.setDayVal(vals[2]) + + def getModeVal(self): + return self.mode + + def setModeVal(self,val): + self.mode = val + + def set(self,text): + if self.calendar == GREGORIAN: + self.set_gregorian(text) + elif self.calendar == JULIAN: + self.set_calendar(text,_m2num,3) + elif self.calendar == HEBREW: + self.set_calendar(text,_hmonth2num,0) + else: + self.set_calendar(text,_fmonth2num,4) + + def set_calendar(self,text,month_map,l): + match = SingleDate.fmt2.match(text) + if match: + matches = match.groups() + self.setMode(matches[0]) + if l == 0: + mon = string.lower(matches[2]) + else: + mon = string.lower(matches[2])[0:l] + self.setYear(int(matches[3])) + self.setMonthStr(mon) + self.setDay(int(matches[1])) + return + match = SingleDate.fmt3.match(text) + if match: + matches = match.groups() + self.setMode(matches[0]) + self.setYearVal(matches[3]) + self.setMonthVal(matches[2]) + self.setDayVal(matches[1]) + return + + match = SingleDate.fmt4.match(text) + if match: + matches = match.groups() + self.setMode(matches[0]) + if l == 0: + mon = string.lower(matches[1]) + else: + mon = string.lower(matches[1])[0:l] + self.setYearVal(matches[2]) + self.setMonthStr(mon) + self.day = UNDEF + return + + match = SingleDate.fmt5.match(text) + if match: + matches = match.groups() + self.setMode(matches[0]) + self.setYearVal(matches[1]) + self.month = UNDEF + self.day = UNDEF + return + + self.year = UNDEF + self.month = UNDEF + self.day = UNDEF + + def set_gregorian(self,text): + match = SingleDate.fmt2.match(text) + if match != None: + matches = match.groups() + self.setMode(matches[0]) + self.setMonthStr(matches[2]) + self.day = int(matches[1]) + if len(matches) == 4 and matches[3] != None: + self.setYearVal(matches[3]) + else: + self.year = UNDEF + return 1 + + match = SingleDate.fmt5.match(text) + if match != None: + matches = match.groups() + self.setMode(matches[0]) + self.month = UNDEF + self.day = UNDEF + self.year = int(matches[1]) + return 1 + + match = SingleDate.fmt7.match(text) + if match != None: + matches = match.groups() + self.setMode(matches[0]) + if Date.entryCode == 2: + self.setMonthVal(matches[2]) + self.setYearVal(matches[1]) + else: + self.setMonthVal(matches[1]) + self.setYearVal(matches[2]) + if self.getMonth() > 13: + raise Date.Error + return 1 + + match = SingleDate.fmt3.match(text) + if match != None: + matches = match.groups() + self.setMode(matches[0]) + if Date.entryCode == 0: + self.setMonthVal(matches[1]) + self.setDayVal(matches[2]) + self.setYearVal(matches[3]) + elif Date.entryCode == 1: + self.setMonthVal(matches[2]) + self.setDayVal(matches[1]) + self.setYearVal(matches[3]) + else: + self.setMonthVal(matches[2]) + self.setDayVal(matches[3]) + self.setYearVal(matches[1]) + return 1 + + match = SingleDate.fmt1.match(text) + if match != None: + (mode,mon,day,year) = match.groups() + self.setMode(mode) + self.setMonthStr(mon) + if day: + self.setDayVal(int(string.replace(day,',',''))) + else: + self.day = UNDEF + self.setYearVal(year) + return 1 + + match = SingleDate.fmt4.match(text) + if match != None: + matches = match.groups() + self.setMode(matches[0]) + self.setMonthStr(matches[1]) + self.day = UNDEF + if len(matches) == 4: + self.setYearVal(matches[3]) + return 1 + + match = SingleDate.fmt6.match(text) + if match != None: + matches = match.groups() + self.setMode(matches[0]) + self.setMonthVal(matches[1]) + self.day = UNDEF + self.year = UNDEF + return 1 + + raise Date.Error,text + + def get_sdn(self): + if self.year == UNDEF: + return 0 + if self.month == UNDEF: + month = 1 + else: + month = self.month + 1 + if self.day == UNDEF: + day = 1 + else: + day = self.day + + if self.calendar == GREGORIAN: + sdn = Calendar.gregorian_to_sdn(self.year,month,day) + elif self.calendar == FRENCH: + sdn = Calendar.french_to_sdn(self.year,month,day) + if self.calendar == HEBREW: + sdn = Calendar.jewish_to_sdn(self.year,month,day) + if self.calendar == JULIAN: + sdn = Calendar.julian_to_sdn(self.year,month,day) + return sdn + + def convert_to(self,val): + if val == GREGORIAN: + self.convert_calendar(Calendar.sdn_to_gregorian,val) + elif val == JULIAN: + self.convert_calendar(Calendar.sdn_to_julian,val) + elif val == HEBREW: + self.convert_calendar(Calendar.sdn_to_jewish,val) + else: + self.convert_calendar(Calendar.sdn_to_french,val) + + def convert_calendar(self,func,mode): + sdn = self.get_sdn() + (y,m,d) = func(sdn) + self.calendar = mode + if y == 0 and m == 0 and d == 0: + self.year = UNDEF + self.month = UNDEF + self.day = UNDEF + else: + self.year = y + self.month = m-1 + self.day = d + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def not_too_old(date): + time_struct = time.localtime(time.time()) + current_year = time_struct[0] + if date.year != UNDEF and current_year - date.year > 110: + return 0 + return 1 + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def compare_dates(f,s): + if f.calendar != s.calendar: + return 1 + if f.range == -1 and s.range == -1: + return cmp(f.text,s.text) + if f.range == -1 or s.range == -1: + return -1 + + 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) + elif f.range != 1: + return cmp(first.day,second.day) + else: + first = f.get_stop_date() + second = s.get_stop_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) + +_func = SingleDate.fmtFunc[0] + diff --git a/gramps2/src/DateEdit.py b/gramps2/src/DateEdit.py new file mode 100644 index 000000000..b87920a97 --- /dev/null +++ b/gramps2/src/DateEdit.py @@ -0,0 +1,83 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002 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 +# + +""" +The DateEdit interface provides visual feedback to the user via a pixamp +to indicate if the assocated GtkEntry box contains a valid date. Green +means complete and valid date. Yellow means a valid, but incomplete date. +Red means that the date is not valid, and will be viewed as a text string +instead of a date. +""" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# GNOME modules +# +#------------------------------------------------------------------------- +import gtk +import gtk.gdk + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import Date +import const + +#------------------------------------------------------------------------- +# +# DateEdit +# +#------------------------------------------------------------------------- +class DateEdit: + """Class that associates a pixmap with a text widget, providing visual + feedback that indicates if the text widget contains a valid date""" + + good = gtk.gdk.pixbuf_new_from_file(const.good_xpm) + bad = gtk.gdk.pixbuf_new_from_file(const.bad_xpm) + caution = gtk.gdk.pixbuf_new_from_file(const.caution_xpm) + + def __init__(self,text_obj,pixmap_obj): + """Creates a connection between the text_obj and the pixmap_obj""" + + self.text_obj = text_obj + self.pixmap_obj = pixmap_obj + self.checkval = Date.Date() + self.text_obj.connect('focus-out-event',self.check) + self.check(None,None) + + def check(self,obj,val): + """Called with the text box loses focus. If the string contains a + valid date, sets the appropriate pixmap""" + + text = self.text_obj.get_text() + self.checkval.set(text) + if not self.checkval.isValid(): + self.pixmap_obj.set_from_pixbuf(DateEdit.bad) + elif self.checkval.getIncomplete(): + self.pixmap_obj.set_from_pixbuf(DateEdit.caution) + else: + self.pixmap_obj.set_from_pixbuf(DateEdit.good) + + diff --git a/gramps2/src/DbPrompter.py b/gramps2/src/DbPrompter.py new file mode 100644 index 000000000..7551e50ee --- /dev/null +++ b/gramps2/src/DbPrompter.py @@ -0,0 +1,139 @@ +#! /usr/bin/python -O +# +# 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 +# + +#------------------------------------------------------------------------- +# +# GNOME modules +# +#------------------------------------------------------------------------- +import gtk +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import Utils +import const +import GrampsCfg +import VersionControl +from intl import gettext +_ = gettext + +try: + import ZODB + _zodb = 1 +except: + _zodb = 0 + +#------------------------------------------------------------------------- +# +# DbPrompter +# +#------------------------------------------------------------------------- +class DbPrompter: + """Make sure a database is opened""" + + def __init__(self,db,want_new): + self.db = db + self.want_new = want_new + self.show() + + def show(self): + opendb = gtk.glade.XML(const.gladeFile, "opendb") + opendb.signal_autoconnect({ + "on_open_ok_clicked" : self.open_ok_clicked, + "on_open_cancel_clicked" : self.open_cancel_clicked, + "on_opendb_delete_event": self.open_delete_event, + }) + self.new = opendb.get_widget("new") + self.zodb = opendb.get_widget("zodb") + if self.want_new: + self.new.set_active(1) + if _zodb: + self.zodb.show() + + def open_ok_clicked(self,obj): + if self.new.get_active(): + self.db.clear_database(0) + self.save_as_activate() + elif self.zodb.get_active(): + self.db.clear_database(1) + self.save_as_activate() + else: + self.open_activate() + Utils.destroy_passed_object(obj) + + def save_as_activate(self): + wFs = gtk.glade.XML (const.gladeFile, "fileselection") + wFs.signal_autoconnect({ + "on_ok_button1_clicked": self.save_ok_button_clicked, + "destroy_passed_object": self.cancel_button_clicked, + }) + + def save_ok_button_clicked(self,obj): + filename = obj.get_filename() + if filename: + Utils.destroy_passed_object(obj) + if GrampsCfg.usevc and GrampsCfg.vc_comment: + self.db.display_comment_box(filename) + else: + self.db.save_file(filename,_("No Comment Provided")) + + def open_activate(self): + wFs = gtk.glade.XML(const.revisionFile, "dbopen") + wFs.signal_autoconnect({ + "on_ok_button1_clicked": self.ok_button_clicked, + "destroy_passed_object": self.cancel_button_clicked, + }) + + self.fileSelector = wFs.get_widget("dbopen") + self.dbname = wFs.get_widget("dbname") + self.getoldrev = wFs.get_widget("getoldrev") + self.dbname.set_default_path(GrampsCfg.db_dir) + self.getoldrev.set_sensitive(GrampsCfg.usevc) + + def cancel_button_clicked(self,obj): + Utils.destroy_passed_object(obj) + self.show() + + def ok_button_clicked(self,obj): + filename = self.dbname.get_full_path(0) + + if not filename: + return + + Utils.destroy_passed_object(obj) + + if self.getoldrev.get_active(): + vc = VersionControl.RcsVersionControl(filename) + VersionControl.RevisionSelect(self.db.database,filename,vc, + self.db.load_revision,self.show) + else: + self.db.read_file(filename) + + def open_delete_event(self,obj,event): + gtk.mainquit() + + def open_cancel_clicked(self,obj): + gtk.mainquit() + diff --git a/gramps2/src/DisplayTrace.py b/gramps2/src/DisplayTrace.py new file mode 100644 index 000000000..cc796ea1c --- /dev/null +++ b/gramps2/src/DisplayTrace.py @@ -0,0 +1,73 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002 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 cStringIO +import traceback +import sys + +#------------------------------------------------------------------------- +# +# GTK/GNOME modules +# +#------------------------------------------------------------------------- +import gtk.glade + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +import const +import intl + +_ = intl.gettext + +#------------------------------------------------------------------------- +# +# DisplayTrace +# +#------------------------------------------------------------------------- +class DisplayTrace: + + def __init__(self): + data = sys.exc_info() + msg = cStringIO.StringIO() + msg.write(_('GRAMPS has encountered an internal error.\n' + 'Please copy the message below and post a bug report ' + 'at http://sourceforge.net/projects/gramps or send an ' + 'email message to gramps-users@lists.sourceforge.net\n\n')) + + traceback.print_exception(data[0],data[1],data[2],None,msg) + + self.glade = gtk.glade.XML(const.pluginsFile,"plugstat") + self.top = self.glade.get_widget("plugstat") + window = self.glade.get_widget("text") + self.top.set_title(_('Internal Error - GRAMPS')) + + window.get_buffer().set_text(msg.getvalue()) +# self.top.run_and_close() + + + diff --git a/gramps2/src/DrawDoc.py b/gramps2/src/DrawDoc.py new file mode 100644 index 000000000..07004dfaa --- /dev/null +++ b/gramps2/src/DrawDoc.py @@ -0,0 +1,153 @@ +# +# 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 +# + +#------------------------------------------------------------------------ +# +# python modules +# +#------------------------------------------------------------------------ +import string +import os + +#------------------------------------------------------------------------ +# +# gramps modules +# +#------------------------------------------------------------------------ +from TextDoc import * + +#------------------------------------------------------------------------ +# +# GraphicsStyle +# +#------------------------------------------------------------------------ +class GraphicsStyle: + def __init__(self,obj=None): + if obj: + self.height = obj.height + self.width = obj.width + self.para_name = obj.para_name + self.shadow = obj.shadow + self.color = obj.color + else: + self.height = 0 + self.width = 0 + self.para_name = "" + self.shadow = 0 + self.color = (255,255,255) + + def set_height(self,val): + self.height = val + + def set_width(self,val): + self.width = val + + def set_paragraph_style(self,val): + self.para_name = val + + def set_shadow(self,val): + self.shadow = val + + def set_color(self,val): + self.color = val + + def get_height(self): + return self.height + + def get_width(self): + return self.width + + def get_paragraph_style(self): + return self.para_name + + def get_shadow(self): + return self.shadow + + def get_color(self): + return self.color + +#------------------------------------------------------------------------ +# +# DrawDoc +# +#------------------------------------------------------------------------ +class DrawDoc: + def __init__(self,styles,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.style_list = styles.get_styles() + self.draw_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 get_right_margin(self): + return self.rmargin + + def get_left_margin(self): + return self.lmargin + + def get_top_margin(self): + return self.tmargin + + def get_bottom_margin(self): + return self.bmargin + + def creator(self,name): + self.name = name + + def add_draw_style(self,name,style): + self.draw_styles[name] = GraphicsStyle(style) + + def open(self,filename): + pass + + def close(self): + pass + + def start_page(self,orientation=None): + pass + + def end_page(self): + pass + + def draw_box(self,style,text,x,y): + pass + + def write_at(self,style,text,x,y): + pass + + def draw_line(self,style,x1,y1,x2,y2): + pass + diff --git a/gramps2/src/EditPerson.py b/gramps2/src/EditPerson.py new file mode 100644 index 000000000..3dca00f1f --- /dev/null +++ b/gramps2/src/EditPerson.py @@ -0,0 +1,1516 @@ +# +# 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 string +import pickle + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk +import gnome.ui +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import GrampsCfg +import Date +from RelLib import * +import ImageSelect +import sort +import AutoComp +from DateEdit import DateEdit +from QuestionDialog import QuestionDialog + +from intl import gettext as _ + +_temple_names = const.lds_temple_codes.keys() +_temple_names.sort() +_temple_names = [""] + _temple_names + +pycode_tgts = [('url', 0, 0), + ('pevent', 0, 1), + ('pattr', 0, 2), + ('paddr', 0, 3)] + +#------------------------------------------------------------------------- +# +# EditPerson class +# +#------------------------------------------------------------------------- +class EditPerson: + + def __init__(self,person,db,callback=None): + """Creates an edit window. Associates a person with the window.""" + self.person = person + self.original_id = person.getId() + self.db = db + self.callback = callback + self.path = db.getSavePath() + self.not_loaded = 1 + self.lds_not_loaded = 1 + self.lists_changed = 0 + self.update_birth = 0 + self.update_death = 0 + self.pmap = {} + self.add_places = [] + + for key in db.getPlaceKeys(): + p = db.getPlaceDisplay(key) + self.pmap[p[0]] = key + + self.load_obj = None + self.top = gtk.glade.XML(const.editPersonFile, "editPerson") + self.icon_list = self.top.get_widget("iconlist") + self.gallery = ImageSelect.Gallery(person, self.path, self.icon_list,self.db,self) + + self.name_delete_btn = self.top.get_widget('aka_delete') + self.web_delete_btn = self.top.get_widget('delete_url') + self.event_delete_btn = self.top.get_widget('event_delete_btn') + self.attr_delete_btn = self.top.get_widget('attr_delete_btn') + self.addr_delete_btn = self.top.get_widget('addr_delete_btn') + + self.top.signal_autoconnect({ + "destroy_passed_object" : self.on_cancel_edit, + "on_up_clicked" : self.on_up_clicked, + "on_down_clicked" : self.on_down_clicked, + "on_add_address_clicked" : self.on_add_addr_clicked, + "on_add_aka_clicked" : self.on_add_aka_clicked, + "on_add_attr_clicked" : self.on_add_attr_clicked, + "on_add_url_clicked" : self.on_add_url_clicked, + "on_addr_button_press" : self.addr_double_click, + "on_web_button_press" : self.url_double_click, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, + "on_aka_delete_clicked" : self.on_aka_delete_clicked, + "on_aka_update_clicked" : self.on_aka_update_clicked, + "on_apply_person_clicked" : self.on_apply_person_clicked, + "on_attr_button_press" : self.attr_double_click, + "on_edit_birth_clicked" : self.on_edit_birth_clicked, + "on_edit_death_clicked" : self.on_edit_death_clicked, + "on_delete_address_clicked" : self.on_delete_addr_clicked, + "on_delete_attr_clicked" : self.on_delete_attr_clicked, + "on_delete_event" : self.on_delete_event, + "on_delete_url_clicked" : self.on_delete_url_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, + "on_edit_properties_clicked": self.gallery.popup_change_description, + "on_editperson_switch_page" : self.on_switch_page, + "on_event_add_clicked" : self.on_event_add_clicked, + "on_event_button_press" : self.event_double_click, + "on_event_delete_clicked" : self.on_event_delete_clicked, + "on_event_update_clicked" : self.on_event_update_clicked, + "on_name_button_press" : self.aka_double_click, + "on_name_note_clicked" : self.on_name_note_clicked, + "on_ldsbap_note_clicked" : self.on_ldsbap_note_clicked, + "on_ldsendow_note_clicked" : self.on_ldsendow_note_clicked, + "on_ldsseal_note_clicked" : self.on_ldsseal_note_clicked, + "on_ldsbap_src_clicked" : self.on_ldsbap_source_clicked, + "on_ldsendow_src_clicked" : self.on_ldsendow_source_clicked, + "on_ldsseal_src_clicked" : self.on_ldsseal_source_clicked, + "on_name_source_clicked" : self.on_primary_name_source_clicked, + "on_photolist_button_press_event" : self.gallery.on_button_press_event, + "on_photolist_select_icon" : self.gallery.on_photo_select_icon, + "on_update_address_clicked" : self.on_update_addr_clicked, + "on_update_attr_clicked" : self.on_update_attr_clicked, + "on_update_url_clicked" : self.on_update_url_clicked, + "on_web_go_clicked" : self.on_web_go_clicked, + }) + + self.window = self.get_widget("editPerson") + self.notes_field = self.get_widget("personNotes") + self.event_name_field = self.get_widget("eventName") + self.event_place_field = self.get_widget("eventPlace") + self.event_cause_field = self.get_widget("eventCause") + self.event_date_field = self.get_widget("eventDate") + self.event_descr_field = self.get_widget("eventDescription") + self.event_src_field = self.get_widget("event_srcinfo") + self.event_conf_field = self.get_widget("event_conf") + self.attr_conf_field = self.get_widget("attr_conf") + self.addr_conf_field = self.get_widget("attr_conf") + self.name_conf_field = self.get_widget("name_conf") + self.attr_src_field = self.get_widget("attr_srcinfo") + self.name_src_field = self.get_widget("name_srcinfo") + self.addr_src_field = self.get_widget("addr_srcinfo") + self.attr_list = self.get_widget("attr_list") + self.attr_type = self.get_widget("attr_type") + self.attr_value = self.get_widget("attr_value") + self.web_list = self.get_widget("web_list") + self.web_url = self.get_widget("web_url") + self.web_go = self.get_widget("web_go") + self.web_description = self.get_widget("url_des") + self.addr_label = self.get_widget("address_label") + self.addr_list = self.get_widget("address_list") + self.addr_start = self.get_widget("address_start") + self.addr_street = self.get_widget("street") + self.addr_city = self.get_widget("city") + self.addr_state = self.get_widget("state") + self.addr_country = self.get_widget("country") + self.addr_postal = self.get_widget("postal") + self.event_list = self.get_widget("eventList") + self.edit_person = self.get_widget("editPerson") + self.name_list = self.get_widget("nameList") + self.name_frame = self.get_widget("name_frame") + self.alt_given_field = self.get_widget("alt_given") + self.alt_last_field = self.get_widget("alt_last") + self.alt_title_field = self.get_widget("alt_title") + self.alt_suffix_field = self.get_widget("alt_suffix") + self.name_type_field = self.get_widget("name_type") + self.surname_field = self.get_widget("surname") + self.ntype_field = self.get_widget("ntype") + self.suffix = self.get_widget("suffix") + self.given = self.get_widget("givenName") + self.nick = self.get_widget("nickname") + self.title = self.get_widget("title") + self.bdate = self.get_widget("birthDate") + self.bplace = self.get_widget("birthPlace") + self.bpcombo = self.get_widget("bpcombo") + self.dpcombo = self.get_widget("dpcombo") + self.sncombo = self.get_widget("sncombo") + self.ddate = self.get_widget("deathDate") + self.dplace = self.get_widget("deathPlace") + self.is_male = self.get_widget("genderMale") + self.is_female = self.get_widget("genderFemale") + self.is_unknown = self.get_widget("genderUnknown") + self.addr_note = self.get_widget("addr_note") + self.addr_source = self.get_widget("addr_source") + self.attr_note = self.get_widget("attr_note") + self.attr_source = self.get_widget("attr_source") + self.name_note = self.get_widget("name_note") + self.name_source = self.get_widget("name_source") + self.gid = self.get_widget("gid") + + self.death = Event(person.getDeath()) + self.birth = Event(person.getBirth()) + self.pname = Name(person.getPrimaryName()) + + self.elist = person.getEventList()[:] + self.nlist = person.getAlternateNames()[:] + self.alist = person.getAttributeList()[:] + self.ulist = person.getUrlList()[:] + self.plist = person.getAddressList()[:] + + # event display + self.event_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING, + gobject.TYPE_STRING,gobject.TYPE_STRING) + + self.build_columns(self.event_list, [(_('Event'),150), (_('Description'),150), + (_('Date'),100), (_('Place'),100)]) + self.event_list.set_model(self.event_model) + self.event_list.get_selection().connect('changed',self.on_event_select_row) + + # attribute display + self.attr_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING) + self.build_columns(self.attr_list, [(_('Attribute'),150),(_('Value'),150)]) + self.attr_list.set_model(self.attr_model) + self.attr_list.get_selection().connect('changed',self.on_attr_select_row) + + # address display + self.addr_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.build_columns(self.addr_list, [(_('Date'),150),(_('Address'),150)]) + self.addr_list.set_model(self.addr_model) + self.addr_list.get_selection().connect('changed',self.on_addr_select_row) + + # name display + self.name_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING) + self.build_columns(self.name_list,[(_('Name'),250),(_('Type'),100)]) + self.name_list.set_model(self.name_model) + self.name_list.get_selection().connect('changed',self.on_name_select_row) + + # web display + self.web_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING) + self.build_columns(self.web_list, [(_('Path'),250),(_('Description'),100)]) + self.web_list.set_model(self.web_model) + self.web_list.get_selection().connect('changed',self.on_web_select_row) + + self.autoplace = AutoComp.AutoCombo(self.bpcombo,self.pmap.keys()) + self.autodeath = AutoComp.AutoCombo(self.dpcombo,self.pmap.keys(), + self.autoplace) + self.comp = AutoComp.AutoCombo(self.sncombo,self.db.getSurnames()) + + self.gid.set_text(person.getId()) + self.gid.set_editable(GrampsCfg.id_edit) + + self.event_list = self.get_widget("eventList") + + if GrampsCfg.display_attr: + self.get_widget("user_label").set_text(GrampsCfg.attr_name) + val = "" + for attr in self.person.getAttributeList(): + if attr.getType() == const.save_pattr(GrampsCfg.attr_name): + val = attr.getValue() + break + self.get_widget("user_data").set_text(val) + self.get_widget("user_colon").show() + else: + self.get_widget("user_label").hide() + self.get_widget("user_colon").hide() + self.get_widget("user_data").hide() + + self.lds_baptism = LdsOrd(self.person.getLdsBaptism()) + self.lds_endowment = LdsOrd(self.person.getLdsEndowment()) + self.lds_sealing = LdsOrd(self.person.getLdsSeal()) + + if GrampsCfg.uselds or self.lds_baptism or self.lds_endowment or self.lds_sealing: + self.get_widget("lds_tab").show() + self.get_widget("lds_page").show() + + types = const.NameTypesMap.keys() + types.sort() + self.ntype_field.set_popdown_strings(types) + self.autotype = AutoComp.AutoEntry(self.ntype_field.entry,types) + self.write_primary_name() + + if person.getGender() == Person.male: + self.is_male.set_active(1) + elif person.getGender() == Person.female: + self.is_female.set_active(1) + else: + self.is_unknown.set_active(1) + + self.nick.set_text(person.getNickName()) + self.update_birth_death() + + self.load_person_image() + + # set notes data + self.notes_buffer = self.notes_field.get_buffer() + self.notes_buffer.set_text(person.getNote()) + + self.event_list.drag_dest_set(gtk.DEST_DEFAULT_ALL,pycode_tgts,gtk.gdk.ACTION_COPY) + self.event_list.drag_source_set(gtk.gdk.BUTTON1_MASK, pycode_tgts, gtk.gdk.ACTION_COPY) + self.event_list.connect('drag_data_get', self.ev_drag_data_get) + self.event_list.connect('drag_data_received', + self.ev_drag_data_received) + +# self.web_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, +# pycode_tgts,ACTION_COPY) +# self.web_list.drag_source_set(BUTTON1_MASK, pycode_tgts, gtk.gdk.ACTION_COPY) +# self.web_list.connect('drag_data_get', self.url_drag_data_get) +# self.web_list.connect('drag_data_received', +# self.url_drag_data_received) + +# self.attr_list.drag_dest_set(gtk.DEST_DEFAULT_ALL,pycode_tgts, +# gtk.gdk.ACTION_COPY) +# self.attr_list.drag_source_set(gtk.gdk.BUTTON1_MASK, pycode_tgts, +# gtk.gdk.ACTION_COPY) +# self.attr_list.connect('drag_data_get', self.at_drag_data_get) +# self.attr_list.connect('drag_data_received', +# self.at_drag_data_received) + +# self.addr_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, +# pycode_tgts,ACTION_COPY) +# self.addr_list.drag_source_set(gtk.gdk.BUTTON1_MASK, pycode_tgts, +# gtk.gdk.ACTION_COPY) +# self.addr_list.connect('drag_data_get', self.ad_drag_data_get) +# self.addr_list.connect('drag_data_received', +# self.ad_drag_data_received) + + self.redraw_event_list() + self.redraw_attr_list() + self.redraw_addr_list() + self.redraw_name_list() + self.redraw_url_list() + + def build_columns(self,tree,list): + cnum = 0 + for name in list: + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn(name[0],renderer,text=cnum) + column.set_min_width(name[1]) + cnum = cnum + 1 + tree.append_column(column) + + def lds_field(self,ord,combo,date,place): + combo.set_popdown_strings(_temple_names) + if ord: + stat = ord.getStatus() + date.set_text(ord.getDate()) + if ord.getTemple() != "": + name = const.lds_temple_to_abrev[ord.getTemple()] + else: + name = "" + combo.entry.set_text(name) + else: + stat = 0 + combo.entry.set_text("") + +# AutoComp.AutoEntry(place,None,self.autoplace) + if ord and ord.getPlace(): + place.set_text(ord.getPlace().get_title()) + return stat + + def draw_lds(self): + """Draws the LDS window. This window is not always drawn, and in + may cases is hidden.""" + + self.ldsbap_date = self.get_widget("ldsbapdate") + self.ldsbap_temple = self.get_widget("ldsbaptemple") + self.ldsend_date = self.get_widget("endowdate") + self.ldsend_temple = self.get_widget("endowtemple") + self.ldsseal_date = self.get_widget("sealdate") + self.ldsseal_temple = self.get_widget("sealtemple") + self.ldsseal_fam = self.get_widget("sealparents") + self.ldsbapstat = self.get_widget("ldsbapstat") + self.ldssealstat = self.get_widget("sealstat") + self.ldsendowstat = self.get_widget("endowstat") + self.ldsbapplace = self.get_widget("lds_bap_place") + self.ldssealplace = self.get_widget("lds_seal_place") + self.ldsendowplace = self.get_widget("lds_end_place") + + self.bstat = self.lds_field(self.lds_baptism, + self.ldsbap_temple, + self.ldsbap_date, + self.ldsbapplace) + + self.estat = self.lds_field(self.lds_endowment, + self.ldsend_temple, + self.ldsend_date, + self.ldsendowplace) + + self.seal_stat = self.lds_field(self.lds_sealing, + self.ldsseal_temple, + self.ldsseal_date, + self.ldssealplace) + if self.lds_sealing: + self.ldsfam = self.lds_sealing.getFamily() + else: + self.ldsfam = None + + myMenu = gtk.Menu() + item = gtk.MenuItem(_("None")) + item.set_data("f",None) + item.connect("activate",self.menu_changed) + item.show() + myMenu.append(item) + + index = 0 + hist = 0 + flist = [self.person.getMainParents()] + for (fam,mrel,frel) in self.person.getParentList(): + flist.append(fam) + for fam in flist: + if fam == None: + continue + f = fam.getFather() + m = fam.getMother() + if f and m: + name = _("%(father)s and %(mother)s") % { + 'father' : GrampsCfg.nameof(f), + 'mother' : GrampsCfg.nameof(m) } + elif f: + name = GrampsCfg.nameof(f) + elif m: + name = GrampsCfg.nameof(m) + else: + name = _("unknown") + item = gtk.MenuItem(name) + item.set_data("f",fam) + item.connect("activate",self.menu_changed) + item.show() + myMenu.append(item) + index = index + 1 + if fam == self.ldsfam: + hist = index + self.ldsseal_fam.set_menu(myMenu) + self.ldsseal_fam.set_history(hist) + + self.build_bap_menu() + self.build_seal_menu() + self.build_endow_menu() + + def build_menu(self,list,task,opt_menu): + menu = gtk.Menu() + index = 0 + for val in list: + menuitem = gtk.MenuItem(val) + menuitem.set_data("val",index) + menuitem.connect('activate',task) + menuitem.show() + menu.append(menuitem) + index = index + 1 + opt_menu.set_menu(menu) + opt_menu.set_history(self.bstat) + + def build_bap_menu(self): + self.build_menu(const.lds_baptism,self.set_lds_bap,self.ldsbapstat) + + def build_endow_menu(self): + self.build_menu(const.lds_baptism,self.set_lds_endow,self.ldsendowstat) + + def build_seal_menu(self): + self.build_menu(const.lds_csealing,self.set_lds_seal,self.ldssealstat) + + def set_lds_bap(self,obj): + self.bstat = obj.get_data("val") + + def set_lds_endow(self,obj): + self.estat = obj.get_data("val") + + def set_lds_seal(self,obj): + self.seal_stat = obj.get_data("val") + + def ev_drag_data_received(self,widget,context,x,y,sel_data,info,time): + if sel_data and sel_data.data: + exec 'data = %s' % sel_data.data + exec 'mytype = "%s"' % data[0] + exec 'person = "%s"' % data[1] + if person == self.person.getId() or mytype != 'pevent': + return + foo = pickle.loads(data[2]); + for src in foo.getSourceRefList(): + base = src.getBase() + newbase = self.db.findSourceNoMap(base.getId()) + src.setBase(newbase) + place = foo.getPlace() + if place: + foo.setPlace(self.db.findPlaceNoMap(place.getId())) + self.elist.append(foo) + self.lists_changed = 1 + self.redraw_event_list() + + def ev_drag_data_get(self,widget, context, sel_data, info, time): + ev = widget.get_row_data(widget.focus_row) + + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('pevent',self.person.getId(),pickled)); + sel_data.set(sel_data.target, bits_per, data) + + def url_drag_data_received(self,widget,context,x,y,sel_data,info,time): + if sel_data and sel_data.data: + exec 'data = %s' % sel_data.data + exec 'mytype = "%s"' % data[0] + exec 'person = "%s"' % data[1] + if person == self.person.getId() or mytype != 'url': + return + foo = pickle.loads(data[2]); + self.ulist.append(foo) + self.lists_changed = 1 + self.redraw_url_list() + + def url_drag_data_get(self,widget, context, sel_data, info, time): + ev = widget.get_row_data(widget.focus_row) + + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('url',self.person.getId(),pickled)); + sel_data.set(sel_data.target, bits_per, data) + + def at_drag_data_received(self,widget,context,x,y,sel_data,info,time): + if sel_data and sel_data.data: + exec 'data = %s' % sel_data.data + exec 'mytype = "%s"' % data[0] + exec 'person = "%s"' % data[1] + if person == self.person.getId() or mytype != 'pattr': + return + foo = pickle.loads(data[2]); + for src in foo.getSourceRefList(): + base = src.getBase() + newbase = self.db.findSourceNoMap(base.getId()) + src.setBase(newbase) + self.alist.append(foo) + self.lists_changed = 1 + self.redraw_attr_list() + + def at_drag_data_get(self,widget, context, sel_data, info, time): + ev = widget.get_row_data(widget.focus_row) + + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('pattr',self.person.getId(),pickled)); + sel_data.set(sel_data.target, bits_per, data) + + def ad_drag_data_received(self,widget,context,x,y,sel_data,info,time): + if sel_data and sel_data.data: + exec 'data = %s' % sel_data.data + exec 'mytype = "%s"' % data[0] + exec 'person = "%s"' % data[1] + if person == self.person.getId() or mytype != 'paddr': + return + foo = pickle.loads(data[2]); + for src in foo.getSourceRefList(): + base = src.getBase() + newbase = self.db.findSourceNoMap(base.getId()) + src.setBase(newbase) + self.plist.append(foo) + self.lists_changed = 1 + self.redraw_addr_list() + + def ad_drag_data_get(self,widget, context, sel_data, info, time): + ev = widget.get_row_data(widget.focus_row) + + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('paddr',self.person.getId(),pickled)); + sel_data.set(sel_data.target, bits_per, data) + + def menu_changed(self,obj): + self.ldsfam = obj.get_data("f") + + def get_widget(self,str): + """returns the widget related to the passed string""" + return self.top.get_widget(str) + + def redraw_name_list(self): + """redraws the name list""" + Utils.redraw_list(self.nlist,self.name_model,disp_name) + + def redraw_url_list(self): + """redraws the url list, disabling the go button if no url + is selected""" + length = Utils.redraw_list(self.ulist,self.web_model,disp_url) + if length > 0: + #self.web_go.set_sensitive(1) + self.web_go.set_sensitive(0) + else: + self.web_go.set_sensitive(0) + self.web_url.set_text("") + self.web_description.set_text("") + + def redraw_attr_list(self): + """Redraws the attribute list""" + Utils.redraw_list(self.alist,self.attr_model,disp_attr) + + def redraw_addr_list(self): + """redraws the address list for the person""" + Utils.redraw_list(self.plist,self.addr_model,disp_addr) + + def redraw_event_list(self): + """redraw_event_list - Update both the birth and death place combo + boxes for any changes that occurred in the 'Event Edit' window. + Make sure not to allow the editing of a birth event to change + any values in the death event, and vice versa. Since updating a + combo list resets its present value, this code will have to save + and restore the value for the event *not* being edited.""" + + Utils.redraw_list(self.elist,self.event_model,disp_event) + + # Remember old combo list input + prev_btext = Utils.strip_id(self.bplace.get_text()) + prev_dtext = Utils.strip_id(self.dplace.get_text()) + + # Update birth with new values, make sure death values don't change + if self.update_birth: + self.update_birth = 0 + self.update_birth_info() + self.dplace.set_text(prev_dtext) + self.bdate_check = DateEdit(self.bdate,self.get_widget("birth_stat")) + + # Update death with new values, make sure birth values don't change + if self.update_death: + self.update_death = 0 + self.update_death_info() + self.bplace.set_text(prev_btext) + self.ddate_check = DateEdit(self.ddate,self.get_widget("death_stat")) + + def on_add_addr_clicked(self,obj): + """Invokes the address editor to add a new address""" + import AddrEdit + AddrEdit.AddressEditor(self,None) + + def on_add_aka_clicked(self,obj): + """Invokes the name editor to add a new name""" + import NameEdit + NameEdit.NameEditor(self,None) + + def on_add_url_clicked(self,obj): + """Invokes the url editor to add a new name""" + import UrlEdit + pname = self.person.getPrimaryName().getName() + UrlEdit.UrlEditor(self,pname,None) + + def on_add_attr_clicked(self,obj): + """Brings up the AttributeEditor for a new attribute""" + import AttrEdit + pname = self.person.getPrimaryName().getName() + AttrEdit.AttributeEditor(self,None,pname,const.personalAttributes) + + def on_up_clicked(self,obj): + sel = obj.get_selection() + store,iter = sel.get_selected() + if iter: + row = store.get_path(iter) + sel.select_path((row[0]-1)) + + def on_down_clicked(self,obj): + sel = obj.get_selection() + store,iter = sel.get_selected() + if iter: + row = store.get_path(iter) + sel.select_path((row[0]+1)) + + def on_event_add_clicked(self,obj): + """Brings up the EventEditor for a new event""" + import EventEdit + pname = self.person.getPrimaryName().getName() + EventEdit.EventEditor(self,pname,const.personalEvents, + const.save_fevent,None,None,0,self.callback) + + def on_edit_birth_clicked(self,obj): + """Brings up the EventEditor for the birth record, event + name cannot be changed""" + + import EventEdit + self.update_birth = 1 + pname = self.person.getPrimaryName().getName() + event = self.birth + event.setDate(self.bdate.get_text()) + def_placename = self.bplace.get_text() + p = self.get_place(self.bplace) + if p: + event.setPlace(p) + EventEdit.EventEditor(self,pname,const.personalEvents, + const.save_fevent,event,def_placename,1, + self.callback) + + def on_edit_death_clicked(self,obj): + """Brings up the EventEditor for the death record, event + name cannot be changed""" + + import EventEdit + self.update_death = 1 + pname = self.person.getPrimaryName().getName() + event = self.death + event.setDate(self.ddate.get_text()) + def_placename = self.dplace.get_text() + p = self.get_place(self.dplace) + if p: + event.setPlace(p) + EventEdit.EventEditor(self,pname,const.personalEvents, + const.save_fevent,event,def_placename,1, + self.callback) + + def on_aka_delete_clicked(self,obj): + """Deletes the selected name from the name list""" + if Utils.delete_selected(obj,self.nlist): + self.lists_changed = 1 + self.redraw_name_list() + + def on_delete_url_clicked(self,obj): + """Deletes the selected URL from the URL list""" + if Utils.delete_selected(obj,self.ulist): + self.lists_changed = 1 + self.redraw_url_list() + + def on_delete_attr_clicked(self,obj): + """Deletes the selected attribute from the attribute list""" + if Utils.delete_selected(obj,self.alist): + self.lists_changed = 1 + self.redraw_attr_list() + + def on_delete_addr_clicked(self,obj): + """Deletes the selected address from the address list""" + if Utils.delete_selected(obj,self.plist): + self.lists_changed = 1 + self.redraw_addr_list() + + def on_web_go_clicked(self,obj): + """Attempts to display the selected URL in a web browser""" + import gnome.url + text = obj.get() + if text: + gnome.url.show(text) + + def on_cancel_edit(self,obj): + """If the data has changed, give the user a chance to cancel + the close window""" + if self.did_data_change(): + QuestionDialog(_('Abandon Changes'), + _("Are you sure you want to abandon your changes?"), + _("Abandon Changes"), + self.cancel_callback, + _("Continue Editing")) + else: + Utils.destroy_passed_object(obj) + + def on_delete_event(self,obj,b): + """If the data has changed, give the user a chance to cancel + the close window""" + if self.did_data_change(): + QuestionDialog(_('Abandon Changes'), + _("Are you sure you want to abandon your changes?"), + _("Abandon Changes"), + self.cancel_callback, + _("Continue Editing")) + return 1 + else: + Utils.destroy_passed_object(obj) + return 0 + + def cancel_callback(self): + """If the user answered yes to abandoning changes, close the window""" + Utils.destroy_passed_object(self.window) + + def did_data_change(self): + """Check to see if any of the data has changed from the + original record""" + surname = self.surname_field.get_text() + ntype = self.ntype_field.entry.get_text() + suffix = self.suffix.get_text() + given = self.given.get_text() + nick = self.nick.get_text() + title = self.title.get_text() + male = self.is_male.get_active() + female = self.is_female.get_active() + unknown = self.is_unknown.get_active() + text = self.notes_buffer.get_text(self.notes_buffer.get_start_iter(), + self.notes_buffer.get_end_iter(),gtk.FALSE) + idval = self.gid.get_text() + + changed = 0 + name = self.person.getPrimaryName() + + if self.person.getId() != idval: + changed = 1 + if suffix != name.getSuffix(): + changed = 1 + if surname != name.getSurname(): + changed = 1 + if ntype != name.getType(): + changed = 1 + if given != name.getFirstName(): + changed = 1 + if nick != self.person.getNickName(): + changed = 1 + if title != name.getTitle(): + changed = 1 + if self.pname.getNote() != name.getNote(): + changed = 1 + if self.lds_not_loaded == 0 and self.check_lds(): + changed == 1 + + bplace = string.strip(self.bplace.get_text()) + dplace = string.strip(self.dplace.get_text()) + + if self.pmap.has_key(bplace): + p1 = self.db.getPlaceMap()[self.pmap[bplace]] + else: + p1 = None + if bplace != "": + changed = 1 + self.birth.setPlace(p1) + + if self.pmap.has_key(dplace): + p1 = self.db.getPlaceMap()[self.pmap[dplace]] + else: + p1 = None + if dplace != "": + changed = 1 + self.death.setPlace(p1) + + if not self.birth.are_equal(self.person.getBirth()): + changed = 1 + if not self.death.are_equal(self.person.getDeath()): + changed = 1 + if male and self.person.getGender() != Person.male: + changed = 1 + elif female and self.person.getGender() != Person.female: + changed = 1 + elif unknown and self.person.getGender() != Person.unknown: + changed = 1 + if text != self.person.getNote() or self.lists_changed: + changed = 1 + + if self.lds_not_loaded == 0: + if not self.lds_baptism.are_equal(self.person.getLdsBaptism()): + changed= 1 + + if not self.lds_endowment.are_equal(self.person.getLdsEndowment()): + changed = 1 + + if not self.lds_sealing.are_equal(self.person.getLdsSeal()): + changed = 1 + + return changed + + def check_lds(self): + self.lds_baptism.setDate(self.ldsbap_date.get_text()) + temple = self.ldsbap_temple.entry.get_text() + if const.lds_temple_codes.has_key(temple): + self.lds_baptism.setTemple(const.lds_temple_codes[temple]) + else: + self.lds_baptism.setTemple("") + self.lds_baptism.setPlace(self.get_place(self.ldsbapplace,1)) + + self.lds_endowment.setDate(self.ldsend_date.get_text()) + temple = self.ldsend_temple.entry.get_text() + if const.lds_temple_codes.has_key(temple): + self.lds_endowment.setTemple(const.lds_temple_codes[temple]) + else: + self.lds_endowment.setTemple("") + self.lds_endowment.setPlace(self.get_place(self.ldsendowplace,1)) + + self.lds_sealing.setDate(self.ldsseal_date.get_text()) + temple = self.ldsseal_temple.entry.get_text() + if const.lds_temple_codes.has_key(temple): + self.lds_sealing.setTemple(const.lds_temple_codes[temple]) + else: + self.lds_sealing.setTemple("") + self.lds_sealing.setFamily(self.ldsfam) + self.lds_sealing.setPlace(self.get_place(self.ldssealplace,1)) + + def on_event_delete_clicked(self,obj): + """Delete the selected event""" + if Utils.delete_selected(obj,self.elist): + self.lists_changed = 1 + self.redraw_event_list() + + def update_birth_death(self): + self.bdate.set_text(self.birth.getDate()) + self.bplace.set_text(self.birth.getPlaceName()) + self.ddate.set_text(self.death.getDate()) + self.dplace.set_text(self.death.getPlaceName()) + self.dplace.set_text(self.death.getPlaceName()) +# self.bdate.set_position(0) +# self.ddate.set_position(0) +# self.bplace.set_position(0) +# self.dplace.set_position(0) + + def attr_double_click(self,obj,event): + if event.button == 1 and event.type == _2BUTTON_PRESS: + self.on_update_attr_clicked(obj) + + def on_update_attr_clicked(self,obj): + import AttrEdit + if obj.selection: + attr = obj.get_row_data(obj.selection[0]) + pname = self.person.getPrimaryName().getName() + AttrEdit.AttributeEditor(self,attr,pname,const.personalAttributes) + + def addr_double_click(self,obj,event): + if event.button == 1 and event.type == _2BUTTON_PRESS: + self.on_update_addr_clicked(obj) + + def on_update_addr_clicked(self,obj): + import AddrEdit + if obj.selection: + AddrEdit.AddressEditor(self,obj.get_row_data(obj.selection[0])) + + def url_double_click(self,obj,event): + if event.button == 1 and event.type == _2BUTTON_PRESS: + self.on_update_url_clicked(obj) + + def on_update_url_clicked(self,obj): + import UrlEdit + if obj.selection: + pname = self.person.getPrimaryName().getName() + url = obj.get_row_data(obj.selection[0]) + UrlEdit.UrlEditor(self,pname,url) + + def event_double_click(self,obj,event): + if event.button == 1 and event.type == _2BUTTON_PRESS: + self.on_event_update_clicked(obj) + + def on_event_update_clicked(self,obj): + import EventEdit + if obj.selection: + pname = self.person.getPrimaryName().getName() + event = obj.get_row_data(obj.selection[0]) + EventEdit.EventEditor(self,pname,const.personalEvents, + const.save_fevent,event,None,0, + self.callback) + + def on_event_select_row(self,obj): + store,iter = obj.get_selected() + if iter: + row = store.get_path(iter) + event = self.elist[row[0]] + self.event_date_field.set_text(event.getDate()) + self.event_place_field.set_text(event.getPlaceName()) + self.event_name_field.set_label(const.display_pevent(event.getName())) + self.event_cause_field.set_text(event.getCause()) + self.event_descr_field.set_text(event.getDescription()) + if len(event.getSourceRefList()) > 0: + psrc = event.getSourceRefList()[0] + self.event_src_field.set_text(psrc.getBase().getTitle()) + self.event_conf_field.set_text(const.confidence[psrc.getConfidence()]) + else: + self.event_src_field.set_text('') + self.event_conf_field.set_text('') + self.event_delete_btn.set_sensitive(1) + else: + self.event_date_field.set_text('') + self.event_place_field.set_text('') + self.event_name_field.set_label('') + self.event_cause_field.set_text('') + self.event_descr_field.set_text('') + self.event_src_field.set_text('') + self.event_conf_field.set_text('') + self.event_delete_btn.set_sensitive(0) + + def on_addr_select_row(self,obj): + store,iter = obj.get_selected() + if iter: + row = store.get_path(iter) + addr = self.plist[row[0]] + label = "%s %s %s" % (addr.getCity(),addr.getState(),addr.getCountry()) + self.addr_label.set_label(label) + self.addr_start.set_text(addr.getDate()) + self.addr_street.set_text(addr.getStreet()) + self.addr_city.set_text(addr.getCity()) + self.addr_state.set_text(addr.getState()) + self.addr_country.set_text(addr.getCountry()) + self.addr_postal.set_text(addr.getPostal()) + if len(addr.getSourceRefList()) > 0: + psrc = addr.getSourceRefList()[0] + self.addr_conf_field.set_text(const.confidence[psrc.getConfidence()]) + self.addr_src_field.set_text(psrc.getBase().getTitle()) + else: + self.addr_src_field.set_text('') + self.addr_conf_field.set_text('') + self.addr_delete_btn.set_sensitive(1) + else: + self.addr_label.set_label('') + self.addr_start.set_text('') + self.addr_street.set_text('') + self.addr_city.set_text('') + self.addr_state.set_text('') + self.addr_country.set_text('') + self.addr_postal.set_text('') + self.addr_conf_field.set_text('') + self.addr_src_field.set_text('') + self.addr_delete_btn.set_sensitive(0) + + def on_name_select_row(self,obj): + store,iter = obj.get_selected() + if iter: + row = store.get_path(iter) + name = self.nlist[row[0]] + self.name_frame.set_label(name.getName()) + self.alt_given_field.set_text(name.getFirstName()) + self.alt_title_field.set_text(name.getTitle()) + self.alt_last_field.set_text(name.getSurname()) + self.alt_suffix_field.set_text(name.getSuffix()) + self.name_type_field.set_text(name.getType()) + if len(name.getSourceRefList()) > 0: + psrc = name.getSourceRefList()[0] + self.name_src_field.set_text(psrc.getBase().getTitle()) + self.name_conf_field.set_text(const.confidence[psrc.getConfidence()]) + else: + self.name_src_field.set_text('') + self.name_conf_field.set_text('') + self.name_delete_btn.set_sensitive(1) + else: + self.name_frame.set_label('') + self.alt_given_field.set_text('') + self.alt_title_field.set_text('') + self.alt_last_field.set_text('') + self.alt_suffix_field.set_text('') + self.name_type_field.set_text('') + self.name_src_field.set_text('') + self.name_conf_field.set_text('') + self.name_delete_btn.set_sensitive(0) + + def on_web_select_row(self,obj): + store,iter = obj.get_selected() + if iter: + row = store.get_path(iter) + url = self.ulist[row[0]] + path = url.get_path() + self.web_url.set_text(path) + self.web_description.set_text(url.get_description()) + self.web_go.set_sensitive(0) + #self.web_go.set_sensitive(1) + self.web_delete_btn.set_sensitive(1) + else: + self.web_url.set_text('') + self.web_description.set_text('') + self.web_go.set_sensitive(0) + self.web_delete_btn.set_sensitive(0) + + def on_attr_select_row(self,obj): + store,iter = obj.get_selected() + if iter: + row = store.get_path(iter) + attr = self.alist[row[0]] + self.attr_type.set_label(const.display_pattr(attr.getType())) + self.attr_value.set_text(attr.getValue()) + if len(attr.getSourceRefList()) > 0: + psrc = attr.getSourceRefList()[0] + self.attr_src_field.set_text(psrc.getBase().getTitle()) + self.attr_conf_field.set_text(const.confidence[psrc.getConfidence()]) + else: + self.attr_src_field.set_text('') + self.attr_conf_field.set_text('') + self.attr_delete_btn.set_sensitive(1) + else: + self.attr_type.set_label('') + self.attr_value.set_text('') + self.attr_src_field.set_text('') + self.attr_conf_field.set_text('') + self.attr_delete_btn.set_sensitive(0) + + def aka_double_click(self,obj,event): + if event.button == 1 and event.type == _2BUTTON_PRESS: + self.on_aka_update_clicked(obj) + elif event.button == 3: + menu = gtk.Menu() + item = gtk.TearoffMenuItem() + item.show() + menu.append(item) + msg = _("Make the selected name the preferred name") + Utils.add_menuitem(menu,msg,None,self.change_name) + menu.popup(None,None,None,0,0) + + def on_aka_update_clicked(self,obj): + import NameEdit + if obj.selection: + NameEdit.NameEditor(self,obj.get_row_data(obj.selection[0])) + + def load_photo(self,photo): + """loads, scales, and displays the person's main photo""" + self.load_obj = photo + if photo == None: + self.get_widget("personPix").hide() + else: + try: + i = gtk.gdk.pixbuf_new_from_file(photo) + ratio = float(max(i.get_height(),i.get_width())) + scale = float(const.picWidth)/ratio + x = int(scale*(i.get_width())) + y = int(scale*(i.get_height())) + i = i.scale_simple(x,y,gtk.gdk.INTERP_BILINEAR) + self.get_widget("personPix").set_from_pixbuf(i) + self.get_widget("personPix").show() + except: + self.get_widget("personPix").hide() + + def update_lists(self): + """Updates the person's lists if anything has changed""" + if self.lists_changed: + self.person.setEventList(self.elist) + self.person.setAlternateNames(self.nlist) + self.person.setUrlList(self.ulist) + self.person.setAttributeList(self.alist) + self.person.setAddressList(self.plist) + self.person.setBirth(self.birth) + self.person.setDeath(self.death) + Utils.modified() + + def on_apply_person_clicked(self,obj): + + surname = self.surname_field.get_text() + suffix = self.suffix.get_text() + ntype = self.ntype_field.entry.get_text() + given = self.given.get_text() + nick = self.nick.get_text() + title = self.title.get_text() + idval = self.gid.get_text() + + name = self.pname + + if idval != self.person.getId(): + m = self.db.getPersonMap() + if not m.has_key(idval): + if m.has_key(self.person.getId()): + del m[self.person.getId()] + m[idval] = self.person + self.person.setId(idval) + Utils.modified() + else: + n = GrampsCfg.nameof(m[idval]) + msg1 = _("GRAMPS ID value was not changed.") + msg2 = _("%(grampsid)s is already used by %(person)s") % { + 'grampsid' : idval, + 'person' : n } + GnomeWarningDialog("%s\n%s" % (msg1,msg2)) + + if suffix != name.getSuffix(): + name.setSuffix(suffix) + + if const.NameTypesMap.has_key(ntype): + ntype = const.NameTypesMap[ntype] + else: + ntype = "Birth Name" + + if ntype != name.getType(): + name.setType(ntype) + + if surname != name.getSurname(): + name.setSurname(surname) + self.db.addSurname(surname) + + if given != name.getFirstName(): + name.setFirstName(given) + + if title != name.getTitle(): + name.setTitle(title) + + name.setSourceRefList(self.pname.getSourceRefList()) + + if not name.are_equal(self.person.getPrimaryName()): + self.person.setPrimaryName(name) + Utils.modified() + + if nick != self.person.getNickName(): + self.person.setNickName(nick) + Utils.modified() + + self.pmap.clear() + for key in self.db.getPlaceKeys(): + p = self.db.getPlaceDisplay(key) + self.pmap[p[0]] = key + + self.birth.setDate(self.bdate.get_text()) + self.birth.setPlace(self.get_place(self.bplace,1)) + + if not self.person.getBirth().are_equal(self.birth): + self.person.setBirth(self.birth) + + # Update each of the families child lists to reflect any + # change in ordering due to the new birth date + family = self.person.getMainParents() + if (family): + new_order = reorder_child_list(self.person,family.getChildList()) + family.setChildList(new_order) + for (family, rel1, rel2) in self.person.getParentList(): + new_order = reorder_child_list(self.person,family.getChildList()) + family.setChildList(new_order) + + self.death.setDate(self.ddate.get_text()) + self.death.setPlace(self.get_place(self.dplace,1)) + + if not self.person.getDeath().are_equal(self.death): + self.person.setDeath(self.death) + + male = self.is_male.get_active() + female = self.is_female.get_active() + unknown = self.is_unknown.get_active() + error = 0 + if male and self.person.getGender() != Person.male: + self.person.setGender(Person.male) + for temp_family in self.person.getFamilyList(): + if self.person == temp_family.getMother(): + if temp_family.getFather() != None: + error = 1 + else: + temp_family.setMother(None) + temp_family.setFather(self.person) + Utils.modified() + elif female and self.person.getGender() != Person.female: + self.person.setGender(Person.female) + for temp_family in self.person.getFamilyList(): + if self.person == temp_family.getFather(): + if temp_family.getMother() != None: + error = 1 + else: + temp_family.setFather(None) + temp_family.setMother(self.person) + Utils.modified() + elif unknown and self.person.getGender() != Person.unknown: + self.person.setGender(Person.unknown) + for temp_family in self.person.getFamilyList(): + if self.person == temp_family.getFather(): + if temp_family.getMother() != None: + error = 1 + else: + temp_family.setFather(None) + temp_family.setMother(self.person) + if self.person == temp_family.getMother(): + if temp_family.getFather() != None: + error = 1 + else: + temp_family.setMother(None) + temp_family.setFather(self.person) + Utils.modified() + + if error == 1: + msg = _("Changing the gender caused problems " + "with marriage information.\nPlease check " + "the person's marriages.") + GnomeErrorDialog(msg) + + text = self.notes_buffer.get_text(self.notes_buffer.get_start_iter(), + self.notes_buffer.get_end_iter(),gtk.FALSE) + + if text != self.person.getNote(): + self.person.setNote(text) + Utils.modified() + + if self.lds_not_loaded == 0: + self.check_lds() + ord = LdsOrd(self.person.getLdsBaptism()) + if not self.lds_baptism.are_equal(ord): + self.person.setLdsBaptism(self.lds_baptism) + Utils.modified() + + ord = LdsOrd(self.person.getLdsEndowment()) + if not self.lds_endowment.are_equal(ord): + self.person.setLdsEndowment(self.lds_endowment) + Utils.modified() + + ord = LdsOrd(self.person.getLdsSeal()) + if not self.lds_sealing.are_equal(ord): + self.person.setLdsSeal(self.lds_sealing) + Utils.modified() + + self.update_lists() + if self.callback: + self.callback(self,self.add_places) + Utils.destroy_passed_object(obj) + + def get_place(self,field,makenew=0): + text = string.strip(field.get_text()) + if text: + if self.pmap.has_key(text): + return self.db.getPlaceMap()[self.pmap[text]] + elif makenew: + place = Place() + place.set_title(text) + self.db.addPlace(place) + self.pmap[text] = place.getId() + self.add_places.append(place) + Utils.modified() + return place + else: + return None + else: + return None + + def on_primary_name_source_clicked(self,obj): + import Sources + Sources.SourceSelector(self.pname.getSourceRefList(),self,self.update_primary_name) + + def update_primary_name(self,list): + self.pname.setSourceRefList(list) + self.lists_changed = 1 + + def on_name_note_clicked(self,obj): + import NoteEdit + NoteEdit.NoteEditor(self.pname) + + def on_ldsbap_source_clicked(self,obj): + import Sources + Sources.SourceSelector(self.lds_baptism.getSourceRefList(),self,self.update_ldsbap_list) + + def update_ldsbap_list(self,list): + self.lds_baptism.setSourceRefList(list) + self.lists_changed = 1 + + def on_ldsbap_note_clicked(self,obj): + import NoteEdit + NoteEdit.NoteEditor(self.lds_baptism) + + def on_ldsendow_source_clicked(self,obj): + import Sources + Sources.SourceSelector(self.lds_endowment.getSourceRefList(),self,self.set_ldsendow_list) + + def set_ldsendow_list(self,list): + self.lds_endowment.setSourceRefList(list) + self.lists_changed = 1 + + def on_ldsendow_note_clicked(self,obj): + import NoteEdit + NoteEdit.NoteEditor(self.lds_endowment) + + def on_ldsseal_source_clicked(self,obj): + import Sources + ord = self.person.getLdsSeal() + Sources.SourceSelector(self.lds_sealing.getSourceRefList(),self,self.lds_seal_list) + + def lds_seal_list(self,list): + self.lds_sealing.setSourceRefList(list) + self.lists_changed = 1 + + def on_ldsseal_note_clicked(self,obj): + import NoteEdit + NoteEdit.NoteEditor(self.lds_sealing) + + def load_person_image(self): + photo_list = self.person.getPhotoList() + if photo_list: + ph = photo_list[0] + object = ph.getReference() + if self.load_obj != object.getPath(): + if object.getMimeType()[0:5] == "image": + self.load_photo(object.getPath()) + else: + self.load_photo(None) + else: + self.load_photo(None) + + def update_birth_info(self): + self.bdate.set_text(self.birth.getDate()) + self.bplace.set_text(self.birth.getPlaceName()) + + def update_death_info(self): + self.ddate.set_text(self.death.getDate()) + self.dplace.set_text(self.death.getPlaceName()) + + def on_switch_page(self,obj,a,page): + if page == 0: + self.load_person_image() + self.update_death_info() + self.update_birth_info() + elif page == 2: + self.redraw_event_list() + elif page == 6 and self.not_loaded: + self.not_loaded = 0 + self.gallery.load_images() + elif page == 8 and self.lds_not_loaded: + self.lds_not_loaded = 0 + self.draw_lds() + + def change_name(self,obj): + if self.name_list.selection: + old = self.pname + row = self.name_list.selection[0] + new = self.name_list.get_row_data(row) + self.nlist.remove(new) + self.nlist.append(old) + self.redraw_name_list() + self.pname = Name(new) + self.lists_changed = 1 + self.write_primary_name() + + def write_primary_name(self): + # initial values + name = GrampsCfg.nameof(self.person) + self.get_widget("activepersonTitle").set_text(name) + self.suffix.set_text(self.pname.getSuffix()) + + self.surname_field.set_text(self.pname.getSurname()) + self.given.set_text(self.pname.getFirstName()) + + self.ntype_field.entry.set_text(_(self.pname.getType())) + self.title.set_text(self.pname.getTitle()) + +#------------------------------------------------------------------------- +# +# disp_name +# +#------------------------------------------------------------------------- +def disp_name(name): + return [name.getName(),_(name.getType())] + +#------------------------------------------------------------------------- +# +# disp_url +# +#------------------------------------------------------------------------- +def disp_url(url): + return [url.get_path(),url.get_description()] + +#------------------------------------------------------------------------- +# +# disp_attr +# +#------------------------------------------------------------------------- +def disp_attr(attr): + detail = Utils.get_detail_flags(attr) + return [const.display_pattr(attr.getType()),attr.getValue()] + +#------------------------------------------------------------------------- +# +# disp_addr +# +#------------------------------------------------------------------------- +def disp_addr(addr): + location = "%s %s %s" % (addr.getCity(),addr.getState(),addr.getCountry()) + return [addr.getDate(),location] + +#------------------------------------------------------------------------- +# +# disp_event +# +#------------------------------------------------------------------------- +def disp_event(event): + attr = Utils.get_detail_flags(event) + return [const.display_pevent(event.getName()),event.getDescription(), + event.getQuoteDate(),event.getPlaceName()] + +#------------------------------------------------------------------------- +# +# birth_dates_in_order +# +# Check any *valid* birthdates in the list to insure that they are in +# numerically increasing order. +# +#------------------------------------------------------------------------- +def birth_dates_in_order(list): + inorder = 1 + prev_date = "00000000" + for i in range(len(list)): + child = list[i] + bday = child.getBirth().getDateObj() + child_date = sort.build_sort_date(bday) + if (child_date == "99999999"): + continue + if (prev_date <= child_date): # <= allows for twins + prev_date = child_date + else: + inorder = 0 + return inorder + + +#------------------------------------------------------------------------- +# +# reorder_child_list +# +# Reorder the child list to put the specified person in his/her +# correct birth order. Only check *valid* birthdates. Move the person +# as short a distance as possible. +# +#------------------------------------------------------------------------- +def reorder_child_list(person, list): + if (birth_dates_in_order(list)): + return(list) + + # Build the person's date string once + person_bday = sort.build_sort_date(person.getBirth().getDateObj()) + + # First, see if the person needs to be moved forward in the list + index = list.index(person) + target = index + for i in range(index-1, -1, -1): + other_bday = sort.build_sort_date(list[i].getBirth().getDateObj()) + if (other_bday == "99999999"): + continue; + if (person_bday < other_bday): + target = i + + # Now try moving to a later position in the list + if (target == index): + for i in range(index, len(list)): + other_bday = sort.build_sort_date(list[i].getBirth().getDateObj()) + if (other_bday == "99999999"): + continue; + if (person_bday > other_bday): + target = i + + # Actually need to move? Do it now. + if (target != index): + list.remove(person) + list.insert(target,person) + return list + diff --git a/gramps2/src/EditPlace.py b/gramps2/src/EditPlace.py new file mode 100644 index 000000000..33d942abe --- /dev/null +++ b/gramps2/src/EditPlace.py @@ -0,0 +1,419 @@ +# +# 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 +# + +#------------------------------------------------------------------------- +# +# python modules +# +#------------------------------------------------------------------------- +import pickle + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk +import gtk.glade +import gnome.ui + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import GrampsCfg +from RelLib import * +import Sources +import ImageSelect + +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# Constants +# +#------------------------------------------------------------------------- +pycode_tgts = [('url', 0, 0)] + +#------------------------------------------------------------------------- +# +# EditPlace +# +#------------------------------------------------------------------------- +class EditPlace: + + def __init__(self,parent,place,func=None): + self.place = place + self.db = parent.db + self.parent = parent + self.callback = func + self.path = parent.db.getSavePath() + self.not_loaded = 1 + self.ref_not_loaded = 1 + self.lists_changed = 0 + if place: + self.srcreflist = place.getSourceRefList() + else: + self.srcreflist = [] + + self.top_window = gtk.glade.XML(const.placesFile,"placeEditor") + adj = gtk.Adjustment() + self.iconlist = self.top_window.get_widget('iconlist') + + self.glry = ImageSelect.Gallery(place, self.path, self.iconlist, self.db, self) + self.title = self.top_window.get_widget("place_title") + self.city = self.top_window.get_widget("city") + self.parish = self.top_window.get_widget("parish") + self.county = self.top_window.get_widget("county") + self.state = self.top_window.get_widget("state") + self.country = self.top_window.get_widget("country") + self.longitude = self.top_window.get_widget("longitude") + self.latitude = self.top_window.get_widget("latitude") + self.note = self.top_window.get_widget("place_note") + + self.web_list = self.top_window.get_widget("web_list") + self.web_url = self.top_window.get_widget("web_url") + self.web_go = self.top_window.get_widget("web_go") + self.web_description = self.top_window.get_widget("url_des") + + # event display + self.web_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING) + self.build_columns(self.web_list, [(_('Path'),150), (_('Description'),150)]) + self.web_list.set_model(self.web_model) + self.web_list.get_selection().connect('changed',self.on_web_list_select_row) + + self.loc_list = self.top_window.get_widget("loc_list") + self.loc_city = self.top_window.get_widget("loc_city") + self.loc_county = self.top_window.get_widget("loc_county") + self.loc_state = self.top_window.get_widget("loc_state") + self.loc_parish = self.top_window.get_widget("loc_parish") + self.loc_country = self.top_window.get_widget("loc_country") + + self.ulist = place.getUrlList()[:] + self.llist = place.get_alternate_locations()[:] + + self.loc_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING, + gobject.TYPE_STRING,gobject.TYPE_STRING) + self.build_columns(self.loc_list, [(_('City'),150), (_('County'),100), + (_('State'),100), (_('Country'),50)]) + self.loc_list.set_model(self.loc_model) + self.loc_list.get_selection().connect('changed',self.on_loc_list_select_row) + + self.title.set_text(place.get_title()) + mloc = place.get_main_location() + self.city.set_text(mloc.get_city()) + self.county.set_text(mloc.get_county()) + self.state.set_text(mloc.get_state()) + self.parish.set_text(mloc.get_parish()) + self.country.set_text(mloc.get_country()) + self.longitude.set_text(place.get_longitude()) + self.latitude.set_text(place.get_latitude()) + self.refinfo = self.top_window.get_widget("refinfo") + self.slist = self.top_window.get_widget("slist") + + self.note_buffer = self.note.get_buffer() + self.note_buffer.set_text(place.getNote()) + + self.top_window.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_switch_page" : self.on_switch_page, + "on_addphoto_clicked" : self.glry.on_add_photo_clicked, + "on_deletephoto_clicked" : self.glry.on_delete_photo_clicked, + "on_edit_properties_clicked": self.glry.popup_change_description, + "on_add_url_clicked" : self.on_add_url_clicked, + "on_delete_url_clicked" : self.on_delete_url_clicked, + "on_update_url_clicked" : self.on_update_url_clicked, + "on_add_loc_clicked" : self.on_add_loc_clicked, + "on_delete_loc_clicked" : self.on_delete_loc_clicked, + "on_update_loc_clicked" : self.on_update_loc_clicked, + "on_web_go_clicked" : self.on_web_go_clicked, + "on_apply_clicked" : self.on_place_apply_clicked + }) + + self.top = self.top_window.get_widget("placeEditor") + + self.sourcetab = Sources.SourceTab(self.srcreflist,self, + self.top_window,self.slist, + self.top_window.get_widget('add_src'), + self.top_window.get_widget('del_src')) + + if self.place.getId() == "": + self.top_window.get_widget("add_photo").set_sensitive(0) + self.top_window.get_widget("delete_photo").set_sensitive(0) + + self.web_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, + pycode_tgts,gtk.gdk.ACTION_COPY) + self.web_list.drag_source_set(gtk.gdk.BUTTON1_MASK, + pycode_tgts, gtk.gdk.ACTION_COPY) + self.web_list.connect('drag_data_get', + self.url_source_drag_data_get) + self.web_list.connect('drag_data_received', + self.url_dest_drag_data_received) + + self.redraw_url_list() + self.redraw_location_list() + + def build_columns(self,tree,list): + cnum = 0 + for name in list: + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn(name[0],renderer,text=cnum) + column.set_min_width(name[1]) + cnum = cnum + 1 + tree.append_column(column) + + def url_dest_drag_data_received(self,widget,context,x,y,sel_data,info,time): + if sel_data and sel_data.data: + exec 'data = %s' % sel_data.data + exec 'mytype = "%s"' % data[0] + exec 'place = "%s"' % data[1] + if place == self.place.getId() or mytype != 'url': + return + foo = pickle.loads(data[2]); + self.ulist.append(foo) + self.lists_changed = 1 + self.redraw_url_list() + + def url_source_drag_data_get(self,widget, context, sel_data, info, time): + ev = widget.get_row_data(widget.focus_row) + + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('url',self.place.getId(),pickled)); + sel_data.set(sel_data.target, bits_per, data) + + def update_lists(self): + self.place.setUrlList(self.ulist) + self.place.set_alternate_locations(self.llist) + if self.lists_changed: + Utils.modified() + + def redraw_url_list(self): + length = Utils.redraw_list(self.ulist,self.web_model,disp_url) + if length > 0: + self.web_go.set_sensitive(1) + else: + self.web_go.set_sensitive(0) + self.web_url.set_text("") + self.web_description.set_text("") + + def redraw_location_list(self): + Utils.redraw_list(self.llist,self.loc_model,disp_loc) + + def on_web_go_clicked(self,obj): + import gnome.url + + text = obj.get() + if text != "": + gnome.url.show(text) + + def set(self,field,getf,setf): + text = field.get_text() + if text != getf(): + setf(text) + Utils.modified() + + def on_place_apply_clicked(self,obj): + + note = self.note_buffer.get_text(self.note_buffer.get_start_iter(), + self.note_buffer.get_end_iter(),gtk.FALSE) + mloc = self.place.get_main_location() + + self.set(self.city,mloc.get_city,mloc.set_city) + self.set(self.parish,mloc.get_parish,mloc.set_parish) + self.set(self.state,mloc.get_state,mloc.set_state) + self.set(self.county,mloc.get_county,mloc.set_county) + self.set(self.country,mloc.get_country,mloc.set_country) + self.set(self.title,self.place.get_title,self.place.set_title) + self.set(self.longitude,self.place.get_longitude, + self.place.set_longitude) + self.set(self.latitude,self.place.get_latitude, + self.place.set_latitude) + + if self.lists_changed: + self.place.setSourceRefList(self.srcreflist) + Utils.modified() + + if note != self.place.getNote(): + self.place.setNote(note) + Utils.modified() + + self.update_lists() + + Utils.destroy_passed_object(self.top) + if self.callback: + self.callback(self.place) + + def on_switch_page(self,obj,a,page): + if page == 3 and self.not_loaded: + self.not_loaded = 0 + self.glry.load_images() + elif page == 5 and self.ref_not_loaded: + self.ref_not_loaded = 0 + self.display_references() + + def on_update_url_clicked(self,obj): + import UrlEdit + if len(obj.selection) > 0: + row = obj.selection[0] + if self.place: + name = _("Internet Address Editor for %s") % self.place.get_title() + else: + name = _("Internet Address Editor") + UrlEdit.UrlEditor(self,name,obj.get_row_data(row)) + + def on_update_loc_clicked(self,obj): + import LocEdit + if obj.selection: + row = obj.selection[0] + LocEdit.LocationEditor(self,obj.get_row_data(row)) + + def on_delete_url_clicked(self,obj): + if Utils.delete_selected(obj,self.ulist): + self.lists_changed = 1 + self.redraw_url_list() + + def on_delete_loc_clicked(self,obj): + if Utils.delete_selected(obj,self.llist): + self.lists_changed = 1 + self.redraw_location_list() + + def on_add_url_clicked(self,obj): + import UrlEdit + if self.place: + name = _("Internet Address Editor for %s") % self.place.get_title() + else: + name = _("Internet Address Editor") + UrlEdit.UrlEditor(self,name,None) + + def on_add_loc_clicked(self,obj): + import LocEdit + LocEdit.LocationEditor(self,None) + + def on_web_list_select_row(self,obj): + store,iter = obj.get_selected() + if not iter: + self.web_url.set_text("") + self.web_go.set_sensitive(0) + self.web_description.set_text("") + else: + row = store.get_path(iter) + url = self.ulist[row[0]] + path = url.get_path() + self.web_url.set_text(path) + self.web_go.set_sensitive(1) + self.web_description.set_text(url.get_description()) + + def on_loc_list_select_row(self,obj,row,b,c): + loc = obj.get_row_data(row) + + self.loc_city.set_text(loc.get_city()) + self.loc_county.set_text(loc.get_county()) + self.loc_state.set_text(loc.get_state()) + self.loc_parish.set_text(loc.get_parish()) + self.loc_country.set_text(loc.get_country()) + + def display_references(self): + pevent = [] + fevent = [] + msg = "" + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + for event in [p.getBirth(), p.getDeath()] + p.getEventList(): + if event.getPlace() == self.place: + pevent.append((p,event)) + for f in self.db.getFamilyMap().values(): + for event in f.getEventList(): + if event.getPlace() == self.place: + fevent.append((f,event)) + + if len(pevent) > 0: + msg = msg + _("People") + "\n" + msg = msg + "_________________________\n\n" + t = _("%s [%s]: event %s\n") + + for e in pevent: + msg = msg + ( t % (GrampsCfg.nameof(e[0]),e[0].getId(),e[1].getName())) + + if len(fevent) > 0: + msg = msg + "\n%s\n" % _("Families") + msg = msg + "_________________________\n\n" + t = _("%s [%s]: event %s\n") + + for e in fevent: + father = e[0].getFather() + mother = e[0].getMother() + if father and mother: + fname = "%s and %s" % (GrampsCfg.nameof(father),GrampsCfg.nameof(mother)) + elif father: + fname = "%s" % GrampsCfg.nameof(father) + else: + fname = "%s" % GrampsCfg.nameof(mother) + + msg = msg + ( t % (fname,e[0].getId(),e[1].getName())) + + self.refinfo.get_buffer().set_text(msg) + +#------------------------------------------------------------------------- +# +# disp_url +# +#------------------------------------------------------------------------- +def disp_url(url): + return [url.get_path(),url.get_description()] + +#------------------------------------------------------------------------- +# +# disp_loc +# +#------------------------------------------------------------------------- +def disp_loc(loc): + return [loc.get_city(),loc.get_county(),loc.get_state(),loc.get_country()] + +#------------------------------------------------------------------------- +# +# DeletePlaceQuery +# +#------------------------------------------------------------------------- +class DeletePlaceQuery: + + def __init__(self,place,db,update): + self.db = db + self.place = place + self.update = update + + def query_response(self): + del self.db.getPlaceMap()[self.place.getId()] + Utils.modified() + + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + for event in [p.getBirth(), p.getDeath()] + p.getEventList(): + if event.getPlace() == self.place: + event.setPlace(None) + for f in self.db.getFamilyMap().values(): + for event in f.getEventList(): + if event.getPlace() == self.place: + event.setPlace(None) + self.update(0) diff --git a/gramps2/src/EditSource.py b/gramps2/src/EditSource.py new file mode 100644 index 000000000..ae7c11dd3 --- /dev/null +++ b/gramps2/src/EditSource.py @@ -0,0 +1,263 @@ +#! /usr/bin/python -O +# +# 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 gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import GrampsCfg +from RelLib import * +import ImageSelect + +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# Constants +# +#------------------------------------------------------------------------- + +class EditSource: + + def __init__(self,source,db,func=None): + self.source = source + self.db = db + self.callback = func + self.path = db.getSavePath() + self.not_loaded = 1 + self.ref_not_loaded = 1 + + self.top_window = gtk.glade.XML(const.gladeFile,"sourceEditor") + plwidget = self.top_window.get_widget("iconlist") + self.gallery = ImageSelect.Gallery(source, self.path, plwidget, db, self) + self.title = self.top_window.get_widget("source_title") + self.author = self.top_window.get_widget("author") + self.pubinfo = self.top_window.get_widget("pubinfo") + self.note = self.top_window.get_widget("source_note") + self.notes_buffer = self.note.get_buffer() + + self.refinfo = self.top_window.get_widget("refinfo") + + self.title.set_text(source.getTitle()) + self.author.set_text(source.getAuthor()) + self.pubinfo.set_text(source.getPubInfo()) + + self.notes_buffer.set_text(source.getNote()) + + self.top_window.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_switch_page" : self.on_switch_page, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, + "on_edit_properties_clicked": self.gallery.popup_change_description, + "on_sourceapply_clicked" : self.on_source_apply_clicked + }) + + self.top = self.top_window.get_widget("sourceEditor") + + if self.source.getId() == "": + self.top_window.get_widget("add_photo").set_sensitive(0) + self.top_window.get_widget("delete_photo").set_sensitive(0) + + def display_references(self): + p_event_list = [] + p_attr_list = [] + p_addr_list = [] + p_name_list = [] + m_list = [] + f_event_list = [] + f_attr_list = [] + p_list = [] + for key in self.db.getPlaceKeys(): + p = self.db.getPlace(key) + name = p.get_title() + for sref in p.getSourceRefList(): + if sref.getBase() == self.source: + p_list.append(name) + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + name = GrampsCfg.nameof(p) + for v in p.getEventList() + [p.getBirth(), p.getDeath()]: + for sref in v.getSourceRefList(): + if sref.getBase() == self.source: + p_event_list.append((name,v.getName())) + for v in p.getAttributeList(): + for sref in v.getSourceRefList(): + if sref.getBase() == self.source: + p_attr_list.append((name,v.getType())) + for v in p.getAlternateNames() + [p.getPrimaryName()]: + for sref in v.getSourceRefList(): + if sref.getBase() == self.source: + p_name_list.append((name,v.getName())) + for v in p.getAddressList(): + for sref in v.getSourceRefList(): + if sref.getBase() == self.source: + p_addr_list.append((name,v.getStreet())) + for p in self.db.getObjectMap().values(): + name = p.getDescription() + for sref in p.getSourceRefList(): + if sref.getBase() == self.source: + m_list.append(name) + for p in self.db.getFamilyMap().values(): + f = p.getFather() + m = p.getMother() + if f and m: + name = _("%(father)s and %(mother)s") % { + "father" : GrampsCfg.nameof(f), + "mother" : GrampsCfg.nameof(m)} + elif f: + name = GrampsCfg.nameof(f) + else: + name = GrampsCfg.nameof(m) + for v in p.getEventList(): + for sref in v.getSourceRefList(): + if sref.getBase() == self.source: + f_event_list.append((name,v.getName())) + for v in p.getAttributeList(): + for sref in v.getSourceRefList(): + if sref.getBase() == self.source: + f_attr_list.append((name,v.getType())) + + slist = self.top_window.get_widget('slist') + if len(p_event_list) > 0: + for p in p_event_list: + slist.append([_("Individual Events"),p[0], + const.display_pevent(p[1])]) + if len(p_attr_list) > 0: + for p in p_attr_list: + slist.append([_("Individual Attributes"),p[0], + const.display_pattr(p[1])]) + if len(p_name_list) > 0: + for p in p_name_list: + slist.append([_("Individual Names"),p[0],p[1]]) + if len(f_event_list) > 0: + for p in f_event_list: + slist.append([_("Family Events"),p[0], + const.display_fevent(p[1])]) + if len(f_attr_list) > 0: + for p in f_event_list: + slist.append([_("Family Attributes"),p[0], + const.display_fattr(p[1])]) + if len(m_list) > 0: + for p in m_list: + slist.append([_("Media Objects"),p,'']) + if len(p_list) > 0: + for p in p_list: + slist.append([_("Places"),p,'']) + + def on_source_apply_clicked(self,obj): + + title = self.title.get_text() + author = self.author.get_text() + pubinfo = self.pubinfo.get_text() + note = self.notes_buffer.get_text() + + if author != self.source.getAuthor(): + self.source.setAuthor(author) + Utils.modified() + + if title != self.source.getTitle(): + self.source.setTitle(title) + Utils.modified() + + if pubinfo != self.source.getPubInfo(): + self.source.setPubInfo(pubinfo) + Utils.modified() + + if note != self.source.getNote(): + self.source.setNote(note) + Utils.modified() + + Utils.destroy_passed_object(self.top) + if self.callback: + self.callback(self.source) + + def on_switch_page(self,obj,a,page): + if page == 2 and self.not_loaded: + self.not_loaded = 0 + self.gallery.load_images() + elif page == 3 and self.ref_not_loaded: + self.ref_not_loaded = 0 + self.display_references() + + +class DelSrcQuery: + def __init__(self,source,db,update): + self.source = source + self.db = db + self.update = update + + def delete_source(self,object): + m = 0 + l = [] + for sref in object.getSourceRefList(): + if sref.getBase() != self.source: + l.append(sref) + else: + m = 1 + if m: + object.setSourceRefList(l) + + def query_response(self): + del self.db.getSourceMap()[self.source.getId()] + Utils.modified() + + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + for v in p.getEventList() + [p.getBirth(), p.getDeath()]: + self.delete_source(v) + + for v in p.getAttributeList(): + self.delete_source(v) + + for v in p.getAlternateNames() + [p.getPrimaryName()]: + self.delete_source(v) + + for v in p.getAddressList(): + self.delete_source(v) + + for p in self.db.getFamilyMap().values(): + for v in p.getEventList(): + self.delete_source(v) + + for v in p.getAttributeList(): + self.delete_source(v) + + for p in self.db.getObjectMap().values(): + self.delete_source(p) + + for key in self.db.getPlaceKeys(): + self.delete_source(self.db.getPlace(key)) + + self.update(0) + + + diff --git a/gramps2/src/EventEdit.py b/gramps2/src/EventEdit.py new file mode 100644 index 000000000..405cb4c83 --- /dev/null +++ b/gramps2/src/EventEdit.py @@ -0,0 +1,226 @@ +# +# 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 string import strip + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import Sources +import const +import Utils +import GrampsCfg +import AutoComp + +from DateEdit import DateEdit +from Date import compare_dates +from RelLib import * +from intl import gettext as _ + +#------------------------------------------------------------------------- +# +# EventEditor class +# +#------------------------------------------------------------------------- +class EventEditor: + + def __init__(self,parent,name,list,trans,event,def_placename,read_only,cb): + self.parent = parent + self.event = event + self.trans = trans + self.callback = cb + self.plist = [] + self.pmap = {} + + for key in self.parent.db.getPlaceKeys(): + p = self.parent.db.getPlaceDisplay(key) + self.pmap[p[0]] = key + + if event: + self.srcreflist = self.event.getSourceRefList() + self.date = Date(self.event.getDateObj()) + else: + self.srcreflist = [] + self.date = Date(None) + + self.top = gtk.glade.XML(const.dialogFile, "event_edit") + self.window = self.top.get_widget("event_edit") + self.name_field = self.top.get_widget("eventName") + self.place_field = self.top.get_widget("eventPlace") + self.cause_field = self.top.get_widget("eventCause") + self.slist = self.top.get_widget("slist") + self.place_combo = self.top.get_widget("eventPlace_combo") + self.date_field = self.top.get_widget("eventDate") + self.cause_field = self.top.get_widget("eventCause") + self.descr_field = self.top.get_widget("event_description") + self.note_field = self.top.get_widget("eventNote") + self.event_menu = self.top.get_widget("personalEvents") + self.priv = self.top.get_widget("priv") + self.calendar = self.top.get_widget("calendar") + + if GrampsCfg.calendar: + self.calendar.show() + else: + self.calendar.hide() + + self.top.get_widget("eventTitle").set_text(name) + if read_only: + self.event_menu.set_sensitive(0) + self.date_field.grab_focus() + + self.sourcetab = Sources.SourceTab(self.srcreflist,self.parent, + self.top,self.slist, + self.top.get_widget('add_src'), + self.top.get_widget('del_src')) + + AutoComp.AutoEntry(self.event_menu.entry,list) + AutoComp.AutoEntry(self.place_field,self.pmap.keys()) + + if event != None: + self.name_field.set_text(event.getName()) + if (def_placename): + self.place_field.set_text(def_placename) + else: + self.place_field.set_text(event.getPlaceName()) + + self.date_field.set_text(self.date.getDate()) + self.cause_field.set_text(event.getCause()) + self.descr_field.set_text(event.getDescription()) + self.priv.set_active(event.getPrivacy()) + + self.note_field.get_buffer().set_text(event.getNote()) + else: + if (def_placename): + self.place_field.set_text(def_placename) + self.date_check = DateEdit(self.date_field,self.top.get_widget("date_stat")) + +# if not read_only: +# self.name_field.select_region(0, -1) + + self.top.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_add_src_clicked" : self.add_source, + "on_del_src_clicked" : self.del_source, + "on_event_edit_ok_clicked" : self.on_event_edit_ok_clicked, + }) + + menu = gtk.Menu() + names = [ _("Gregorian"), _("Julian"), _("Hebrew"), ("French") ] + for index in range(0,len(names)): + item = gtk.MenuItem(names[index]) + item.set_data("d",index) + item.connect("activate",self.on_menu_changed) + item.show() + menu.append(item) + menu.set_active(self.date.get_calendar()) + self.calendar.set_menu(menu) + + def add_source(self,obj): + pass + + def del_source(self,obj): + pass + + def on_menu_changed(self,obj): + self.date.set_calendar(obj.get_data("d")) + self.date_field.set_text(self.date.getDate()) + + def get_place(self,field,makenew=0): + text = strip(field.get_text()) + if text != "": + if self.pmap.has_key(text): + return self.parent.db.getPlaceMap()[self.pmap[text]] + elif makenew: + place = Place() + place.set_title(text) + self.parent.db.addPlace(place) + self.pmap[text] = place.getId() + self.plist.append(place) + Utils.modified() + return place + else: + return None + else: + return None + + def on_event_edit_ok_clicked(self,obj): + + ename = self.name_field.get_text() + self.date.set(self.date_field.get_text()) + ecause = self.cause_field.get_text() + eplace_obj = self.get_place(self.place_field,1) + buf = self.note_field.get_buffer() + + enote = buf.get_text(buf.get_start_iter(),buf.get_end_iter(),gtk.FALSE) + edesc = self.descr_field.get_text() + epriv = self.priv.get_active() + + if self.event == None: + self.event = Event() + self.event.setSourceRefList(self.srcreflist) + self.parent.elist.append(self.event) + + self.update_event(ename,self.date,eplace_obj,edesc,enote,epriv,ecause) + self.parent.redraw_event_list() + self.callback(None,self.plist) + Utils.destroy_passed_object(obj) + + def update_event(self,name,date,place,desc,note,priv,cause): + if self.event.getPlace() != place: + self.event.setPlace(place) + self.parent.lists_changed = 1 + + if self.event.getName() != self.trans(name): + self.event.setName(self.trans(name)) + self.parent.lists_changed = 1 + + if self.event.getDescription() != desc: + self.event.setDescription(desc) + self.parent.lists_changed = 1 + + if self.event.getNote() != note: + self.event.setNote(note) + self.parent.lists_changed = 1 + + dobj = self.event.getDateObj() + + self.event.setSourceRefList(self.srcreflist) + + if compare_dates(dobj,date) != 0: + self.event.setDateObj(date) + self.parent.lists_changed = 1 + + if self.event.getCause() != cause: + self.event.setCause(cause) + self.parent.lists_changed = 1 + + if self.event.getPrivacy() != priv: + self.event.setPrivacy(priv) + self.parent.lists_changed = 1 diff --git a/gramps2/src/FamilyView.py b/gramps2/src/FamilyView.py new file mode 100644 index 000000000..83e27a31a --- /dev/null +++ b/gramps2/src/FamilyView.py @@ -0,0 +1,438 @@ +# +# 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 gobject +import gtk +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import sort +from intl import gettext as _ +import Utils +import GrampsCfg +from RelLib import Person + +import AddSpouse +import DisplayTrace +import Marriage +import ChooseParents + +#------------------------------------------------------------------------- +# +# FamilyView +# +#------------------------------------------------------------------------- +class FamilyView: + + def __init__(self,parent): + self.parent = parent + self.top = parent.gtop + self.ap_data = self.top.get_widget('ap_data').get_buffer() + + self.swap_btn = self.top.get_widget('swap_spouse_btn') + self.add_spouse_btn = self.top.get_widget('add_spouse') + self.remove_spouse_btn = self.top.get_widget('remove_spouse') + + self.ap_parents = self.top.get_widget('ap_parents') + self.ap_parents_model = gtk.ListStore(gobject.TYPE_STRING) + self.ap_parents.set_model(self.ap_parents_model) + self.ap_selection = self.ap_parents.get_selection() + column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0) + self.ap_parents.append_column(column) + self.ap_parents.connect('button-press-event',self.edit_ap_parents) + + self.sp_parents = self.top.get_widget('sp_parents') + self.sp_parents_model = gtk.ListStore(gobject.TYPE_STRING) + self.sp_parents.set_model(self.sp_parents_model) + self.sp_selection = self.sp_parents.get_selection() + column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0) + self.sp_parents.append_column(column) + self.sp_parents.connect('button-press-event',self.edit_sp_parents) + + self.spouse_list = self.top.get_widget('sp_list') + self.spouse_model = gtk.ListStore(gobject.TYPE_STRING) + self.spouse_list.set_model(self.spouse_model) + self.spouse_selection = self.spouse_list.get_selection() + self.spouse_selection.connect('changed',self.spouse_changed) + + self.top.get_widget('add_parents').connect('clicked',self.add_parents_clicked) + self.top.get_widget('del_parents').connect('clicked',self.del_parents_clicked) + self.top.get_widget('add_spparents').connect('clicked',self.add_sp_parents) + self.top.get_widget('del_spparents').connect('clicked',self.del_sp_parents) + + column = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0) + self.spouse_list.append_column(column) + self.selected_spouse = None + + self.child_list = self.top.get_widget('chlist') + self.child_model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING, + gobject.TYPE_STRING,gobject.TYPE_STRING, + gobject.TYPE_STRING,gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.child_selection = self.child_list.get_selection() + + self.child_list.connect('button-press-event',self.on_child_list_button_press) + + self.top.get_widget('ap_parents_btn').connect('clicked',self.ap_parents_clicked) + self.top.get_widget('sp_parents_btn').connect('clicked',self.sp_parents_clicked) + + self.swap_btn.connect('clicked',self.spouse_swap) + self.remove_spouse_btn.connect('clicked',self.remove_spouse) + self.add_spouse_btn.connect('clicked',self.add_spouse) + self.spouse_list.connect('button-press-event',self.edit_releationship) + + + self.child_list.set_model(self.child_model) + self.child_list.set_search_column(0) + self.child_selection = self.child_list.get_selection() + + colno = 0 + for title in [ (_('Order'),0), (_('Name'),1), (_('ID'),2), + (_('Gender'),3), (_('Birth Date'),4), + (_('Status'),5), ('',6) ]: + renderer = gtk.CellRendererText () + column = gtk.TreeViewColumn (title[0], renderer, text=colno) + colno = colno + 1 + column.set_clickable (gtk.TRUE) + if title[0] == '': + column.set_clickable(gtk.TRUE) + column.set_visible(gtk.FALSE) + column.set_sort_column_id(title[1]) + self.child_list.append_column (column) + + def on_child_list_button_press(self,obj,event): + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + model, iter = self.child_selection.get_selected() + if iter: + id = self.child_model.get_value(iter,2) + self.parent.load_person(self.parent.db.getPerson(id)) + + def spouse_changed(self,obj): + model, iter = obj.get_selected() + if not iter: + self.display_marriage(None) + else: + row = model.get_path(iter) + self.display_marriage(self.person.getFamilyList()[row[0]]) + + def edit_releationship(self,obj,event): + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + if self.person: + try: + Marriage.Marriage(self.family,self.parent.db, + self.parent.new_after_edit) + except: + DisplayTrace.DisplayTrace() + + def add_spouse(self,obj): + if not self.person: + return + try: + AddSpouse.AddSpouse(self.parent.db, self.person, + self.load_family, + self.parent.redisplay_person_list) + except: + DisplayTrace.DisplayTrace() + + def remove_spouse(self,obj): + """Delete the currently selected spouse from the family""" + if self.person == None: + return + if self.selected_spouse == self.family.getFather(): + self.family.setMother(None) + else: + self.family.setFather(None) + + if self.selected_spouse: + self.selected_spouse.removeFamily(self.family) + + if len(self.family.getChildList()) == 0: + self.person.removeFamily(self.family) + self.parent.db.deleteFamily(self.family) + if len(self.person.getFamilyList()) > 0: + self.load_family(self.person.getFamilyList()[0]) + else: + self.load_family() + else: + self.load_family() + + if len(self.person.getFamilyList()) <= 1: + self.spouse_selection.set_mode(gtk.SELECTION_NONE) + + Utils.modified() + + def spouse_swap(self,obj): + if self.selected_spouse: + self.parent.active_person = self.selected_spouse + self.load_family() + + def ap_parents_clicked(self,obj): + self.change_families(self.person) + + def sp_parents_clicked(self,obj): + self.change_families(self.selected_spouse) + + def change_families(self,person): + if not person: + return + plist = person.getParentList() + + if len(plist) == 0: + return + if len(plist) == 1: + family,m,r = plist[0] + else: + model, iter = self.ap_selection.get_selected() + path = model.get_path(iter) + family,m,r = plist[path[0]] + + if family.getFather(): + person = family.getFather() + else: + person = family.getMother() + self.parent.change_active_person(person) + self.load_family(family) + + + def load_family(self,family=None): + self.person = self.parent.active_person + if not self.person: + return + + n = "%s\n\tb. %s\n\td. %s" % (self.person.getPrimaryName().getName(), + self.person.getBirth().getDate(), + self.person.getDeath().getDate()) + self.ap_data.set_text(n,len(n)) + + self.selected_spouse = None + self.spouse_model.clear() + splist = self.person.getFamilyList() + f = None + first_family = None + first_spouse = None + for f in splist: + if not f: + continue + if f.getFather() == self.person: + sp = f.getMother() + else: + sp = f.getFather() + + iter = self.spouse_model.append() + if f == family: + first_spouse = sp + first_family = f + elif first_spouse == None: + first_spouse = sp + first_family = f + + if len(splist) > 1: + self.spouse_selection.set_mode(gtk.SELECTION_SINGLE) + self.spouse_selection.select_iter(iter) + else: + self.spouse_selection.set_mode(gtk.SELECTION_NONE) + + if sp: + if f.getMarriage(): + mdate = " - %s" % f.getMarriage().getDate() + else: + mdate = "" + v = "%s\n\t%s%s" % (sp.getPrimaryName().getName(), + f.getRelationship(),mdate) + self.spouse_model.set(iter,0,v) + else: + self.spouse_model.set(iter,0,"unknown\n") + + if first_family: + self.display_marriage(first_family) + + self.update_list(self.ap_parents_model,self.ap_parents,self.person) + self.family = first_family + + def update_list(self,model,tree,person): + model.clear() + sel = None + selection = tree.get_selection() + list = person.getParentList() + + for (f,mrel,frel) in list: + + father = self.nameof(_("Father"),f.getFather(),frel) + mother = self.nameof(_("Mother"),f.getMother(),mrel) + + iter = model.append() + if not sel: + sel = iter + v = "%s\n%s" % (father,mother) + model.set(iter,0,v) + if len(list) > 1: + selection.set_mode(gtk.SELECTION_SINGLE) + selection.select_iter(sel) + else: + selection.set_mode(gtk.SELECTION_NONE) + + def nameof(self,l,p,mode): + if p: + n = p.getPrimaryName().getName() + return "%s: %s\n\tRelationship: %s" % (l,n,mode) + else: + return "unknown\n" + + def display_marriage(self,family): + + self.child_model.clear() + if not family: + return + else: + self.family = family + + if family.getFather() == self.person: + self.selected_spouse = family.getMother() + else: + self.selected_spouse = family.getFather() + + if self.selected_spouse: + self.update_list(self.sp_parents_model,self.sp_parents, + self.selected_spouse) + + i = 0 + fiter = None + child_list = list(family.getChildList()) + child_list.sort(sort.by_birthdate) + + self.child_map = {} + + attr = "" + for child in child_list: + status = _("Unknown") + if child.getGender() == Person.male: + gender = const.male + elif child.getGender() == Person.female: + gender = const.female + else: + gender = const.unknown + for fam in child.getParentList(): + if fam[0] == family: + if self.person == family.getFather(): + status = "%s/%s" % (_(fam[2]),_(fam[1])) + else: + status = "%s/%s" % (_(fam[1]),_(fam[2])) + + iter = self.child_model.append() + self.child_map[iter] = child.getId() + + if fiter == None: + fiter = self.child_model.get_path(iter) + self.child_model.set(iter, + 0,(i+1), + 1,GrampsCfg.nameof(child), + 2,child.getId(), + 3,gender, + 4,Utils.birthday(child), + 5,status, + 6,attr) + + def edit_ap_parents(self,obj,event): + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + self.parent_editor(self.person,self.ap_selection) + + def edit_sp_parents(self,obj,event): + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + self.parent_editor(self.selected_spouse,self.sp_selection) + + def add_parents_clicked(self,obj): + self.parent_add(self.person) + + def add_sp_parents(self,obj): + self.parent_editor(self.selected_spouse,self.sp_selection) + + def del_parents_clicked(self,obj): + self.parent_deleter(self.person,self.ap_selection) + + def del_sp_parents(self,obj): + self.parent_deleter(self.selected_spouse,self.sp_selection) + + def parent_editor(self,person,selection): + if not person: + return + + plist = person.getParentList() + + if len(plist) == 0: + return + elif len(plist) == 1: + parents,mrel,frel = plist[0] + else: + model, iter = selection.get_selected() + if not iter: + return + + row = model.get_path(iter) + parents,mrel,frel = plist[row[0]] + + try: + ChooseParents.ModifyParents(self.parent.db,person,parents, + self.load_family,self.parent.full_update) + except: + DisplayTrace.DisplayTrace() + + def parent_add(self,person): + if not person: + return + + try: + ChooseParents.ChooseParents(self.parent.db,person,None, + self.load_family,self.parent.full_update) + except: + DisplayTrace.DisplayTrace() + + def parent_deleter(self,person,selection): + if not person: + return + + plist = person.getParentList() + + if len(plist) == 0: + return + + if len(plist) == 1: + person.clearAltFamilyList() + else: + model, iter = selection.get_selected() + if not iter: + return + + row = model.get_path(iter) + fam = person.getParentList()[row[0]] + person.removeAltFamily(fam[0]) + self.load_family() + + + diff --git a/gramps2/src/Filter.py b/gramps2/src/Filter.py new file mode 100644 index 000000000..0f9773b4f --- /dev/null +++ b/gramps2/src/Filter.py @@ -0,0 +1,142 @@ +# +# 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 re +import os +import sys +import gtk + +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# Base filter class +# +#------------------------------------------------------------------------- +class Filter: + + def __init__(self,text): + self.text = text + self.invert = 0 + + def get_text(self): + return self.text + + def get_invert(self): + return self.invert + + def set_invert(self,invert): + self.invert = invert + + def compare(self,person): + val = self.match(person) + if self.invert: + return not val + else: + return val + + def get_name(self): + return str(self.__class__) + + def match(self,person): + return 1 + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- + +_filter_list = [(Filter, _("All people"), 0, _("Qualifier"))] +_filter2class = {} +_filter2descr = {} + +def register_filter(class_name, description=None, qualifier=0, label=None): + name = str(class_name) + if label == None: + label = _("Qualifier") + if description == None: + description = _("No description") + _filter2class[name] = class_name + _filter2descr[name] = description + _filter_list.append((class_name,description,qualifier,label)) + +def get_filter_description(name): + if _filter2descr.has_key(name): + return _filter2descr[name] + else: + return "" + +def make_filter_from_name(name,qualifier,invert): + a = _filter2class[name](qualifier) + a.set_invert(invert) + return a + +#------------------------------------------------------------------------- +# +# load_filters - loads all filters in the specfied directory. Assumes +# that the filters will register themselves +# +#------------------------------------------------------------------------- +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: + plugin = match.groups()[0] + try: + __import__(plugin) + except: + print _("Failed to load the module: %s") % plugin + import traceback + traceback.print_exc() + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def build_filter_menu(callback,fw): + myMenu = gtk.Menu() + for filter in _filter_list: + menuitem = gtk.MenuItem(filter[1]) + myMenu.append(menuitem) + menuitem.set_data("filter",fw) + menuitem.set_data("name",filter[1]) + menuitem.set_data("function",filter[0]) + menuitem.set_data("qual",filter[2]) + menuitem.set_data("label",filter[3]) + menuitem.connect("activate",callback) + menuitem.show() + return myMenu + + diff --git a/gramps2/src/Find.py b/gramps2/src/Find.py new file mode 100644 index 000000000..dec927e41 --- /dev/null +++ b/gramps2/src/Find.py @@ -0,0 +1,255 @@ +# +# 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 +# + +"""interface for opening a find person dialog for gramps +""" + +__author__ = 'Don Allingham' + +#------------------------------------------------------------------------- +# +# python modules +# +#------------------------------------------------------------------------- +import string + +#------------------------------------------------------------------------- +# +# Gnome modules +# +#------------------------------------------------------------------------- +import gtk +from gnome.ui import * + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import GrampsCfg +import AutoComp +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# FindBase +# +#------------------------------------------------------------------------- +class FindBase: + """Opens find person dialog for gramps""" + + def __init__(self,clist,task,name,db): + """Opens a dialog box instance that allows users to + search for a person. + + clist - GtkCList containing the people information + task - function to call to change the active person""" + + self.db = db + self.clist = clist + self.nlist = [] + self.task = task + title = "%s - GRAMPS" % name + self.top = GnomeDialog(title,STOCK_BUTTON_PREV, + STOCK_BUTTON_NEXT,STOCK_BUTTON_CLOSE) + self.top.set_policy(0,1,0) + self.top.vbox.set_spacing(5) + self.top.vbox.pack_start(gtk.GtkLabel(name),0,0,5) + self.top.vbox.pack_start(gtk.GtkHSeparator(),0,0,0) + self.entry = gtk.GtkEntry() + self.top.vbox.pack_start(self.entry,0,0,25) + self.top.button_connect(0,self.on_prev_clicked) + self.top.button_connect(1,self.on_next_clicked) + self.top.button_connect(2,self.on_close_clicked) + self.top.set_usize(350,175) + self.top.set_default(1) + self.top.show_all() + self.top.editable_enters(self.entry) + self.entry.grab_focus() + + def get_value(self,id): + return None + + def enable_autocomp(self): + if GrampsCfg.autocomp: + self.comp = AutoComp.AutoEntry(self.entry,self.nlist) + + def advance(self,func): + try: + self.row = self.clist.selection[0] + except IndexError: + gtk.gdk_beep() + return + + text = self.entry.get_text() + if self.row == None or text == "": + gtk.gdk_beep() + return + orow = self.row + func() + while self.row != orow: + id = self.clist.get_row_data(self.row) + if id == None: + func() + continue + if string.find(string.upper(self.get_value(id)),string.upper(text)) >= 0: + self.task(self.row) + return + func() + gtk.gdk_beep() + + def forward(self): + self.row = self.row + 1 + if self.row == self.clist.rows: + self.row = 0 + + def backward(self): + self.row = self.row - 1 + if self.row < 0: + self.row = self.clist.rows + + def on_close_clicked(self,obj): + """Destroys the window in response to a close window button press""" + self.top.destroy() + + def on_next_clicked(self,obj): + """Advances to the next person that matches the dialog text""" + self.advance(self.forward) + + def on_prev_clicked(self,obj): + """Advances to the previous person that matches the dialog text""" + self.advance(self.backward) + +#------------------------------------------------------------------------- +# +# FindPerson +# +#------------------------------------------------------------------------- +class FindPerson(FindBase): + """Opens a Find Person dialog for GRAMPS""" + + def __init__(self,clist,task,db): + """Opens a dialog box instance that allows users to + search for a person. + + clist - GtkCList containing the people information + task - function to call to change the active person""" + + FindBase.__init__(self,clist,task,_("Find Person"),db) + for n in self.db.getPersonKeys(): + val = self.db.getPersonDisplay(n) + self.nlist.append(val[0]) + self.enable_autocomp() + + def get_value(self,id): + return self.db.getPersonDisplay(id)[0] + + +#------------------------------------------------------------------------- +# +# FindPlace +# +#------------------------------------------------------------------------- +class FindPlace(FindBase): + """Opens a Find Place dialog for GRAMPS""" + + def __init__(self,clist,task,db): + """Opens a dialog box instance that allows users to + search for a place. + + clist - GtkCList containing the people information + task - function to call to change the active person""" + + FindBase.__init__(self,clist,task,_("Find Place"),db) + for n in self.db.getPlaceKeys(): + self.nlist.append(self.db.getPlaceDisplay(n)[0]) + self.enable_autocomp() + + def get_value(self,id): + return self.db.getPlaceDisplay(id)[0] + +#------------------------------------------------------------------------- +# +# FindSource +# +#------------------------------------------------------------------------- +class FindSource(FindBase): + """Opens a Find Place dialog for GRAMPS""" + + def __init__(self,clist,task,db): + """Opens a dialog box instance that allows users to + search for a place. + + clist - GtkCList containing the people information + task - function to call to change the active person""" + + FindBase.__init__(self,clist,task,_("Find Source"),db) + for n in self.db.getSourceKeys(): + self.nlist.append(n[0]) + self.enable_autocomp() + + def get_value(self,id): + return self.db.getSourceDisplay(id)[0] + +#------------------------------------------------------------------------- +# +# FindMedia +# +#------------------------------------------------------------------------- +class FindMedia(FindBase): + """Opens a Find Media Object dialog for GRAMPS""" + + def __init__(self,clist,task,db): + """Opens a dialog box instance that allows users to + search for a place. + + clist - GtkCList containing the people information + task - function to call to change the active person""" + + FindBase.__init__(self,clist,task,_("Find Media Object"),db) + for n in self.db.getObjectMap().values(): + self.nlist.append(n.getDescription()) + self.enable_autocomp() + + def advance(self,func): + try: + self.row = self.clist.selection[0] + except IndexError: + gtk.gdk_beep() + return + + text = self.entry.get_text() + if self.row == None or text == "": + gtk.gdk_beep() + return + orow = self.row + func() + while self.row != orow: + value = self.clist.get_row_data(self.row) + if value == None: + func() + continue + name = value.getDescription() + if string.find(string.upper(name),string.upper(text)) >= 0: + self.task(self.row) + return + func() + gtk.gdk_beep() diff --git a/gramps2/src/FontScale.py b/gramps2/src/FontScale.py new file mode 100644 index 000000000..b6de44cdd --- /dev/null +++ b/gramps2/src/FontScale.py @@ -0,0 +1,260 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2001 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 +# +_swiss = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.278, 0.278, 0.355, 0.556, 0.556, 0.889, 0.667, 0.191, +0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278, 0.556, 0.556, +0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.278, 0.278, +0.584, 0.584, 0.584, 0.556, 1.015, 0.667, 0.667, 0.722, 0.722, 0.667, +0.611, 0.778, 0.722, 0.278, 0.500, 0.667, 0.556, 0.833, 0.722, 0.778, +0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944, 0.667, 0.667, +0.611, 0.278, 0.278, 0.278, 0.469, 0.556, 0.333, 0.556, 0.556, 0.500, +0.556, 0.556, 0.278, 0.556, 0.556, 0.222, 0.222, 0.500, 0.222, 0.833, +0.556, 0.556, 0.556, 0.556, 0.333, 0.500, 0.278, 0.556, 0.500, 0.722, +0.500, 0.500, 0.500, 0.334, 0.260, 0.334, 0.584, 0.350, 0.556, 0.350, +0.222, 0.556, 0.333, 1.000, 0.556, 0.556, 0.333, 1.000, 0.667, 0.333, +1.000, 0.350, 0.611, 0.350, 0.350, 0.222, 0.222, 0.333, 0.333, 0.350, +0.556, 1.000, 0.333, 1.000, 0.500, 0.333, 0.944, 0.350, 0.500, 0.667, +0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.260, 0.556, 0.333, 0.737, +0.370, 0.556, 0.584, 0.333, 0.737, 0.333, 0.400, 0.584, 0.333, 0.333, +0.333, 0.556, 0.537, 0.278, 0.333, 0.333, 0.365, 0.556, 0.834, 0.834, +0.834, 0.611, 0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 1.000, 0.722, +0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278, 0.722, 0.722, +0.778, 0.778, 0.778, 0.778, 0.778, 0.584, 0.778, 0.722, 0.722, 0.722, +0.722, 0.667, 0.667, 0.611, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, +0.889, 0.500, 0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278, +0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.584, 0.611, 0.556, +0.556, 0.556, 0.556, 0.500, 0.556, 0.500] + +_swiss_b = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.278, 0.333, 0.474, 0.556, 0.556, 0.889, 0.722, 0.238, +0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278, 0.556, 0.556, +0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.333, 0.333, +0.584, 0.584, 0.584, 0.611, 0.975, 0.722, 0.722, 0.722, 0.722, 0.667, +0.611, 0.778, 0.722, 0.278, 0.556, 0.722, 0.611, 0.833, 0.722, 0.778, +0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944, 0.667, 0.667, +0.611, 0.333, 0.278, 0.333, 0.584, 0.556, 0.333, 0.556, 0.611, 0.556, +0.611, 0.556, 0.333, 0.611, 0.611, 0.278, 0.278, 0.556, 0.278, 0.889, +0.611, 0.611, 0.611, 0.611, 0.389, 0.556, 0.333, 0.611, 0.556, 0.778, +0.556, 0.556, 0.500, 0.389, 0.280, 0.389, 0.584, 0.350, 0.556, 0.350, +0.278, 0.556, 0.500, 1.000, 0.556, 0.556, 0.333, 1.000, 0.667, 0.333, +1.000, 0.350, 0.611, 0.350, 0.350, 0.278, 0.278, 0.500, 0.500, 0.350, +0.556, 1.000, 0.333, 1.000, 0.556, 0.333, 0.944, 0.350, 0.500, 0.667, +0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.280, 0.556, 0.333, 0.737, +0.370, 0.556, 0.584, 0.333, 0.737, 0.333, 0.400, 0.584, 0.333, 0.333, +0.333, 0.611, 0.556, 0.278, 0.333, 0.333, 0.365, 0.556, 0.834, 0.834, +0.834, 0.611, 0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722, +0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278, 0.722, 0.722, +0.778, 0.778, 0.778, 0.778, 0.778, 0.584, 0.778, 0.722, 0.722, 0.722, +0.722, 0.667, 0.667, 0.611, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, +0.889, 0.556, 0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278, +0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.584, 0.611, 0.611, +0.611, 0.611, 0.611, 0.556, 0.611, 0.556] + +_swiss_i = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.278, 0.278, 0.355, 0.556, 0.556, 0.889, 0.667, 0.191, +0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278, 0.556, 0.556, +0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.278, 0.278, +0.584, 0.584, 0.584, 0.556, 1.015, 0.667, 0.667, 0.722, 0.722, 0.667, +0.611, 0.778, 0.722, 0.278, 0.500, 0.667, 0.556, 0.833, 0.722, 0.778, +0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944, 0.667, 0.667, +0.611, 0.278, 0.278, 0.278, 0.469, 0.556, 0.333, 0.556, 0.556, 0.500, +0.556, 0.556, 0.278, 0.556, 0.556, 0.222, 0.222, 0.500, 0.222, 0.833, +0.556, 0.556, 0.556, 0.556, 0.333, 0.500, 0.278, 0.556, 0.500, 0.722, +0.500, 0.500, 0.500, 0.334, 0.260, 0.334, 0.584, 0.350, 0.556, 0.350, +0.222, 0.556, 0.333, 1.000, 0.556, 0.556, 0.333, 1.000, 0.667, 0.333, +1.000, 0.350, 0.611, 0.350, 0.350, 0.222, 0.222, 0.333, 0.333, 0.350, +0.556, 1.000, 0.333, 1.000, 0.500, 0.333, 0.944, 0.350, 0.500, 0.667, +0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.260, 0.556, 0.333, 0.737, +0.370, 0.556, 0.584, 0.333, 0.737, 0.333, 0.400, 0.584, 0.333, 0.333, +0.333, 0.556, 0.537, 0.278, 0.333, 0.333, 0.365, 0.556, 0.834, 0.834, +0.834, 0.611, 0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 1.000, 0.722, +0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278, 0.722, 0.722, +0.778, 0.778, 0.778, 0.778, 0.778, 0.584, 0.778, 0.722, 0.722, 0.722, +0.722, 0.667, 0.667, 0.611, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, +0.889, 0.500, 0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278, +0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.584, 0.611, 0.556, +0.556, 0.556, 0.556, 0.500, 0.556, 0.500] + +_swiss_bi = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.278, 0.333, 0.474, 0.556, 0.556, 0.889, 0.722, 0.238, +0.333, 0.333, 0.389, 0.584, 0.278, 0.333, 0.278, 0.278, 0.556, 0.556, +0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, 0.333, 0.333, +0.584, 0.584, 0.584, 0.611, 0.975, 0.722, 0.722, 0.722, 0.722, 0.667, +0.611, 0.778, 0.722, 0.278, 0.556, 0.722, 0.611, 0.833, 0.722, 0.778, +0.667, 0.778, 0.722, 0.667, 0.611, 0.722, 0.667, 0.944, 0.667, 0.667, +0.611, 0.333, 0.278, 0.333, 0.584, 0.556, 0.333, 0.556, 0.611, 0.556, +0.611, 0.556, 0.333, 0.611, 0.611, 0.278, 0.278, 0.556, 0.278, 0.889, +0.611, 0.611, 0.611, 0.611, 0.389, 0.556, 0.333, 0.611, 0.556, 0.778, +0.556, 0.556, 0.500, 0.389, 0.280, 0.389, 0.584, 0.350, 0.556, 0.350, +0.278, 0.556, 0.500, 1.000, 0.556, 0.556, 0.333, 1.000, 0.667, 0.333, +1.000, 0.350, 0.611, 0.350, 0.350, 0.278, 0.278, 0.500, 0.500, 0.350, +0.556, 1.000, 0.333, 1.000, 0.556, 0.333, 0.944, 0.350, 0.500, 0.667, +0.278, 0.333, 0.556, 0.556, 0.556, 0.556, 0.280, 0.556, 0.333, 0.737, +0.370, 0.556, 0.584, 0.333, 0.737, 0.333, 0.400, 0.584, 0.333, 0.333, +0.333, 0.611, 0.556, 0.278, 0.333, 0.333, 0.365, 0.556, 0.834, 0.834, +0.834, 0.611, 0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722, +0.667, 0.667, 0.667, 0.667, 0.278, 0.278, 0.278, 0.278, 0.722, 0.722, +0.778, 0.778, 0.778, 0.778, 0.778, 0.584, 0.778, 0.722, 0.722, 0.722, +0.722, 0.667, 0.667, 0.611, 0.556, 0.556, 0.556, 0.556, 0.556, 0.556, +0.889, 0.556, 0.556, 0.556, 0.556, 0.556, 0.278, 0.278, 0.278, 0.278, +0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.584, 0.611, 0.611, +0.611, 0.611, 0.611, 0.556, 0.611, 0.556] + +_roman = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.250, 0.333, 0.408, 0.500, 0.500, 0.833, 0.778, 0.180, +0.333, 0.333, 0.500, 0.564, 0.250, 0.333, 0.250, 0.278, 0.500, 0.500, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.278, 0.278, +0.564, 0.564, 0.564, 0.444, 0.921, 0.722, 0.667, 0.667, 0.722, 0.611, +0.556, 0.722, 0.722, 0.333, 0.389, 0.722, 0.611, 0.889, 0.722, 0.722, +0.556, 0.722, 0.667, 0.556, 0.611, 0.722, 0.722, 0.944, 0.722, 0.722, +0.611, 0.333, 0.278, 0.333, 0.469, 0.500, 0.333, 0.444, 0.500, 0.444, +0.500, 0.444, 0.333, 0.500, 0.500, 0.278, 0.278, 0.500, 0.278, 0.778, +0.500, 0.500, 0.500, 0.500, 0.333, 0.389, 0.278, 0.500, 0.500, 0.722, +0.500, 0.500, 0.444, 0.480, 0.200, 0.480, 0.541, 0.350, 0.500, 0.350, +0.333, 0.500, 0.444, 1.000, 0.500, 0.500, 0.333, 1.000, 0.556, 0.333, +0.889, 0.350, 0.611, 0.350, 0.350, 0.333, 0.333, 0.444, 0.444, 0.350, +0.500, 1.000, 0.333, 0.980, 0.389, 0.333, 0.722, 0.350, 0.444, 0.722, +0.250, 0.333, 0.500, 0.500, 0.500, 0.500, 0.200, 0.500, 0.333, 0.760, +0.276, 0.500, 0.564, 0.333, 0.760, 0.333, 0.400, 0.564, 0.300, 0.300, +0.333, 0.500, 0.453, 0.250, 0.333, 0.300, 0.310, 0.500, 0.750, 0.750, +0.750, 0.444, 0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 0.889, 0.667, +0.611, 0.611, 0.611, 0.611, 0.333, 0.333, 0.333, 0.333, 0.722, 0.722, +0.722, 0.722, 0.722, 0.722, 0.722, 0.564, 0.722, 0.722, 0.722, 0.722, +0.722, 0.722, 0.556, 0.500, 0.444, 0.444, 0.444, 0.444, 0.444, 0.444, +0.667, 0.444, 0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.564, 0.500, 0.500, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500] + +_roman_b = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.250, 0.333, 0.555, 0.500, 0.500, 1.000, 0.833, 0.278, +0.333, 0.333, 0.500, 0.570, 0.250, 0.333, 0.250, 0.278, 0.500, 0.500, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.333, 0.333, +0.570, 0.570, 0.570, 0.500, 0.930, 0.722, 0.667, 0.722, 0.722, 0.667, +0.611, 0.778, 0.778, 0.389, 0.500, 0.778, 0.667, 0.944, 0.722, 0.778, +0.611, 0.778, 0.722, 0.556, 0.667, 0.722, 0.722, 1.000, 0.722, 0.722, +0.667, 0.333, 0.278, 0.333, 0.581, 0.500, 0.333, 0.500, 0.556, 0.444, +0.556, 0.444, 0.333, 0.500, 0.556, 0.278, 0.333, 0.556, 0.278, 0.833, +0.556, 0.500, 0.556, 0.556, 0.444, 0.389, 0.333, 0.556, 0.500, 0.722, +0.500, 0.500, 0.444, 0.394, 0.220, 0.394, 0.520, 0.350, 0.500, 0.350, +0.333, 0.500, 0.500, 1.000, 0.500, 0.500, 0.333, 1.000, 0.556, 0.333, +1.000, 0.350, 0.667, 0.350, 0.350, 0.333, 0.333, 0.500, 0.500, 0.350, +0.500, 1.000, 0.333, 1.000, 0.389, 0.333, 0.722, 0.350, 0.444, 0.722, +0.250, 0.333, 0.500, 0.500, 0.500, 0.500, 0.220, 0.500, 0.333, 0.747, +0.300, 0.500, 0.570, 0.333, 0.747, 0.333, 0.400, 0.570, 0.300, 0.300, +0.333, 0.556, 0.540, 0.250, 0.333, 0.300, 0.330, 0.500, 0.750, 0.750, +0.750, 0.500, 0.722, 0.722, 0.722, 0.722, 0.722, 0.722, 1.000, 0.722, +0.667, 0.667, 0.667, 0.667, 0.389, 0.389, 0.389, 0.389, 0.722, 0.722, +0.778, 0.778, 0.778, 0.778, 0.778, 0.570, 0.778, 0.722, 0.722, 0.722, +0.722, 0.722, 0.611, 0.556, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, +0.722, 0.444, 0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278, +0.500, 0.556, 0.500, 0.500, 0.500, 0.500, 0.500, 0.570, 0.500, 0.556, +0.556, 0.556, 0.556, 0.500, 0.556, 0.500] + +_roman_i = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.250, 0.333, 0.420, 0.500, 0.500, 0.833, 0.778, 0.214, +0.333, 0.333, 0.500, 0.675, 0.250, 0.333, 0.250, 0.278, 0.500, 0.500, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.333, 0.333, +0.675, 0.675, 0.675, 0.500, 0.920, 0.611, 0.611, 0.667, 0.722, 0.611, +0.611, 0.722, 0.722, 0.333, 0.444, 0.667, 0.556, 0.833, 0.667, 0.722, +0.611, 0.722, 0.611, 0.500, 0.556, 0.722, 0.611, 0.833, 0.611, 0.556, +0.556, 0.389, 0.278, 0.389, 0.422, 0.500, 0.333, 0.500, 0.500, 0.444, +0.500, 0.444, 0.278, 0.500, 0.500, 0.278, 0.278, 0.444, 0.278, 0.722, +0.500, 0.500, 0.500, 0.500, 0.389, 0.389, 0.278, 0.500, 0.444, 0.667, +0.444, 0.444, 0.389, 0.400, 0.275, 0.400, 0.541, 0.350, 0.500, 0.350, +0.333, 0.500, 0.556, 0.889, 0.500, 0.500, 0.333, 1.000, 0.500, 0.333, +0.944, 0.350, 0.556, 0.350, 0.350, 0.333, 0.333, 0.556, 0.556, 0.350, +0.500, 0.889, 0.333, 0.980, 0.389, 0.333, 0.667, 0.350, 0.389, 0.556, +0.250, 0.389, 0.500, 0.500, 0.500, 0.500, 0.275, 0.500, 0.333, 0.760, +0.276, 0.500, 0.675, 0.333, 0.760, 0.333, 0.400, 0.675, 0.300, 0.300, +0.333, 0.500, 0.523, 0.250, 0.333, 0.300, 0.310, 0.500, 0.750, 0.750, +0.750, 0.500, 0.611, 0.611, 0.611, 0.611, 0.611, 0.611, 0.889, 0.667, +0.611, 0.611, 0.611, 0.611, 0.333, 0.333, 0.333, 0.333, 0.722, 0.667, +0.722, 0.722, 0.722, 0.722, 0.722, 0.675, 0.722, 0.722, 0.722, 0.722, +0.722, 0.556, 0.611, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, +0.667, 0.444, 0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.675, 0.500, 0.500, +0.500, 0.500, 0.500, 0.444, 0.500, 0.444] + +_roman_bi = [ +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, +0.000, 0.000, 0.250, 0.389, 0.555, 0.500, 0.500, 0.833, 0.778, 0.278, +0.333, 0.333, 0.500, 0.570, 0.250, 0.333, 0.250, 0.278, 0.500, 0.500, +0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.333, 0.333, +0.570, 0.570, 0.570, 0.500, 0.832, 0.667, 0.667, 0.667, 0.722, 0.667, +0.667, 0.722, 0.778, 0.389, 0.500, 0.667, 0.611, 0.889, 0.722, 0.722, +0.611, 0.722, 0.667, 0.556, 0.611, 0.722, 0.667, 0.889, 0.667, 0.611, +0.611, 0.333, 0.278, 0.333, 0.570, 0.500, 0.333, 0.500, 0.500, 0.444, +0.500, 0.444, 0.333, 0.500, 0.556, 0.278, 0.278, 0.500, 0.278, 0.778, +0.556, 0.500, 0.500, 0.500, 0.389, 0.389, 0.278, 0.556, 0.444, 0.667, +0.500, 0.444, 0.389, 0.348, 0.220, 0.348, 0.570, 0.350, 0.500, 0.350, +0.333, 0.500, 0.500, 1.000, 0.500, 0.500, 0.333, 1.000, 0.556, 0.333, +0.944, 0.350, 0.611, 0.350, 0.350, 0.333, 0.333, 0.500, 0.500, 0.350, +0.500, 1.000, 0.333, 1.000, 0.389, 0.333, 0.722, 0.350, 0.389, 0.611, +0.250, 0.389, 0.500, 0.500, 0.500, 0.500, 0.220, 0.500, 0.333, 0.747, +0.266, 0.500, 0.606, 0.333, 0.747, 0.333, 0.400, 0.570, 0.300, 0.300, +0.333, 0.576, 0.500, 0.250, 0.333, 0.300, 0.300, 0.500, 0.750, 0.750, +0.750, 0.500, 0.667, 0.667, 0.667, 0.667, 0.667, 0.667, 0.944, 0.667, +0.667, 0.667, 0.667, 0.667, 0.389, 0.389, 0.389, 0.389, 0.722, 0.722, +0.722, 0.722, 0.722, 0.722, 0.722, 0.570, 0.722, 0.722, 0.722, 0.722, +0.722, 0.611, 0.611, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, 0.500, +0.722, 0.444, 0.444, 0.444, 0.444, 0.444, 0.278, 0.278, 0.278, 0.278, +0.500, 0.556, 0.500, 0.500, 0.500, 0.500, 0.500, 0.570, 0.500, 0.556, +0.556, 0.556, 0.556, 0.444, 0.500, 0.444] + +_font_array = [ [_swiss, _swiss_b, _swiss_i, _swiss_bi ], + [_roman, _roman_b, _roman_i, _roman_bi ] ] + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def string_width(font,text): + i = font.get_type_face() + j = font.get_bold() + font.get_italic()*2 + s = font.get_size() + l = _font_array[i][j] + r = 0 + for c in text: + r = r + l[ord(c)] + return (r+1)*s diff --git a/gramps2/src/GedcomInfo.py b/gramps2/src/GedcomInfo.py new file mode 100644 index 000000000..bd220ce8f --- /dev/null +++ b/gramps2/src/GedcomInfo.py @@ -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 +# + +import const +from latin_utf8 import utf8_to_latin +u2l = utf8_to_latin + +ADOPT_NONE = 0 +ADOPT_EVENT = 1 +ADOPT_FTW = 2 +ADOPT_LEGACY = 3 +ADOPT_PEDI = 4 +ADOPT_STD = 5 +CONC_OK = 0 +CONC_BROKEN = 1 +ALT_NAME_NONE = 0 +ALT_NAME_STD = 1 +ALT_NAME_ALIAS = 2 +ALT_NAME_AKA = 3 +ALT_NAME_EVENT_AKA = 4 +ALT_NAME_UALIAS = 5 +CALENDAR_NO = 0 +CALENDAR_YES = 1 +OBJE_NO = 0 +OBJE_YES = 1 +RESIDENCE_ADDR = 0 +RESIDENCE_PLAC = 1 + +#------------------------------------------------------------------------- +# +# XML parser +# +#------------------------------------------------------------------------- +import xml.parsers.expat + +class GedcomDescription: + def __init__(self,name): + self.name = name + self.dest = "" + self.adopt = ADOPT_STD + self.conc = CONC_OK + self.altname = ALT_NAME_STD + self.cal = CALENDAR_YES + self.obje = OBJE_YES + self.resi = RESIDENCE_ADDR + self.gramps2tag_map = {} + self.tag2gramps_map = {} + + def set_dest(self,val): + self.dest = val + + def get_dest(self): + return self.dest + + def set_adopt(self,val): + self.adopt = val + + def get_adopt(self): + return self.adopt + + def set_conc(self,val): + self.conc = val + + def get_conc(self): + return self.conc + + def set_alt_name(self,val): + self.altname = val + + def get_alt_name(self): + return self.altname + + def set_alt_calendar(self,val): + self.cal = val + + def get_alt_calendar(self): + return self.cal + + def set_obje(self,val): + self.obje = val + + def get_obje(self): + return self.obje + + def set_resi(self,val): + self.resi = val + + def get_resi(self): + return self.resi + + def add_tag_value(self,tag,value): + self.gramps2tag_map[value] = tag + self.tag2gramps_map[tag] = value + + def gramps2tag(self,key): + if self.gramps2tag_map.has_key(key): + return self.gramps2tag_map[key] + return "" + + def tag2gramps(self,key): + if self.tag2gramps_map.has_key(key): + return self.tag2gramps_map[key] + return key + +class GedcomInfoDB: + def __init__(self): + self.map = {} + + self.standard = GedcomDescription("GEDCOM 5.5 standard") + self.standard.set_dest("GEDCOM 5.5") + + try: + file = "%s/gedcom.xml" % const.dataDir + f = open(file,"r") + except: + return + + try: + parser = GedInfoParser(self) + parser.parse(f) + f.close() + except: + pass + + def add_description(self,name,obj): + self.map[name] = obj + + def get_description(self,name): + if self.map.has_key(name): + return self.map[name] + return self.standard + + def get_from_source_tag(self,name): + for k in self.map.keys(): + val = self.map[k] + if val.get_dest() == name: + return val + return self.standard + + def get_name_list(self): + mylist = self.map.keys() + mylist.sort() + return ["GEDCOM 5.5 standard"] + mylist + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +class GedInfoParser: + def __init__(self,parent): + self.parent = parent + self.current = None + + def parse(self,file): + p = xml.parsers.expat.ParserCreate() + p.StartElementHandler = self.startElement + p.ParseFile(file) + + def startElement(self,tag,attrs): + tag = u2l(tag) + if tag == "target": + name = u2l(attrs['name']) + self.current = GedcomDescription(name) + self.parent.add_description(name,self.current) + elif tag == "dest": + self.current.set_dest(u2l(attrs['val'])) + elif tag == "adopt": + val = u2l(attrs['val']) + if val == 'none': + self.current.set_adopt(ADOPT_NONE) + elif val == 'event': + self.current.set_adopt(ADOPT_EVENT) + elif val == 'ftw': + self.current.set_adopt(ADOPT_FTW) + elif val == 'legacy': + self.current.set_adopt(ADOPT_LEGACY) + elif val == 'pedigree': + self.current.set_adopt(ADOPT_PEDI) + elif tag == "conc": + if u2l(attrs['val']) == 'broken': + self.current.set_conc(CONC_BROKEN) + elif tag == "alternate_names": + val = u2l(attrs['val']) + if val == 'none': + self.current.set_alt_name(ALT_NAME_NONE) + elif val == 'event_aka': + self.current.set_alt_name(ALT_NAME_EVENT_AKA) + elif val == 'alias': + self.current.set_alt_name(ALT_NAME_ALIAS) + elif val == 'aka': + self.current.set_alt_name(ALT_NAME_AKA) + elif val == '_alias': + self.current.set_alt_name(ALT_NAME_UALIAS) + elif tag == "calendars": + if u2l(attrs['val']) == 'no': + self.current.set_alt_calendar(CALENDAR_NO) + elif tag == "event": + self.current.add_tag_value(u2l(attrs['tag']),u2l(attrs['value'])) + elif tag == "object_support": + if u2l(attrs['val']) == 'no': + self.current.set_obje(OBJE_NO) + elif tag == "residence": + if u2l(attrs['val']) == 'place': + self.current.set_resi(RESIDENCE_PLAC) diff --git a/gramps2/src/GenericFilter.py b/gramps2/src/GenericFilter.py new file mode 100644 index 000000000..449019cc1 --- /dev/null +++ b/gramps2/src/GenericFilter.py @@ -0,0 +1,894 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002 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 +# + +"""Generic Filtering Routines""" + +__author__ = "Don Allingham" + +#------------------------------------------------------------------------- +# +# Try to abstract SAX1 from SAX2 +# +#------------------------------------------------------------------------- +try: + from xml.sax import make_parser,handler,SAXParseException +except: + from _xmlplus.sax import make_parser,handler,SAXParseException + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +import os +from string import find,join,strip,replace +import gtk + +from latin_utf8 import utf8_to_latin +u2l = utf8_to_latin + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +import const +from RelLib import * +import Date +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# date_cmp +# +#------------------------------------------------------------------------- +def date_cmp(rule,value): + sd = rule.get_start_date() + s = sd.mode + if s == Date.SingleDate.before: + return Date.compare_dates(rule,value) == 1 + elif s == Date.SingleDate.after: + return Date.compare_dates(rule,value) == -1 + elif sd.month == Date.UNDEF and sd.year != Date.UNDEF: + return sd.year == value.get_start_date().year + else: + return Date.compare_dates(rule,value) == 0 + +#------------------------------------------------------------------------- +# +# Rule +# +#------------------------------------------------------------------------- +class Rule: + """Base rule class""" + + labels = [] + + def __init__(self,list): + assert(type(list) == type([]),"Argument is not a list") + self.list = list + + def values(self): + return self.list + + def trans_name(self): + return _(self.name()) + + def name(self): + return 'None' + + def check(self): + return len(self.list) == len(self.labels) + + def apply(self,p): + return 1 + + def display_values(self): + v = [] + for i in range(0,len(self.list)): + if self.list[i]: + v.append('%s="%s"' % (_(self.labels[i]),self.list[i])) + return join(v,'; ') + +#------------------------------------------------------------------------- +# +# Everyone +# +#------------------------------------------------------------------------- +class Everyone(Rule): + """Matches Everyone""" + + labels = [] + + def name(self): + return 'Everyone' + + def apply(self,p): + return 1 + +#------------------------------------------------------------------------- +# +# HasIdOf +# +#------------------------------------------------------------------------- +class HasIdOf(Rule): + """Rule that checks for a person with a specific GID""" + + labels = [ _('ID') ] + + def name(self): + return 'Has the Id' + + def apply(self,p): + return p.getId() == self.list[0] + +#------------------------------------------------------------------------- +# +# IsFemale +# +#------------------------------------------------------------------------- +class IsFemale(Rule): + """Rule that checks for a person that is a female""" + + labels = [] + + def name(self): + return 'Is a female' + + def apply(self,p): + return p.getGender() == Person.female + +#------------------------------------------------------------------------- +# +# IsDescendantOf +# +#------------------------------------------------------------------------- +class IsDescendantOf(Rule): + """Rule that checks for a person that is a descendant + of a specified person""" + + labels = [ _('ID') ] + + def name(self): + return 'Is a descendant of' + + def apply(self,p): + return self.search(p) + + def search(self,p): + if p.getId() == self.list[0]: + return 1 + for (f,r1,r2) in p.getParentList(): + for p1 in [f.getMother(),f.getFather()]: + if p1: + if self.search(p1): + return 1 + return 0 + +#------------------------------------------------------------------------- +# +# IsDescendantFamilyOf +# +#------------------------------------------------------------------------- +class IsDescendantFamilyOf(Rule): + """Rule that checks for a person that is a descendant or the spouse + of a descendant of a specified person""" + + labels = [ _('ID') ] + + def name(self): + return "Is a descendant family member of" + + def apply(self,p): + return self.search(p,1) + + def search(self,p,val): + if p.getId() == self.list[0]: + return 1 + for (f,r1,r2) in p.getParentList(): + for p1 in [f.getMother(),f.getFather()]: + if p1: + if self.search(p1,0): + return 1 + if val: + for fm in p.getFamilyList(): + if p == fm.getFather(): + s = fm.getMother() + else: + s = fm.getFather() + if s: + if self.search(s,0): + return 1 + + return 0 + +#------------------------------------------------------------------------- +# +# IsAncestorOf +# +#------------------------------------------------------------------------- +class IsAncestorOf(Rule): + """Rule that checks for a person that is an ancestor of a specified person""" + + labels = [ _('ID') ] + + def name(self): + return 'Is an ancestor of' + + def apply(self,p): + return self.search(p) + + def search(self,p): + if p.getId() == self.list[0]: + return 1 + + for f in p.getFamilyList(): + for p1 in f.getChildList(): + if p1: + if self.search(p1): + return 1 + return 0 + +#------------------------------------------------------------------------- +# +# IsMale +# +#------------------------------------------------------------------------- +class IsMale(Rule): + """Rule that checks for a person that is a male""" + + labels = [] + + def name(self): + return 'Is a male' + + def apply(self,p): + return p.getGender() == Person.male + +#------------------------------------------------------------------------- +# +# HasEvent +# +#------------------------------------------------------------------------- +class HasEvent(Rule): + """Rule that checks for a person with a particular value""" + + labels = [ _('Personal Event'), _('Date'), _('Place'), _('Description') ] + + def __init__(self,list): + Rule.__init__(self,list) + if self.list[0]: + self.date = Date.Date() + self.date.set(self.list[0]) + else: + self.date = None + + def name(self): + return 'Has the personal event' + + def apply(self,p): + for event in p.getEventList(): + val = 1 + if self.list[0] and event.getName() != self.list[0]: + val = 0 + if self.list[3] and find(event.getDescription(),self.list[3])==-1: + val = 0 + if self.date: + if date_cmp(self.date,event.getDateObj()): + val = 0 + if self.list[2] and find(p.getPlaceName(),self.list[2]) == -1: + val = 0 + if val == 1: + return 1 + return 0 + +#------------------------------------------------------------------------- +# +# HasFamilyEvent +# +#------------------------------------------------------------------------- +class HasFamilyEvent(Rule): + """Rule that checks for a person who has a relationship event + with a particular value""" + + labels = [ _('Family Event'), _('Date'), _('Place'), _('Description') ] + + def __init__(self,list): + Rule.__init__(self,list) + if self.list[0]: + self.date = Date.Date() + self.date.set(self.list[0]) + else: + self.date = None + + def name(self): + return 'Has the family event' + + def apply(self,p): + for f in p.getFamilyList(): + for event in f.getEventList(): + val = 1 + if self.list[0] and event.getName() != self.list[0]: + val = 0 + v = self.list[3] + if v and find(event.getDescription(),v)==-1: + val = 0 + if self.date: + if date_cmp(self.date,event.getDateObj()): + val = 0 + if self.list[2] and find(p.getPlaceName(),self.list[2]) == -1: + val = 0 + if val == 1: + return 1 + return 0 + +#------------------------------------------------------------------------- +# +# HasRelationship +# +#------------------------------------------------------------------------- +class HasRelationship(Rule): + """Rule that checks for a person who has a particular relationship""" + + labels = [ _('Number of Relationships'), + _('Relationship Type'), + _('Number of Children') ] + + def name(self): + return 'Has the relationships' + + def apply(self,p): + rel_type = 0 + cnt = 0 + num_rel = len(p.getFamilyList()) + + # count children and look for a relationship type match + for f in p.getFamilyList(): + cnt = cnt + len(f.getChildList()) + if self.list[1] and f.getRelationship() == self.list[1]: + rel_type = 1 + + # if number of relations specified + if self.list[0]: + try: + v = int(self.list[0]) + except: + return 0 + if v != num_rel: + return 0 + + # number of childred + if self.list[2]: + try: + v = int(self.list[2]) + except: + return 0 + if v != cnt: + return 0 + + # relation + if self.list[1]: + return rel_type == 1 + else: + return 1 + +#------------------------------------------------------------------------- +# +# HasBirth +# +#------------------------------------------------------------------------- +class HasBirth(Rule): + """Rule that checks for a person with a birth of a particular value""" + + labels = [ _('Date'), _('Place'), _('Description') ] + + def __init__(self,list): + Rule.__init__(self,list) + if self.list[0]: + self.date = Date.Date() + self.date.set(self.list[0]) + else: + self.date = None + + def name(self): + return 'Has the birth' + + def apply(self,p): + event = p.getBirth() + if len(self.list) > 2 and find(event.getDescription(),self.list[2])==-1: + return 0 + if self.date: + if date_cmp(self.date,event.getDateObj()) == 0: + return 0 + if len(self.list) > 1 and find(event.getPlaceName(),self.list[1]) == -1: + return 0 + return 1 + +#------------------------------------------------------------------------- +# +# HasDeath +# +#------------------------------------------------------------------------- +class HasDeath(Rule): + """Rule that checks for a person with a death of a particular value""" + + labels = [ _('Date'), _('Place'), _('Description') ] + + def __init__(self,list): + Rule.__init__(self,list) + if self.list[0]: + self.date = Date.Date() + self.date.set(self.list[0]) + else: + self.date = None + + def name(self): + return 'Has the death' + + def apply(self,p): + event = p.getDeath() + if self.list[2] and find(event.getDescription(),self.list[2])==-1: + return 0 + if self.date: + if date_cmp(self.date,event.getDateObj()) == 0: + return 0 + if self.list[1] and find(p.getPlaceName(),self.list[1]) == -1: + return 0 + return 1 + +#------------------------------------------------------------------------- +# +# HasAttribute +# +#------------------------------------------------------------------------- +class HasAttribute(Rule): + """Rule that checks for a person with a particular personal attribute""" + + labels = [ _('Personal Attribute'), _('Value') ] + + def name(self): + return 'Has the personal attribute' + + def apply(self,p): + for event in p.getAttributes(): + if self.list[0] and event.getType() != self.list[0]: + return 0 + if self.list[1] and find(event.getValue(),self.list[1])==-1: + return 0 + return 1 + +#------------------------------------------------------------------------- +# +# HasFamilyAttribute +# +#------------------------------------------------------------------------- +class HasFamilyAttribute(Rule): + """Rule that checks for a person with a particular family attribute""" + + labels = [ _('Family Attribute'), _('Value') ] + + def name(self): + return 'Has the family attribute' + + def apply(self,p): + for f in p.getFamilyList(): + for event in f.getAttributes(): + val = 1 + if self.list[0] and event.getType() != self.list[0]: + val = 0 + if self.list[1] and find(event.getValue(),self.list[1])==-1: + val = 0 + if val == 1: + return 1 + return 0 + +#------------------------------------------------------------------------- +# +# HasNameOf +# +#------------------------------------------------------------------------- +class HasNameOf(Rule): + """Rule that checks for full or partial name matches""" + + labels = [_('Given Name'),_('Surname'),_('Suffix'),_('Title')] + + def name(self): + return 'Has a name' + + def apply(self,p): + self.f = self.list[0] + self.l = self.list[1] + self.s = self.list[2] + self.t = self.list[3] + for name in [p.getPrimaryName()] + p.getAlternateNames(): + val = 1 + if self.f and find(name.getFirstName(),self.f) == -1: + val = 0 + if self.l and find(name.getSurname(),self.l) == -1: + val = 0 + if self.s and find(name.getSuffix(),self.s) == -1: + val = 0 + if self.t and find(name.getTitle(),self.t) == -1: + val = 0 + if val == 1: + return 1 + return 0 + + +class MatchesFilter(Rule): + """Rule that checks against another filter""" + + labels = [_('Filter Name')] + + def name(self): + return 'Matches the filter named' + + def apply(self, p): + for filter in SystemFilters.get_filters(): + if filter.get_name() == self.list[0]: + return filter.check(p) + for filter in CustomFilters.get_filters(): + if filter.get_name() == self.list[0]: + return filter.check(p) + return 0 + +#------------------------------------------------------------------------- +# +# GenericFilter +# +#------------------------------------------------------------------------- +class GenericFilter: + """Filter class that consists of several rules""" + + def __init__(self,source=None): + if source: + self.flist = source.flist[:] + self.name = source.name + self.comment = source.comment + self.logical_op = source.logical_op + self.invert = source.invert + else: + self.flist = [] + self.name = '' + self.comment = '' + self.logical_op = 'and' + self.invert = 0 + + def set_logical_op(self,val): + if val in const.logical_functions: + self.logical_op = val + else: + self.logical_op = 'and' + + def get_logical_op(self): + return self.logical_op + + def set_invert(self, val): + self.invert = not not val + + def get_invert(self): + return self.invert + + def get_name(self): + return self.name + + def set_name(self,name): + self.name = name + + def set_comment(self,comment): + self.comment = comment + + def get_comment(self): + return self.comment + + def add_rule(self,rule): + self.flist.append(rule) + + def set_rules(self,rules): + self.flist = rules + + def get_rules(self): + return self.flist + + def check_or(self,p): + test = 0 + for rule in self.flist: + test = test or rule.apply(p) + if test: + break + if self.invert: + return not test + else: + return test + + def check_xor(self,p): + test = 0 + for rule in self.flist: + temp = rule.apply(p) + test = ((not test) and temp) or (test and (not temp)) + if self.invert: + return not test + else: + return test + + def check_one(self,p): + count = 0 + for rule in self.flist: + if rule.apply(p): + count = count + 1 + if count > 1: + break + if self.invert: + return count != 1 + else: + return count == 1 + + def check_and(self,p): + test = 1 + for rule in self.flist: + test = test and rule.apply(p) + if not test: + break + if self.invert: + return not test + else: + return test + + def check(self,p): + try: + m = getattr(self, 'check_' + self.logical_op) + except AttributeError: + m = self.check_and + + return m(p) + + def apply(self,list): + try: + m = getattr(self, 'check_' + self.logical_op) + except AttributeError: + m = self.check_and + + return filter(m, list) + +#------------------------------------------------------------------------- +# +# Name to class mappings +# +#------------------------------------------------------------------------- +tasks = { + _("Everyone") : Everyone, + _("Has the Id") : HasIdOf, + _("Has a name") : HasNameOf, + _("Has the relationships") : HasRelationship, + _("Has the death") : HasDeath, + _("Has the birth") : HasBirth, + _("Is a descendant of") : IsDescendantOf, + _("Is a descendant family member of"): IsDescendantFamilyOf, + _("Is an ancestor of") : IsAncestorOf, + _("Is a female") : IsFemale, + _("Is a male") : IsMale, + _("Has the personal event") : HasEvent, + _("Has the family event") : HasFamilyEvent, + _("Has the personal attribute") : HasAttribute, + _("Has the family attribute") : HasFamilyAttribute, + _("Matches the filter named") : MatchesFilter, + } + +#------------------------------------------------------------------------- +# +# GenericFilterList +# +#------------------------------------------------------------------------- +class GenericFilterList: + """Container class for the generic filters. Stores, saves, and + loads the filters.""" + + def __init__(self,file): + self.filter_list = [] + self.file = os.path.expanduser(file) + + def get_filters(self): + return self.filter_list + + def add(self,filter): + self.filter_list.append(filter) + + def load(self): + try: + parser = make_parser() + parser.setContentHandler(FilterParser(self)) + parser.parse(self.file) + except (IOError,OSError,SAXParseException): + pass + + def fix(self,line): + l = strip(line) + l = replace(l,'&','&') + l = replace(l,'>','>') + l = replace(l,'<','<') + return replace(l,'"','"') + + def save(self): + try: + f = open(self.file,'w') + except: + return + + f.write("\n") + f.write('\n') + for i in self.filter_list: + f.write(' \n') + for rule in i.get_rules(): + f.write(' \n' % self.fix(rule.name())) + for v in rule.values(): + f.write(' \n' % self.fix(v)) + f.write(' \n') + f.write(' \n') + f.write('\n') + f.close() + +#------------------------------------------------------------------------- +# +# FilterParser +# +#------------------------------------------------------------------------- +class FilterParser(handler.ContentHandler): + """Parses the XML file and builds the list of filters""" + + def __init__(self,gfilter_list): + handler.ContentHandler.__init__(self) + self.gfilter_list = gfilter_list + self.f = None + self.r = None + self.a = [] + self.cname = None + + def setDocumentLocator(self,locator): + self.locator = locator + + def startElement(self,tag,attrs): + if tag == "filter": + self.f = GenericFilter() + self.f.set_name(u2l(attrs['name'])) + if attrs.has_key('function'): + try: + if int(u2l(attrs['function'])): + op = 'or' + else: + op = 'and' + except ValueError: + op = u2l(attrs['function']) + self.f.set_logical_op(op) + if attrs.has_key('comment'): + self.f.set_comment(u2l(attrs['comment'])) + if attrs.has_key('invert'): + try: + self.f.set_invert(int(u2l(attrs['invert']))) + except ValueError: + pass + self.gfilter_list.add(self.f) + elif tag == "rule": + c = attrs['class'] + name = _(u2l(c)) + self.a = [] + self.cname = tasks[name] + elif tag == "arg": + c = attrs['value'] + self.a.append(u2l(c)) + + def endElement(self,tag): + if tag == "rule": + rule = self.cname(self.a) + self.f.add_rule(rule) + + def characters(self, data): + pass + + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +SystemFilters = None +CustomFilters = None + +def reload_system_filters(): + global SystemFilters + SystemFilters = GenericFilterList(const.system_filters) + SystemFilters.load() + +def reload_custom_filters(): + global CustomFilters + CustomFilters = GenericFilterList(const.custom_filters) + CustomFilters.load() + +if not SystemFilters: + reload_system_filters() + +if not CustomFilters: + reload_custom_filters() + +def build_filter_menu(local_filters = []): + menu = gtk.GtkMenu() + + menuitem = gtk.GtkMenuItem(_("Local Filters")) + menu.append(menuitem) + menuitem.show() + menuitem.set_sensitive(0) + + menuitem = gtk.GtkMenuItem() + menuitem.show() + menu.append(menuitem) + + for filter in local_filters: + menuitem = gtk.GtkMenuItem(filter.get_name()) + menuitem.show() + menu.append(menuitem) + menuitem.set_data("filter", filter) + + menuitem = gtk.GtkMenuItem(_("System Filters")) + menuitem.show() + menu.append(menuitem) + menuitem.set_sensitive(0) + + menuitem = gtk.GtkMenuItem() + menuitem.show() + menu.append(menuitem) + + for filter in SystemFilters.get_filters(): + menuitem = gtk.GtkMenuItem(_(filter.get_name())) + menuitem.show() + menu.append(menuitem) + menuitem.set_data("filter", filter) + + menuitem = gtk.GtkMenuItem(_("Custom Filters")) + menu.append(menuitem) + menuitem.show() + menuitem.set_sensitive(0) + + menuitem = gtk.GtkMenuItem() + menuitem.show() + menu.append(menuitem) + + for filter in CustomFilters.get_filters(): + menuitem = gtk.GtkMenuItem(_(filter.get_name())) + menuitem.show() + menu.append(menuitem) + menuitem.set_data("filter", filter) + + if len(local_filters): + menu.set_active(2) + elif len(SystemFilters.get_filters()): + menu.set_active(4 + len(local_filters)) + elif len(CustomFilters.get_filters()): + menu.set_active(6 + len(local_filters) + len(SystemFilters.get_filters())) + else: + menu.set_active(0) + + return menu diff --git a/gramps2/src/GrampsCfg.py b/gramps2/src/GrampsCfg.py new file mode 100644 index 000000000..07bfbf585 --- /dev/null +++ b/gramps2/src/GrampsCfg.py @@ -0,0 +1,1127 @@ +# +# 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 string +import os + +import PaperMenu +import Plugins + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk +import gconf +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +from RelLib import * +from Date import * + +import const +import Utils + +from intl import gettext as _ + +client = gconf.client_get_default() +client.add_dir("/apps/gramps",gconf.CLIENT_PRELOAD_NONE) + +_surname_styles = [ + _("Father's surname"), + _("None"), + _("Combination of mother's and father's surname"), + _("Icelandic style"), + ] + +_date_format_list = [ + _("Month Day, Year"), + _("MON Day, Year"), + _("Day MON Year"), + _("MM/DD/YYYY"), + _("MM-DD-YYYY"), + _("DD/MM/YYYY"), + _("DD-MM-YYYY"), + _("MM.DD.YYYY"), + _("DD.MM.YYYY"), + _("DD. Month Year"), + _("YYYY/MM/DD"), + _("YYYY-MM-DD"), + _("YYYY.MM.DD"), + ] + +_date_entry_list = [ + _("MM/DD/YYYY, MM.DD.YYYY, or MM-DD-YYYY"), + _("DD/MM/YYYY, DD.MM.YYYY, or DD-MM-YYYY"), + _("YYYY/MM/DD, YYYY.MM.DD, or YYYY-MM-DD"), + ] + +_name_format_list = [ + (_("Firstname Surname"), Utils.normal_name), + (_("Surname, Firstname"), Utils.phonebook_name), + ] + +panellist = [ + (_("Database"), + [( _("General"), 1), + ( _("Dates and Calendars"), 6), + ( _("Media Objects"), 9), + ( _("GRAMPS internal IDs"), 10), + ( _("Revision Control"),2)]), + (_("Display"), + [( _("General"), 5), + ( _("Tool and Status Bars"), 4)]), + (_("Usage"), + [( _("Find"), 3), + ( _("Report Preferences"), 8), + ( _("Researcher Information"), 7), + ( _("Data Guessing"), 11)]), + ] + + +#------------------------------------------------------------------------- +# +# Visible globals +# +#------------------------------------------------------------------------- + +iprefix = "I" +oprefix = "O" +sprefix = "S" +pprefix = "P" +fprefix = "F" +autoload = 0 +autosave_int = 0 +usetabs = 0 +uselds = 0 +autocomp = 1 +usevc = 0 +vc_comment = 0 +uncompress = 0 +show_detail = 0 +hide_altnames = 0 +lastfile = None +nameof = Utils.normal_name +display_attr = 0 +attr_name = "" +status_bar = 0 +toolbar = 2 +calendar = 0 +paper_preference = "" +output_preference = "" +goutput_preference = "" +lastnamegen = None +report_dir = "./" +web_dir = "./" +db_dir = "./" +id_visible = 0 +id_edit = 0 +index_visible = 0 +mediaref = 1 +globalprop = 1 +localprop = 1 + +#------------------------------------------------------------------------- +# +# Globals +# +#------------------------------------------------------------------------- +_name_format = 0 +_callback = None + +#------------------------------------------------------------------------- +# +# Constants +# +#------------------------------------------------------------------------- +ODDFGCOLOR = "oddfg" +ODDBGCOLOR = "oddbg" +EVENFGCOLOR = "evenfg" +EVENBGCOLOR = "evenbg" +ANCESTORFGCOLOR = "ancestorfg" +INDEX = "i" +OBJECT = "o" +DATA = "d" + +#------------------------------------------------------------------------- +# +# 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 autosave_int + global usetabs + global uselds + global autocomp + global calendar + global usevc + global iprefix, fprefix, pprefix, oprefix, sprefix + global vc_comment + global uncompress + global id_visible + global id_edit + global index_visible + global show_detail + global hide_altnames + global lastfile + global nameof + global display_attr + global attr_name + global _name_format + global _callback + global paper_preference + global output_preference + global goutput_preference + global lastnamegen + global report_dir + global web_dir + global db_dir + global status_bar + global toolbar + global mediaref + global globalprop + global localprop + + _callback = call + lastfile = get_string("/gramps/data/LastFile") + usetabs = get_bool("/gramps/config/UseTabs") + uselds = get_bool("/gramps/config/UseLDS") + ac = get_bool("/gramps/config/DisableAutoComplete",0) + mediaref = get_bool("/gramps/config/MakeReference",1) + globalprop = get_bool("/gramps/config/DisplayGlobal",1) + localprop = get_bool("/gramps/config/DisplayLocal",1) + calendar = get_bool("/gramps/config/ShowCalendar") + usevc = get_bool("/gramps/config/UseVersionControl") + vc_comment = get_bool("/gramps/config/UseComment") + uncompress = get_bool("/gramps/config/DontCompressXML") + id_visible = get_bool("/gramps/config/IdVisible") + id_edit = get_bool("/gramps/config/IdEdit") + index_visible = get_bool("/gramps/config/IndexVisible") + show_detail = get_bool("/gramps/config/ShowDetail") + status_bar = get_int("/gramps/config/StatusBar") + toolbar = get_int("/gramps/config/ToolBar",2) + display_attr = get_bool("/gramps/config/DisplayAttr") + attr_name = get_string("/gramps/config/DisplayAttrName") + + hide_altnames = get_bool("/gramps/config/DisplayAltNames") + autoload = get_bool("/gramps/config/autoLoad",0) + autosave_int = get_int("/gramps/config/autoSaveInterval") + dateFormat = get_int("/gramps/config/dateFormat") + dateEntry = get_int("/gramps/config/dateEntry") + paper_preference = get_string("/gramps/config/paperPreference") + output_preference = get_string("/gramps/config/outputPreference") + goutput_preference = get_string("/gramps/config/goutputPreference") + lastnamegen = get_int("/gramps/config/surnameGuessing") + _name_format = get_int("/gramps/config/nameFormat") + + iprefix = get_string("/gramps/config/iprefix") + fprefix = get_string("/gramps/config/fprefix") + sprefix = get_string("/gramps/config/sprefix") + oprefix = get_string("/gramps/config/oprefix") + pprefix = get_string("/gramps/config/pprefix") + + report_dir = get_string("/gramps/config/ReportDirectory") + web_dir = get_string("/gramps/config/WebsiteDirectory") + db_dir = get_string("/gramps/config/DbDirectory") + + if report_dir == None: + report_dir = "./" + else: + report_dir = os.path.normpath(report_dir) + os.sep + + if web_dir == None: + web_dir = "./" + else: + web_dir = os.path.normpath(web_dir) + os.sep + + if db_dir == None: + db_dir = "./" + else: + db_dir = os.path.normpath(db_dir) + os.sep + + en = get_bool("/gramps/color/enableColors") + if en == None: + en = 0 + + if paper_preference == None: + paper_preference = "Letter" + + if output_preference == None: + output_preference = "" + + if goutput_preference == None: + goutput_preference = "" + + if iprefix == None: + iprefix = "I" + if fprefix == None: + fprefix = "F" + if sprefix == None: + sprefix = "S" + if pprefix == None: + pprefix = "P" + if oprefix == None: + oprefix = "O" + + if display_attr == None: + display_attr = 0 + + if attr_name == None: + attr_name = "" + + autocomp = not ac + + set_format_code(dateFormat) + Date.entryCode = dateEntry + + if _name_format == 0: + nameof = Utils.normal_name + else: + nameof = Utils.phonebook_name + + make_path(os.path.expanduser("~/.gramps")) + make_path(os.path.expanduser("~/.gramps/filters")) + make_path(os.path.expanduser("~/.gramps/plugins")) + make_path(os.path.expanduser("~/.gramps/templates")) + +def get_string(value,defval=""): + v = client.get_string(value) + if v == None: + return defval + else: + return v + +def get_bool(key,defval=0): + v = client.get_bool(key) + if v: + return v + else: + return defval + +def get_int(key,defval=0): + v = client.get_int(key) + if v: + return v + else: + return defval + +def set_int(key,value): + client.set_int(key,value) + +def set_bool(key,value): + client.set_bool(key,value) + +def set_string(key,value): + client.set_string(key,value) + +def get_string(key): + val = client.get_string(key) + if val: + return val + else: + return "" + +def sync(): + client.suggest_sync() + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def save_last_file(file): + set_string("/gramps/data/LastFile",file) + sync() + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def get_researcher(): + n = get_string("/gramps/researcher/name") + a = get_string("/gramps/researcher/addr") + c = get_string("/gramps/researcher/city") + s = get_string("/gramps/researcher/state") + ct = get_string("/gramps/researcher/country") + p = get_string("/gramps/researcher/postal") + ph = get_string("/gramps/researcher/phone") + e = get_string("/gramps/researcher/email") + + owner = Researcher() + owner.set(n,a,c,s,ct,p,ph,e) + return owner + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def save_config_color(name,color): + set_int("/gramps/color/" + name + ".r",color[0]) + set_int("/gramps/color/" + name + ".g",color[1]) + set_int("/gramps/color/" + name + ".b",color[2]) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- + +def get_config_text(panel,key): + val = get_string("/gramps/%s/%s" % (panel,key)) + if val: + return val + else: + return "" + +def get_config_bool(panel,key): + return get_bool("/gramps/%s/%s" % (panel,key)) + +def get_config_int(panel,key): + return get_int("/gramps/%s/%s" % (panel,key)) + +ext_items = [] + +class ConfigWidget: + def __init__(self,panel,key,label,default): + self.p = panel + self.k = key + self.l = label + self.w = None + self.d = default + self.tag = "/gramps/%s/%s" % (panel,key) + + def set(self): + pass + +class ConfigEntry(ConfigWidget): + + def get_widgets(self): + l = gtk.Label(self.l) + l.show() + self.w = gtk.Entry() + self.w.show() + + val = get_string(self.tag) + if val == None: + self.w.set_text(self.d) + else: + self.w.set_text(val) + return [l,self.w] + + def set(self): + val = self.w.get_text() + set_string(self.tag,val) + +class ConfigInt(ConfigWidget): + + def set_range(self,lower,upper): + self.lower = lower + self.upper = upper + + def get_widgets(self): + l = gtk.Label(self.l) + l.show() + self.w = gtk.SpinButton(digits=0) + self.w.show() + + val = get_string(self.tag) + if val == None: + val = int(self.d) + else: + val = int(val) + + adj = gtk.Adjustment(val,self.lower,self.upper,1,1,1) + + self.w.set_adjustment(adj) + return [l,self.w] + + def set(self): + val = self.w.get_value_as_int() + set_int(self.tag,val) + +class ConfigCheckbox(ConfigWidget): + + def get_widgets(self): + self.w = gtk.CheckButton(self.l) + self.w.show() + val = get_bool(self.tag) + if val == None: + self.w.set_active(self.d) + else: + self.w.set_active(val) + return [self.w] + + def set(self): + val = self.w.get_active() + set_bool(self.tag,val) + + +class ConfigFile(ConfigWidget): + + def get_widgets(self): + self.w = gnome.ui.GnomeFileEntry(self.tag) + lbl = gtk.Label(self.l) + self.w.show() + lbl.show() + val = get_string(self.tag) + self.w.set_title("%s -- GRAMPS" % (self.l)) + if val == None: + self.w.gtk_entry().set_text(self.d) + else: + self.w.gtk_entry().set_text(val) + return [lbl,self.w] + + def set(self): + val = self.w.get_full_path(0) + set_string(self.tag,val) + + +def add_text(category,panel,frame,config_tag,label,default): + ext_items.append((category,panel,frame,ConfigEntry(panel,config_tag,label,default))) + +def add_file_entry(category,panel,frame,config_tag,label,default): + ext_items.append((category,panel,frame,ConfigFile(panel,config_tag,label,default))) + +def add_int(category,panel,frame,config_tag,label,default,range=(0,100)): + cfgint = ConfigInt(panel,config_tag,label,default) + cfgint.set_range(range[0],range[1]) + ext_items.append((category,panel,frame,cfgint)) + +def add_checkbox(category,panel,frame,config_tag,label,default): + ext_items.append((category,panel,frame,ConfigCheckbox(panel,config_tag,label,default))) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +class GrampsPreferences: + def __init__(self,db): + self.db = db + self.top = gtk.glade.XML(const.prefsFile,"preferences") + self.top.signal_autoconnect({ + "on_close_clicked" : self.on_close_clicked, + "on_ok_clicked" : self.on_ok_clicked, + "on_apply_clicked" : self.on_propertybox_apply, + "on_help_clicked" : self.on_propertybox_help, + "on_color_toggled" : self.on_color_toggled, + "on_color_set" : self.on_color_set, + "on_object_toggled" : self.on_object_toggled, + "on_tree_select_row" : self.select + }) + + self.window = self.top.get_widget("preferences") + self.apply = self.top.get_widget("apply") + self.tree = self.top.get_widget("tree") + self.store = gtk.TreeStore(gobject.TYPE_STRING) + self.selection = self.tree.get_selection() + self.selection.connect('changed',self.select) + col = gtk.TreeViewColumn('',gtk.CellRendererText(),text=0) + self.tree.append_column(col) + self.tree.set_model(self.store) + self.panel = self.top.get_widget("panel") + self.ofmt = self.top.get_widget("output_format") + self.gfmt = self.top.get_widget("graphical_format") + + self.imap = {} + self.build_tree() + self.build() + self.build_ext() + self.apply.set_sensitive(0) + + def build_tree(self): + prev = None + ilist = [] + for (name,list) in panellist: + node = self.store.insert_after(None, prev) + self.store.set(node,0,name) + next = None + for (subname,tab) in list: + next = self.store.insert_after(node,next) + ilist.append((next,tab)) + self.store.set(next,0,subname) + for next,tab in ilist: + path = self.store.get_path(next) + self.imap[path] = tab + + def build(self): + auto = self.top.get_widget("autoload") + asave_int = self.top.get_widget("autosave_interval") + vis = self.top.get_widget("gid_visible") + idedit = self.top.get_widget("gid_edit") + index_vis = self.top.get_widget("show_child_id") + tabs = self.top.get_widget("usetabs") + lds = self.top.get_widget("uselds") + ac = self.top.get_widget("autocomp") + mr = self.top.get_widget("mediaref") + mc = self.top.get_widget("mediacopy") + dg = self.top.get_widget("globalprop") + dl = self.top.get_widget("localprop") + cal = self.top.get_widget("calendar") + vc = self.top.get_widget("use_vc") + vcom = self.top.get_widget("vc_comment") + compress = self.top.get_widget("uncompress") + detail = self.top.get_widget("showdetail") + display_attr_obj = self.top.get_widget("attr_display") + display_altnames = self.top.get_widget("display_altnames") + + auto.set_active(autoload) + asave_int.set_value(int(autosave_int)) + detail.set_active(show_detail) + tabs.set_active(usetabs) + lds.set_active(uselds) + ac.set_active(autocomp) + if mediaref: + mr.set_active(1) + else: + mc.set_active(1) + dg.set_active(globalprop) + dl.set_active(localprop) + cal.set_active(calendar) + vc.set_active(usevc) + vcom.set_active(vc_comment) + compress.set_active(uncompress) + vis.set_active(id_visible) + idedit.set_active(id_edit) + index_vis.set_active(index_visible) + + self.top.get_widget("iprefix").set_text(iprefix) + self.top.get_widget("oprefix").set_text(oprefix) + self.top.get_widget("fprefix").set_text(fprefix) + self.top.get_widget("sprefix").set_text(sprefix) + self.top.get_widget("pprefix").set_text(pprefix) + + if status_bar == 0: + self.top.get_widget("stat1").set_active(1) + elif status_bar == 1: + self.top.get_widget("stat2").set_active(1) + else: + self.top.get_widget("stat3").set_active(1) + + if toolbar == 0: + self.top.get_widget("tool1").set_active(1) + elif toolbar == 1: + self.top.get_widget("tool2").set_active(1) + else: + self.top.get_widget("tool3").set_active(1) + + display_attr_obj.set_active(display_attr) + self.top.get_widget("attr_name").set_text(attr_name) + + display_altnames.set_active(hide_altnames) + + paper_obj = self.top.get_widget("paper_size") + menu = gtk.Menu() + choice = 0 + for index in range(0,len(PaperMenu.paper_sizes)): + name = PaperMenu.paper_sizes[index].get_name() + if name == paper_preference: + choice = index + item = gtk.MenuItem(name) + item.set_data(DATA,name) + item.connect("activate", self.on_format_toggled) + item.show() + menu.append(item) + menu.set_active(choice) + paper_obj.set_menu(menu) + + lastnamegen_obj = self.top.get_widget("lastnamegen") + menu = gtk.Menu() + choice = 0 + for index in range(0,len(_surname_styles)): + name = _surname_styles[index] + item = gtk.MenuItem(name) + item.set_data(DATA,index) + item.connect("activate", self.on_format_toggled) + item.show() + menu.append(item) + menu.set_active(lastnamegen) + lastnamegen_obj.set_menu(menu) + + self.osubmenu = gtk.Menu() + choice = 0 + index = 0 + for name in [ _("No default format") ] + Plugins.get_text_doc_list(): + if name == output_preference: + choice = index + item = gtk.MenuItem(name) + item.set_data(DATA,name) + item.connect("activate", self.on_format_toggled) + item.show() + self.osubmenu.append(item) + index = index + 1 + self.osubmenu.set_active(choice) + self.ofmt.set_menu(self.osubmenu) + + self.gsubmenu = gtk.Menu() + choice = 0 + index = 0 + for name in [ _("No default format") ] + Plugins.get_draw_doc_list(): + if name == goutput_preference: + choice = index + item = gtk.MenuItem(name) + item.set_data(DATA,name) + item.connect("activate", self.on_format_toggled) + item.show() + self.gsubmenu.append(item) + index = index + 1 + self.gsubmenu.set_active(choice) + self.gfmt.set_menu(self.gsubmenu) + + date_option = self.top.get_widget("date_format") + date_menu = gtk.Menu() + for index in range(0,len(_date_format_list)): + item = gtk.MenuItem(_date_format_list[index]) + item.set_data(INDEX,index) + item.connect("activate", self.on_format_toggled) + item.show() + date_menu.append(item) + date_menu.set_active(get_format_code()) + date_option.set_menu(date_menu) + + date_entry = self.top.get_widget("date_entry_format") + date_menu = gtk.Menu() + for index in range(0,len(_date_entry_list)): + item = gtk.MenuItem(_date_entry_list[index]) + item.set_data(INDEX,index) + item.connect("activate", self.on_format_toggled) + item.show() + date_menu.append(item) + date_menu.set_active(Date.entryCode) + date_entry.set_menu(date_menu) + + name_option = self.top.get_widget("name_format") + name_menu = gtk.Menu() + for index in range(0,len(_name_format_list)): + name_tuple = _name_format_list[index] + item = gtk.MenuItem(name_tuple[0]) + item.set_data(INDEX,index) + item.connect("activate", self.on_format_toggled) + item.show() + name_menu.append(item) + name_menu.set_active(_name_format) + name_option.set_menu(name_menu) + + cname = get_string("/gramps/researcher/name") + caddr = get_string("/gramps/researcher/addr") + ccity = get_string("/gramps/researcher/city") + cstate = get_string("/gramps/researcher/state") + ccountry = get_string("/gramps/researcher/country") + cpostal = get_string("/gramps/researcher/postal") + cphone = get_string("/gramps/researcher/phone") + cemail = get_string("/gramps/researcher/email") + + self.top.get_widget("resname").set_text(cname) + self.top.get_widget("resaddr").set_text(caddr) + self.top.get_widget("rescity").set_text(ccity) + self.top.get_widget("resstate").set_text(cstate) + self.top.get_widget("rescountry").set_text(ccountry) + self.top.get_widget("respostal").set_text(cpostal) + self.top.get_widget("resphone").set_text(cphone) + self.top.get_widget("resemail").set_text(cemail) + + self.top.get_widget("dbdir").gtk_entry().set_text(db_dir) + self.top.get_widget("repdir").gtk_entry().set_text(report_dir) + self.top.get_widget("htmldir").gtk_entry().set_text(web_dir) + + def build_ext(self): + self.c = {} + self.ext_list = [] + for (c,p,f,o) in ext_items: + self.ext_list.append(o) + if self.c.has_key(c): + if self.c[c][p].has_key(f): + self.c[c][p][f].append(o) + else: + self.c[c][p][f] = [o] + else: + self.c[c] = {} + self.c[c][p] = {} + self.c[c][p][f] = [o] + + next_panel=13 + for c in self.c.keys(): + node = self.tree.insert_node(None,None,[c],is_leaf=0,expanded=1) + self.tree.node_set_row_data(node,0) + next = None + for panel in self.c[c].keys(): + next = self.tree.insert_node(node,next,[panel],is_leaf=1,expanded=1) + self.tree.node_set_row_data(next,next_panel) + next_panel = next_panel + 1 + box = gtk.VBox() + box.show() + col = 0 + panel_label = gtk.Label("") + panel_label.show() + self.panel.append_page(box,panel_label) + for frame in self.c[c][panel].keys(): + pairs = self.c[c][panel][frame] + fr = gtk.Frame(frame) + fr.show() + box.pack_start(fr,gtk.FALSE,gtk.FALSE) + table = gtk.Table(len(pairs),2) + table.show() + fr.add(table) + for wobj in pairs: + w = wobj.get_widgets() + if len(w) == 2: + table.attach(w[0],0,1,col,col+1, + gtk.FILL,gtk.SHRINK,5,5) + table.attach(w[1],1,2,col,col+1, + gtk.FILL|gtk.EXPAND,gtk.SHRINK,5,5) + else: + table.attach(w[0],0,2,col,col+1, + gtk.FILL|gtk.EXPAND,gtk.SHRINK,5,5) + col = col + 1 + + def select(self,obj): + store,iter = self.selection.get_selected() + path = store.get_path(iter) + if iter and self.imap.has_key(path): + self.panel.set_current_page(self.imap[path]) + + def on_propertybox_help(self,obj): + import gnome.help + gnome.help.display('gramps-manual','prefs.html') + + def on_close_clicked(self,obj): + Utils.destroy_passed_object(self.window) + + def on_ok_clicked(self,obj): + self.on_propertybox_apply(obj) + Utils.destroy_passed_object(self.window) + + def on_propertybox_apply(self,obj): + global nameof + global usetabs + global uselds + global autocomp + global autosave_int + global mediaref + global globalprop + global localprop + global calendar + global usevc + global iprefix + global fprefix + global pprefix + global sprefix + global oprefix + global vc_comment + global uncompress + global id_visible + global id_edit + global index_visible + global status_bar + global toolbar + global display_attr + global attr_name + global hide_altnames + global paper_preference + global output_preference + global goutput_preference + global show_detail + global report_dir + global web_dir + global db_dir + global lastnamegen + global autoload + + show_detail = self.top.get_widget("showdetail").get_active() + autoload = self.top.get_widget("autoload").get_active() + autosave_int = self.top.get_widget("autosave_interval").get_value_as_int() + display_attr = self.top.get_widget("attr_display").get_active() + attr_name = string.strip(self.top.get_widget("attr_name").get_text()) + usetabs = self.top.get_widget("usetabs").get_active() + uselds = self.top.get_widget("uselds").get_active() + autocomp = self.top.get_widget("autocomp").get_active() + mediaref = self.top.get_widget("mediaref").get_active() + localprop = self.top.get_widget("localprop").get_active() + globalprop = self.top.get_widget("globalprop").get_active() + calendar = self.top.get_widget("calendar").get_active() + usevc = self.top.get_widget("use_vc").get_active() + vc_comment = self.top.get_widget("vc_comment").get_active() + uncompress = self.top.get_widget("uncompress").get_active() + id_visible = self.top.get_widget("gid_visible").get_active() + id_edit = self.top.get_widget("gid_edit").get_active() + index_visible = self.top.get_widget("show_child_id").get_active() + hide_altnames = self.top.get_widget("display_altnames").get_active() + paper_obj = self.top.get_widget("paper_size").get_menu().get_active() + + output_obj = self.osubmenu.get_active() + goutput_obj = self.gsubmenu.get_active() + + if self.top.get_widget("stat1").get_active(): + status_bar = 0 + elif self.top.get_widget("stat2").get_active(): + status_bar = 1 + else: + status_bar = 2 + + if self.top.get_widget("tool1").get_active(): + toolbar = 0 + elif self.top.get_widget("tool2").get_active(): + toolbar = 1 + else: + toolbar = 2 + + iprefix = self.top.get_widget("iprefix").get_text() + if iprefix == "": + iprefix = "I" + sprefix = self.top.get_widget("sprefix").get_text() + if sprefix == "": + sprefix = "S" + oprefix = self.top.get_widget("oprefix").get_text() + if oprefix == "": + oprefix = "O" + fprefix = self.top.get_widget("fprefix").get_text() + if fprefix == "": + fprefix = "F" + pprefix = self.top.get_widget("pprefix").get_text() + if pprefix == "": + pprefix = "P" + + dbdir_temp = self.top.get_widget("dbdir").get_full_path(1) + if dbdir_temp != None and os.path.isdir(dbdir_temp): + db_dir = os.path.normpath(dbdir_temp) + os.sep + + repdir_temp = self.top.get_widget("repdir").get_full_path(1) + if repdir_temp != None and os.path.isdir(repdir_temp): + report_dir = os.path.normpath(repdir_temp) + os.sep + + webdir_temp = self.top.get_widget("htmldir").get_full_path(1) + if webdir_temp != None and os.path.isdir(webdir_temp): + web_dir = os.path.normpath(webdir_temp) + os.sep + + paper_preference = paper_obj.get_data(DATA) + output_preference = output_obj.get_data(DATA) + goutput_preference = goutput_obj.get_data(DATA) + + set_bool("/gramps/config/UseTabs",usetabs) + set_bool("/gramps/config/UseLDS",uselds) + set_bool("/gramps/config/DisableAutoComplete",not autocomp) + set_bool("/gramps/config/MakeReference",mediaref) + set_bool("/gramps/config/DisplayGlobal",globalprop) + set_bool("/gramps/config/DisplayLocal",localprop) + set_bool("/gramps/config/ShowCalendar",calendar) + set_bool("/gramps/config/UseVersionControl",usevc) + set_bool("/gramps/config/UseComment",vc_comment) + set_bool("/gramps/config/DontCompressXML",uncompress) + set_bool("/gramps/config/IdVisible",id_visible) + set_bool("/gramps/config/IdEdit",id_edit) + set_bool("/gramps/config/IndexVisible",index_visible) + set_bool("/gramps/config/ShowDetail",show_detail) + set_int("/gramps/config/StatusBar",status_bar) + set_int("/gramps/config/ToolBar",toolbar+1) + set_bool("/gramps/config/DisplayAttr",display_attr) + set_string("/gramps/config/DisplayAttrName",attr_name) + set_string("/gramps/config/paperPreference",paper_preference) + set_string("/gramps/config/outputPreference",output_preference) + set_string("/gramps/config/goutputPreference",goutput_preference) + set_bool("/gramps/config/autoLoad",autoload) + set_int("/gramps/config/autoSaveInterval",autosave_int) + + if autosave_int != 0: + Utils.enable_autosave(None,autosave_int) + else: + Utils.disable_autosave() + + set_bool("/gramps/config/DisplayAltNames",hide_altnames) + set_string("/gramps/config/ReportDirectory",report_dir) + set_string("/gramps/config/WebsiteDirectory",web_dir) + set_string("/gramps/config/DbDirectory",db_dir) + set_string("/gramps/config/iprefix",iprefix) + set_string("/gramps/config/fprefix",fprefix) + set_string("/gramps/config/pprefix",pprefix) + set_string("/gramps/config/oprefix",oprefix) + set_string("/gramps/config/sprefix",sprefix) + + # search for the active date format selection + format_menu = self.top.get_widget("date_format").get_menu() + active = format_menu.get_active().get_data(INDEX) + + set_format_code(active) + set_int("/gramps/config/dateFormat",active) + + format_menu = self.top.get_widget("date_entry_format").get_menu() + entry_active = format_menu.get_active().get_data(INDEX) + + Date.entryCode = entry_active + set_int("/gramps/config/dateEntry",entry_active) + + # get the name format + + format_menu = self.top.get_widget("name_format").get_menu() + active_name = format_menu.get_active().get_data(INDEX) + + name_tuple = _name_format_list[active_name] + nameof = name_tuple[1] + set_int("/gramps/config/nameFormat",active_name) + + format_menu = self.top.get_widget("lastnamegen").get_menu() + lastnamegen = format_menu.get_active().get_data(DATA) + set_int("/gramps/config/surnameGuessing",lastnamegen) + + name = self.top.get_widget("resname").get_text() + addr = self.top.get_widget("resaddr").get_text() + city = self.top.get_widget("rescity").get_text() + state = self.top.get_widget("resstate").get_text() + country = self.top.get_widget("rescountry").get_text() + postal = self.top.get_widget("respostal").get_text() + phone = self.top.get_widget("resphone").get_text() + email = self.top.get_widget("resemail").get_text() + + Sorter.set_enable(self.top.get_widget("enableColors").get_active()) + set_bool("/gramps/color/enableColors",Sorter.get_enable()) + + Sorter.oddfg = self.top.get_widget(ODDFGCOLOR).get_i16() + Sorter.oddbg = self.top.get_widget(ODDBGCOLOR).get_i16() + Sorter.evenfg = self.top.get_widget(EVENFGCOLOR).get_i16() + Sorter.evenbg = self.top.get_widget(EVENBGCOLOR).get_i16() + Sorter.ancestorfg = self.top.get_widget(ANCESTORFGCOLOR).get_i16() + + save_config_color(ODDFGCOLOR,Sorter.oddfg) + save_config_color(ODDBGCOLOR,Sorter.oddbg) + save_config_color(EVENFGCOLOR,Sorter.evenfg) + save_config_color(EVENBGCOLOR,Sorter.evenbg) + save_config_color(ANCESTORFGCOLOR,Sorter.ancestorfg) + + set_string("/gramps/researcher/name",name) + set_string("/gramps/researcher/addr",addr) + set_string("/gramps/researcher/city",city) + set_string("/gramps/researcher/state",state) + set_string("/gramps/researcher/country",country) + set_string("/gramps/researcher/postal",postal) + set_string("/gramps/researcher/phone",phone) + set_string("/gramps/researcher/email",email) + + self.db.set_iprefix(iprefix) + self.db.set_fprefix(fprefix) + self.db.set_sprefix(sprefix) + self.db.set_oprefix(oprefix) + self.db.set_pprefix(pprefix) + + for o in self.ext_list: + o.set() + + # update the config file + + sync() + _callback() + + def on_object_toggled(self,obj): + """Called by the elements on the property box to set the changed flag, + so that the property box knows to set the Apply button""" + self.apply.set_sensitive(1) + + def on_format_toggled(self,obj): + """Called by the elements on the property box to set the changed flag, + so that the property box knows to set the Apply button""" + self.apply.set_sensitive(1) + + def on_color_toggled(self,obj): + """Called by the elements on the property box to set the changed flag, + so that the property box knows to set the Apply button""" + active = self.top.get_widget("enableColors").get_active() + self.top.get_widget(ODDFGCOLOR).set_sensitive(active) + self.top.get_widget(ODDBGCOLOR).set_sensitive(active) + self.top.get_widget(EVENFGCOLOR).set_sensitive(active) + self.top.get_widget(EVENBGCOLOR).set_sensitive(active) + self.top.get_widget(ANCESTORFGCOLOR).set_sensitive(active) + self.apply.set_sensitive(1) + + def on_color_set(self,obj,r,g,b,a): + """Called by the elements on the property box to set the changed flag, + so that the property box knows to set the Apply button""" + self.apply.set_sensitive(1) + +#------------------------------------------------------------------------- +# +# Create the property box, and set the elements off the current values +# +#------------------------------------------------------------------------- +def display_preferences_box(db): + GrampsPreferences(db) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def get_config_color(name,defval): + r = get_int("/gramps/color/" + name + ".r") + g = get_int("/gramps/color/" + name + ".g") + b = get_int("/gramps/color/" + name + ".b") + if r == None: + return defval + else: + return (r,g,b) + +def get_sort_cols(name,col,dir): + c = get_int("/gramps/sort/%s_col" % name) + if c == None: + c = col + d = get_int("/gramps/sort/%s_dir" % name) + if d == None: + d = dir + return (c,d) + +def save_sort_cols(name,col,dir): + set_int("/gramps/sort/%s_col" % name, col) + set_int("/gramps/sort/%s_dir" % name, dir) + sync() + +def save_view(val): + set_bool("/gramps/config/view",val) + +def get_view(): + return get_bool("/gramps/config/view",1) + +def save_filter(val): + set_bool("/gramps/config/filter",val) + +def get_filter(): + return get_bool("/gramps/config/filter") diff --git a/gramps2/src/GrampsParser.py b/gramps2/src/GrampsParser.py new file mode 100644 index 000000000..fa692f7e7 --- /dev/null +++ b/gramps2/src/GrampsParser.py @@ -0,0 +1,913 @@ +# +# 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 Date import SingleDate + +import string +import Utils +import xml.parsers.expat + +#------------------------------------------------------------------------- +# +# Remove extraneous spaces +# +#------------------------------------------------------------------------- + +def rs(text): + return string.join(string.split(text)) + +def fix_spaces(text_list): + return string.join(map(rs,text_list),'\n') + +#------------------------------------------------------------------------- +# +# Gramps database parsing class. Derived from SAX XML parser +# +#------------------------------------------------------------------------- +class GrampsParser: + + def __init__(self,database,callback,base): + self.stext_list = [] + self.scomments_list = [] + self.note_list = [] + self.tlist = [] + self.conf = 2 + + self.ord = None + self.objref = None + self.object = None + self.pref = None + self.use_p = 0 + self.in_note = 0 + self.in_stext = 0 + self.in_scomments = 0 + self.db = database + self.base = base + self.photo = None + self.person = None + self.family = None + self.address = None + self.source = None + self.source_ref = None + self.attribute = None + self.placeobj = None + self.locations = 0 + self.place_map = {} + + self.resname = "" + self.resaddr = "" + self.rescity = "" + self.resstate = "" + self.rescon = "" + self.respos = "" + self.resphone = "" + self.resemail = "" + + self.pmap = {} + self.fmap = {} + self.smap = {} + + self.callback = callback + self.entries = 0 + self.count = 0 + self.increment = 100 + self.event = None + self.name = None + self.tempDefault = None + self.owner = Researcher() + self.func_list = [None]*50 + self.func_index = 0 + self.func = None + + def parse(self,file): + p = xml.parsers.expat.ParserCreate() + p.StartElementHandler = self.startElement + p.EndElementHandler = self.endElement + p.CharacterDataHandler = self.characters + p.ParseFile(file) + + self.db.setResearcher(self.owner) + if self.tempDefault != None: + id = self.tempDefault + if self.db.personMap.has_key(id): + person = self.db.personMap[id] + self.db.setDefaultPerson(person) + + def start_lds_ord(self,attrs): + type = attrs['type'] + self.ord = LdsOrd() + if self.person: + if type == "baptism": + self.person.setLdsBaptism(self.ord) + elif type == "endowment": + self.person.setLdsEndowment(self.ord) + elif type == "sealed_to_parents": + self.person.setLdsSeal(self.ord) + elif self.family: + if type == "sealed_to_spouse": + self.family.setLdsSeal(self.ord) + + def start_temple(self,attrs): + self.ord.setTemple(attrs['val']) + + def start_status(self,attrs): + self.ord.setStatus(int(attrs['val'])) + + def start_sealed_to(self,attrs): + id = attrs['ref'] + self.ord.setFamily(self.db.findFamilyNoMap(id)) + + def start_place(self,attrs): + if attrs.has_key('ref'): + self.placeobj = self.db.findPlaceNoMap(attrs['ref']) + else: + self.placeobj = None + + def start_placeobj(self,attrs): + self.placeobj = self.db.findPlaceNoMap(attrs['id']) + title = attrs['title'] + if title == "": + title = attrs['id'] + self.placeobj.set_title(title) + self.locations = 0 + if self.num_places > 0: + if self.callback != None and self.count % self.increment == 0: + self.callback(float(self.count)/float(self.entries)) + self.count = self.count + 1 + + def start_location(self,attrs): + """Bypass the function calls for this one, since it appears to + take up quite a bit of time""" + + loc = Location() + if attrs.has_key('city'): + loc.city = attrs['city'] + if attrs.has_key('parish'): + loc.parish = attrs['parish'] + if attrs.has_key('state'): + loc.state = attrs['state'] + if attrs.has_key('county'): + loc.county =attrs['county'] + if attrs.has_key('country'): + loc.country = attrs['country'] + if self.locations > 0: + self.placeobj.add_alternate_locations(loc) + else: + self.placeobj.set_main_location(loc) + self.locations = self.locations + 1 + + def start_coord(self,attrs): + if attrs.has_key('lat'): + self.placeobj.set_latitude(attrs['lat']) + if attrs.has_key('long'): + self.placeobj.set_longitude(attrs['long']) + + def start_event(self,attrs): + self.event = Event() + self.event_type = attrs["type"] + if attrs.has_key("conf"): + self.event.conf = int(attrs["conf"]) + else: + self.event.conf = 2 + if attrs.has_key("priv"): + self.event.private = int(attrs["priv"]) + + def start_attribute(self,attrs): + self.attribute = Attribute() + if attrs.has_key("conf"): + self.attribute.conf = int(attrs["conf"]) + else: + self.attribute.conf = 2 + if attrs.has_key("priv"): + self.attribute.private = int(attrs["priv"]) + if attrs.has_key('type'): + self.attribute.setType(attrs["type"]) + if attrs.has_key('value'): + self.attribute.setValue(attrs["value"]) + if self.photo: + self.photo.addAttribute(self.attribute) + elif self.object: + self.object.addAttribute(self.attribute) + elif self.objref: + self.objref.addAttribute(self.attribute) + elif self.person: + self.person.addAttribute(self.attribute) + elif self.family: + self.family.addAttribute(self.attribute) + + def start_address(self,attrs): + self.address = Address() + self.person.addAddress(self.address) + if attrs.has_key("conf"): + self.address.conf = int(attrs["conf"]) + else: + self.address.conf = 2 + if attrs.has_key("priv"): + self.address.private = int(attrs["priv"]) + + def start_bmark(self,attrs): + person = self.db.findPersonNoMap(attrs["ref"]) + self.db.bookmarks.append(person) + + def start_person(self,attrs): + if self.callback != None and self.count % self.increment == 0: + self.callback(float(self.count)/float(self.entries)) + self.count = self.count + 1 + self.person = self.db.findPersonNoMap(attrs["id"]) + + def start_people(self,attrs): + if attrs.has_key("default"): + self.tempDefault = attrs["default"] + + def start_father(self,attrs): + self.family.Father = self.db.findPersonNoMap(attrs["ref"]) + + def start_mother(self,attrs): + self.family.Mother = self.db.findPersonNoMap(attrs["ref"]) + + def start_child(self,attrs): + self.family.Children.append(self.db.findPersonNoMap(attrs["ref"])) + + def start_url(self,attrs): + + if not attrs.has_key("href"): + return + try: + desc = attrs["description"] + except KeyError: + desc = "" + + try: + url = Url() + url.set_path(attrs["href"]) + url.set_description(desc) + if attrs.has_key("priv"): + url.setPrivacy(int(attrs['priv'])) + if self.person: + self.person.addUrl(url) + elif self.placeobj: + self.placeobj.addUrl(url) + except KeyError: + return + + def start_family(self,attrs): + if self.callback != None and self.count % self.increment == 0: + self.callback(float(self.count)/float(self.entries)) + self.count = self.count + 1 + self.family = self.db.findFamilyNoMap(attrs["id"]) + if attrs.has_key("type"): + self.family.setRelationship(attrs["type"]) + else: + self.family.setRelationship("") + + def start_childof(self,attrs): + family = self.db.findFamilyNoMap(attrs["ref"]) + if attrs.has_key("mrel"): + mrel = attrs["mrel"] + else: + mrel = "Birth" + if attrs.has_key("frel"): + frel = attrs["frel"] + else: + frel = "Birth" + self.person.AltFamilyList.append((family,mrel,frel)) + + def start_parentin(self,attrs): + self.person.FamilyList.append(self.db.findFamilyNoMap(attrs["ref"])) + + def start_name(self,attrs): + self.name = Name() + if attrs.has_key("type"): + self.name.setType(attrs["type"]) + if attrs.has_key("conf"): + self.name.conf = int(attrs["conf"]) + else: + self.name.conf = 2 + if attrs.has_key("priv"): + self.name.private = int(attrs["priv"]) + + def start_note(self,attrs): + self.in_note = 1 + + def start_sourceref(self,attrs): + self.source_ref = SourceRef() + source = self.db.findSourceNoMap(attrs["ref"]) + if attrs.has_key("conf"): + self.source_ref.confidence = int(attrs["conf"]) + else: + self.source_ref.confidence = self.conf + self.source_ref.setBase(source) + if self.photo: + self.photo.addSourceRef(self.source_ref) + elif self.ord: + self.ord.addSourceRef(self.source_ref) + elif self.object: + self.object.addSourceRef(self.source_ref) + elif self.event: + self.event.addSourceRef(self.source_ref) + elif self.address: + self.address.addSourceRef(self.source_ref) + elif self.name: + self.name.addSourceRef(self.source_ref) + elif self.attribute: + self.attribute.addSourceRef(self.source_ref) + elif self.placeobj: + self.placeobj.addSourceRef(self.source_ref) + + def start_source(self,attrs): + if self.num_srcs > 0: + if self.callback != None and self.count % self.increment == 0: + self.callback(float(self.count)/float(self.entries)) + self.count = self.count + 1 + self.source = self.db.findSourceNoMap(attrs["id"]) + + def start_objref(self,attrs): + self.objref = ObjectRef() + self.objref.setReference(self.db.findObjectNoMap(attrs['ref'])) + if attrs.has_key('priv'): + self.objref.setPrivacy(int(attrs['priv'])) + if self.family: + self.family.addPhoto(self.objref) + elif self.source: + self.source.addPhoto(self.objref) + elif self.person: + self.person.addPhoto(self.objref) + elif self.placeobj: + self.placeobj.addPhoto(self.objref) + + def start_object(self,attrs): + self.object = self.db.findObjectNoMap(attrs['id']) + self.object.setMimeType(attrs['mime']) + self.object.setDescription(attrs['description']) + src = attrs["src"] + if src: + if src[0] != '/': + self.object.setPath("%s/%s" % (self.base,src)) + self.object.setLocal(1) + else: + self.object.setPath(src) + self.object.setLocal(0) + + def stop_object(self,tag): + self.object = None + + def stop_objref(self,tag): + self.objref = None + + def start_photo(self,attrs): + self.photo = Photo() + self.pref = ObjectRef() + self.pref.setReference(self.photo) + + for key in attrs.keys(): + if key == "descrip" or key == "description": + self.photo.setDescription(attrs[key]) + elif key == "priv": + self.pref.setPrivacy(int(attrs[key])) + elif key == "src": + src = attrs["src"] + if src[0] != '/': + self.photo.setPath("%s/%s" % (self.base,src)) + self.photo.setLocal(1) + else: + self.photo.setPath(src) + self.photo.setLocal(0) + else: + a = Attribute() + a.setType(key) + a.setValue(attrs[key]) + self.photo.addAttribute(a) + self.photo.setMimeType(Utils.get_mime_type(self.photo.getPath())) + self.db.addObject(self.photo) + if self.family: + self.family.addPhoto(self.pref) + elif self.source: + self.source.addPhoto(self.pref) + elif self.person: + self.person.addPhoto(self.pref) + elif self.placeobj: + self.placeobj.addPhoto(self.pref) + + def start_daterange(self,attrs): + if self.source_ref: + d = self.source_ref.getDate() + elif self.ord: + d = self.ord.getDateObj() + elif self.address: + d = self.address.getDateObj() + else: + d = self.event.getDateObj() + + if attrs.has_key("calendar"): + d.set_calendar(int(attrs['calendar'])) + + d.get_start_date().setIsoDate(attrs['start']) + d.get_stop_date().setIsoDate(attrs['stop']) + d.range = 1 + + def start_dateval(self,attrs): + if self.source_ref: + d = self.source_ref.getDate() + elif self.ord: + d = self.ord.getDateObj() + elif self.address: + d = self.address.getDateObj() + else: + d = self.event.getDateObj() + + if attrs.has_key("calendar"): + d.set_calendar(int(attrs['calendar'])) + + d.get_start_date().setIsoDate(attrs['val']) + + if attrs.has_key("type"): + d.get_start_date().setMode(attrs['type']) + else: + d.get_start_date().setMode(None) + + def start_datestr(self,attrs): + if self.source_ref: + d = self.source_ref.getDate() + elif self.ord: + d = self.ord.getDateObj() + elif self.address: + d = self.address.getDateObj() + else: + d = self.event.getDateObj() + + d.set(attrs['val']) + + def start_created(self,attrs): + if attrs.has_key('sources'): + self.num_srcs = int(attrs['sources']) + else: + self.num_srcs = 0 + if attrs.has_key('places'): + self.num_places = int(attrs['places']) + else: + self.num_places = 0 + self.entries = int(attrs["people"]) + int(attrs["families"]) + \ + self.num_places + self.num_srcs + + def start_pos(self,attrs): + self.person.position = (int(attrs["x"]), int(attrs["y"])) + + def stop_attribute(self,tag): + self.attribute = None + + def stop_attr_type(self,tag): + self.attribute.setType(tag) + + def stop_attr_value(self,tag): + self.attribute.setValue(tag) + + def stop_address(self,tag): + self.address = None + + def stop_places(self,tag): + self.placeobj = None + + def stop_photo(self,tag): + self.photo = None + + def stop_placeobj(self,tag): + if self.placeobj.get_title() == "": + loc = self.placeobj.get_main_location() + self.placeobj.set_title(build_place_title(loc)) + self.db.buildPlaceDisplay(self.placeobj.getId()) + self.palceobj = None + + def stop_event(self,tag): + self.event.name = self.event_type + + if self.family: + self.family.EventList.append(self.event) + else: + if self.event_type == "Birth": + self.person.setBirth(self.event) + elif self.event_type == "Death": + self.person.setDeath(self.event) + else: + self.person.EventList.append(self.event) + self.event = None + + def stop_name(self,tag): + self.person.PrimaryName = self.name + if self.name.getType() == "": + self.name.setType("Birth Name") + self.name = None + + def stop_place(self,tag): + if self.placeobj == None: + if self.place_map.has_key(tag): + self.placeobj = self.place_map[tag] + else: + self.placeobj = Place() + self.placeobj.set_title(tag) + self.db.addPlace(self.placeobj) + self.place_map[tag] = self.placeobj + if self.ord: + self.ord.setPlace(self.placeobj) + else: + self.event.place = self.placeobj + + def stop_uid(self,tag): + self.person.setPafUid(tag) + + def stop_date(self,tag): + if tag: + if self.address: + self.address.setDate(tag) + else: + self.event.setDate(tag) + + def stop_first(self,tag): + self.name.FirstName = tag + + def stop_families(self,tag): + self.family = None + + def stop_people(self,tag): + self.person = None + + def stop_person(self,tag): + self.db.buildPersonDisplay(self.person.getId()) + + def stop_description(self,tag): + self.event.setDescription(tag) + + def stop_cause(self,tag): + self.event.setCause(tag) + + def stop_gender(self,tag): + t = tag + if t == "M": + self.person.gender = Person.male + elif t == "F": + self.person.gender = Person.female + else: + self.person.gender = Person.unknown + + def stop_stitle(self,tag): + self.source.setTitle(tag) + + def stop_sourceref(self,tag): + self.source_ref = None + + def stop_source(self,tag): + self.db.buildSourceDisplay(self.source.getId()) + self.source = None + + def stop_sauthor(self,tag): + self.source.setAuthor(tag) + + def stop_sdate(self,tag): + date = Date() + date.set(tag) + self.source_ref.setDate(date) + + 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_ref.setPage(tag) + + def stop_lds_ord(self,tag): + self.ord = None + + def stop_spubinfo(self,tag): + self.source.setPubInfo(tag) + + def stop_scallno(self,tag): + self.source.setCallNumber(tag) + + def stop_stext(self,tag): + if self.use_p: + self.use_p = 0 + note = fix_spaces(self.stext_list) + else: + note = tag + self.source_ref.setText(note) + + def stop_scomments(self,tag): + if self.use_p: + self.use_p = 0 + note = fix_spaces(self.scomments_list) + else: + note = tag + self.source_ref.setComments(note) + + def stop_last(self,tag): + if self.name: + self.name.Surname = tag + + def stop_suffix(self,tag): + if self.name: + self.name.Suffix = tag + + def stop_title(self,tag): + if self.name: + self.name.Title = tag + + def stop_nick(self,tag): + if self.person: + self.person.setNickName(tag) + + def stop_note(self,tag): + self.in_note = 0 + if self.use_p: + self.use_p = 0 + note = fix_spaces(self.note_list) + else: + note = tag + + if self.address: + self.address.setNote(note) + elif self.ord: + self.ord.setNote(note) + elif self.attribute: + self.attribute.setNote(note) + elif self.object: + self.object.setNote(note) + elif self.objref: + self.objref.setNote(note) + elif self.photo: + self.photo.setNote(note) + elif self.name: + self.name.setNote(note) + elif self.source: + self.source.setNote(note) + elif self.event: + self.event.setNote(note) + elif self.person: + self.person.setNote(note) + elif self.family: + self.family.setNote(note) + elif self.placeobj: + self.placeobj.setNote(note) + self.note_list = [] + + def stop_research(self,tag): + self.owner.set(self.resname, self.resaddr, self.rescity, self.resstate, + self.rescon, self.respos, self.resphone, self.resemail) + + def stop_resname(self,tag): + self.resname = tag + + def stop_resaddr(self,tag): + self.resaddr = tag + + def stop_rescity(self,tag): + self.rescity = tag + + def stop_resstate(self,tag): + self.resstate = tag + + def stop_rescountry(self,tag): + self.rescon = tag + + def stop_respostal(self,tag): + self.respos = tag + + def stop_resphone(self,tag): + self.resphone = tag + + def stop_resemail(self,tag): + self.resemail = tag + + def stop_ptag(self,tag): + self.use_p = 1 + 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) + if self.name.getType() == "": + self.name.setType("Also Known As") + self.name = None + + func_map = { + "address" : (start_address, stop_address), + "addresses" : (None,None), + "childlist" : (None,None), + "aka" : (start_name, stop_aka), + "attribute" : (start_attribute, stop_attribute), + "attr_type" : (None,stop_attr_type), + "attr_value" : (None,stop_attr_value), + "bookmark" : (start_bmark, None), + "bookmarks" : (None, None), + "child" : (start_child,None), + "childof" : (start_childof,None), + "city" : (None, stop_city), + "country" : (None, stop_country), + "created" : (start_created, None), + "database" : (None, None), + "date" : (None, stop_date), + "cause" : (None, stop_cause), + "description": (None, stop_description), + "event" : (start_event, stop_event), + "families" : (None, stop_families), + "family" : (start_family, None), + "father" : (start_father, None), + "first" : (None, stop_first), + "gender" : (None, stop_gender), + "header" : (None, None), + "last" : (None, stop_last), + "mother" : (start_mother,None), + "name" : (start_name, stop_name), + "nick" : (None, stop_nick), + "note" : (start_note, stop_note), + "p" : (None, stop_ptag), + "parentin" : (start_parentin,None), + "people" : (start_people, stop_people), + "person" : (start_person, stop_person), + "img" : (start_photo, stop_photo), + "objref" : (start_objref, stop_objref), + "object" : (start_object, stop_object), + "place" : (start_place, stop_place), + "dateval" : (start_dateval, None), + "daterange" : (start_daterange, None), + "datestr" : (start_datestr, None), + "places" : (None, stop_places), + "placeobj" : (start_placeobj,stop_placeobj), + "location" : (start_location,None), + "lds_ord" : (start_lds_ord, stop_lds_ord), + "temple" : (start_temple, None), + "status" : (start_status, None), + "sealed_to" : (start_sealed_to, None), + "coord" : (start_coord,None), + "pos" : (start_pos, None), + "postal" : (None, stop_postal), + "researcher" : (None, stop_research), + "resname" : (None, stop_resname ), + "resaddr" : (None, stop_resaddr ), + "rescity" : (None, stop_rescity ), + "resstate" : (None, stop_resstate ), + "rescountry" : (None, stop_rescountry), + "respostal" : (None, stop_respostal), + "resphone" : (None, stop_resphone), + "resemail" : (None, stop_resemail), + "sauthor" : (None, stop_sauthor), + "scallno" : (None, stop_scallno), + "scomments" : (None, stop_scomments), + "sdate" : (None,stop_sdate), + "source" : (start_source, stop_source), + "sourceref" : (start_sourceref, stop_sourceref), + "sources" : (None, None), + "spage" : (None, stop_spage), + "spubinfo" : (None, stop_spubinfo), + "state" : (None, stop_state), + "stext" : (None, stop_stext), + "stitle" : (None, stop_stitle), + "street" : (None, stop_street), + "suffix" : (None, stop_suffix), + "title" : (None, stop_title), + "uid" : (None, stop_uid), + "url" : (start_url, None) + } + + def startElement(self,tag,attrs): + + self.func_list[self.func_index] = (self.func,self.tlist) + self.func_index = self.func_index + 1 + self.tlist = [] + + try: + f,self.func = GrampsParser.func_map[tag] + if f: + f(self,attrs) + except KeyError: + GrampsParser.func_map[tag] = (None,None) + self.func = None + + def endElement(self,tag): + + if self.func: + self.func(self,string.join(self.tlist,'')) + self.func_index = self.func_index - 1 + self.func,self.tlist = self.func_list[self.func_index] + + def characters(self, data): + if self.func: + self.tlist.append(data) + +#------------------------------------------------------------------------- +# +# Gramps database parsing class. Derived from SAX XML parser +# +#------------------------------------------------------------------------- +class GrampsImportParser(GrampsParser): + + def start_bmark(self,attrs): + person = self.db.findPerson("x%s" % attrs["ref"],self.pmap) + self.db.bookmarks.append(person) + + def start_person(self,attrs): + if self.callback != None and self.count % self.increment == 0: + self.callback(float(self.count)/float(self.entries)) + self.count = self.count + 1 + self.person = self.db.findPerson("x%s" % attrs["id"],self.pmap) + + def start_father(self,attrs): + father = self.db.findPerson("x%s" % attrs["ref"],self.pmap) + self.family.setFather(father) + + def start_mother(self,attrs): + mother = self.db.findPerson("x%s" % attrs["ref"],self.pmap) + self.family.setMother(mother) + + def start_child(self,attrs): + child = self.db.findPerson("x%s" % attrs["ref"],self.pmap) + self.family.addChild(child) + + def start_family(self,attrs): + if self.callback != None and self.count % self.increment == 0: + self.callback(float(self.count)/float(self.entries)) + self.count = self.count + 1 + self.family = self.db.findFamily(attrs["id"],self.fmap) + if attrs.has_key("type"): + self.family.setRelationship(attrs["type"]) + + def start_sourceref(self,attrs): + self.source_ref = SourceRef() + self.source = self.db.findSource(attrs["ref"],self.smap) + self.source_ref.setBase(self.source) + if self.address: + self.address.addSourceRef(self.source_ref) + elif self.name: + self.name.addSourceRef(self.source_ref) + elif self.event: + self.event.addSourceRef(self.source_ref) + elif self.attribute: + self.attribute.addSourceRef(self.source_ref) + elif self.placeobj: + self.placeobj.addSourceRef(self.source_ref) + else: + print "Sorry, I'm lost" + + def start_source(self,attrs): + self.source = self.db.findSource(attrs["id"],self.smap) + + +def append_value(orig,val): + if orig: + return "%s, %s" % (orig,val) + else: + return val + +def build_place_title(loc): + "Builds a title from a location" + city = loc.get_city() + state = loc.get_state() + country = loc.get_country() + county = loc.get_county() + parish = loc.get_parish() + + value = "" + + if parish: + value = parish + if city: + value = append_value(value,city) + if county: + value = append_value(value,county) + if state: + value = append_value(value,state) + if country: + value = append_value(value,country) + return value + diff --git a/gramps2/src/GrampsXML.py b/gramps2/src/GrampsXML.py new file mode 100644 index 000000000..60ff140c6 --- /dev/null +++ b/gramps2/src/GrampsXML.py @@ -0,0 +1,58 @@ +# +# 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 GrampsDB +import WriteXML +import ReadXML +import const + +class GrampsXML(GrampsDB): + + def get_base(self): + return const.xmlFile + + def get_type(self): + return 'GrampsXML' + + def new(self): + GrampsDB.new(self) + + def save(self,name,callback): + WriteXML.exportData(self,name,callback) + + def load(self,name,callback): + ReadXML.importData(self,name,callback) + self.personTable = {} + for key in self.personMap.keys(): + person = self.personMap[key] + self.personTable[key] = person.getDisplayInfo() + self.addSurname(person.getPrimaryName().getSurname()) + + self.placeTable = {} + for key in self.placeMap.keys(): + place = self.placeMap[key] + self.placeTable[key] = place.getDisplayInfo() + + self.sourceTable = {} + for key in self.sourceMap.keys(): + src = self.sourceMap[key] + self.sourceTable[key] = src.getDisplayInfo() + + return 1 diff --git a/gramps2/src/GrampsZODB.py b/gramps2/src/GrampsZODB.py new file mode 100644 index 000000000..82a51ee4c --- /dev/null +++ b/gramps2/src/GrampsZODB.py @@ -0,0 +1,259 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2002 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 ZODB import Persistent +from ZODB.PersistentList import PersistentList +from ZODB.dbmStorage import gdbmStorage +from ZODB.DB import DB +from BTrees.OOBTree import OOBTree +from UserDict import UserDict +from RelLib import GrampsDB, Person +import const + +class PersistentReference(Persistent): + + def __init__(self, ob): + self.ob = ob + + def getOb(self): + return self.ob + +class PersonWrapper: + + _real = None + + def __init__(self, real, map): + self._real = real + self._map_ref = PersistentReference(map) + self.id = real.getId() + self.PrimaryName = real.getPrimaryName() + self.gender = real.getGender() + self.birth = real.getBirth() + self.death = real.getDeath() + + def _notifyChange(self): + # Trigger a change to the PersonMap. + self._map_ref.getOb()[self.id] = self + + def getId(self): + return self.id + + def setId(self, id): + self._real.setId(id) + self.id = self._real.getId() + self._notifyChange() + + def getPrimaryName(self): + return self.PrimaryName + + def setPrimaryName(self, name): + self._real.setPrimaryName(name) + self.PrimaryName = self._real.getPrimaryName() + self._notifyChange() + + def getGender(self): + return self.gender + + def setGender(self, gender): + self._real.setGender(gender) + self.gender = self._real.getGender() + self._notifyChange() + + def getBirth(self): + return self.birth + + def setBirth(self, birth): + self._real.setBirth(birth) + self.birth = self._real.getBirth() + self._notifyChange() + + def getDeath(self): + return self.death + + def setDeath(self, death): + self._real.setDeath(death) + self.death = self._real.getDeath() + self._notifyChange() + + +for key, value in Person.__dict__.items(): + if not key.startswith('_'): + code = ("def %s(self, *args, **kw): " + "return apply(self._real.%s, args, kw)") % (key, key) + d = {} + exec code in d + PersonWrapper.__dict__[key] = d[key] + + +class PersonMap(Persistent, UserDict): + + def __init__(self): + self.data = OOBTree() + + def __setitem__(self, key, value): + if not isinstance(value, PersonWrapper): + # Create the PersonWrapper. + assert isinstance(value, Person) + value = PersonWrapper(value, self) + self.data[key] = value + + def update(self): + # This probably shouldn't be called anyway. + raise NotImplementedError + + def copy(self): + # This probably shouldn't be called anyway. + raise NotImplementedError + +class GrampsZODB(GrampsDB): + + def __init__(self): + self.conn = None + GrampsDB.__init__(self) + + def get_type(self): + return 'GrampsZODB' + + def close(self): + self.db.close() + + def get_base(self): + return const.zodbFile + + def need_autosave(self): + return 0 + + def new(self): + GrampsDB.new(self) + self.familyMap = OOBTree() + self.personMap = PersonMap() + self.sourceMap = OOBTree() + self.placeMap = OOBTree() + self.personTable = OOBTree() + self.placeTable = OOBTree() + self.sourceTable = OOBTree() + self.need_commit = 0 + + if self.conn: + self.db.close() + self.conn.close() + self.conn = None + + def save(self,name,callback): + get_transaction().commit() + if self.conn == None: + self.load(name,callback) + + def get_object(self,tag): + if self.root.has_key(tag): + item = self.root[tag] + else: + item = OOBTree() + self.root[tag] = item + self.need_commit = 1 + return item + + def get_display_table(self,src,tag): + if self.root.has_key(tag): + table = self.root[tag] + else: + table = OOBTree() + for key in src.keys(): + obj = src[key] + table[key] = obj.getDisplayInfo() + self.root[tag] = table + self.need_commit = 1 + return table + + def load(self,name,callback): + self.db = DB(gdbmStorage(name,'w')) + self.conn = self.db.open() + self.root = self.conn.root() + self.need_commit = 0 + + self.familyMap = self.get_object('familyMap') + + if self.root.has_key('personMap'): + self.personMap = self.root['personMap'] + else: + self.personMap = PersonMap() + self.root['personMap'] = self.personMap + self.need_commit = 1 + + self.personTable = self.get_display_table(self.personMap,'personTable') + + if self.root.has_key('surnames'): + self.surnames = self.root['surnames'] + else: + self.surnames = PersistentList() + for key in self.personMap.keys(): + person = self.personMap[key] + self.addSurname(person.getPrimaryName().getSurname()) + self.root['surnames'] = self.surnames + self.need_commit = 1 + + self.sourceMap = self.get_object('sourceMap') + self.sourceTable = self.get_display_table(self.sourceMap,'sourceTable') + + self.placeMap = self.get_object('placeMap') + self.placeTable = self.get_display_table(self.placeMap,'placeTable') + + if self.root.has_key('default'): + self.default = self.root['default'] + else: + self.default = None + self.root['default'] = self.default + self.need_commit = 1 + + if self.root.has_key('bookmarks'): + self.bookmarks = self.root['bookmarks'] + else: + self.bookmarks = [] + self.root['bookmarks'] = self.bookmarks + self.need_commit = 1 + if self.need_commit: + get_transaction().commit() + return 1 + + def setDefaultPerson(self,person): + """sets the default Person to the passed instance""" + GrampsDB.setDefaultPerson(self,person) + self.root['default'] = person + + + + + + + + + + + + + + + + + + + + + diff --git a/gramps2/src/GraphLayout.py b/gramps2/src/GraphLayout.py new file mode 100644 index 000000000..5b15db81e --- /dev/null +++ b/gramps2/src/GraphLayout.py @@ -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 +# + +class GraphLayout: + + def __init__(self,plist,person): + self.plist = plist + self.person = person + self.v = [] + self.e = [] + self.maxx = 0 + self.maxy = 0 + + def max_size(self): + return (self.maxx,self.maxy) + + def layout(self): + return ([],[]) + +class DescendLine(GraphLayout): + + def layout(self): + self.elist = [(0,0)] + self.space_for(self.person) + return (self.v,self.e[1:]) + + def space_for(self,person,level=1.0,pos=1.0): + last = self.elist[-1] + self.elist.append((level,pos)) + self.e.append((last[0],last[1],level,pos)) + self.v.append((person,level,pos)) + if level > self.maxx: + self.maxx = level + if pos > self.maxy: + self.maxy = pos + + for family in person.getFamilyList(): + for child in family.getChildList(): + self.space_for(child,level+1.0,pos) + pos = pos + max(self.depth(child),1) + if pos > self.maxy: + self.maxy = pos + self.elist.pop() + + def depth(self,person,val=1.0): + for family in person.getFamilyList(): + clist = family.getChildList() + val = val + len(clist) + for child in clist: + val = self.depth(child,val) + val = val - 1.0 + return val diff --git a/gramps2/src/ImageSelect.py b/gramps2/src/ImageSelect.py new file mode 100644 index 000000000..dae6317a7 --- /dev/null +++ b/gramps2/src/ImageSelect.py @@ -0,0 +1,838 @@ +# +# 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 +import string + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk +import gnome.ui +import gnome.canvas +import gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import GrampsCfg +import Plugins +from RelLib import * +import RelImage + +import EditPerson +import Marriage +import EditPlace +import EditSource + +from intl import gettext as _ + +_IMAGEX = 140 +_IMAGEY = 150 + +#------------------------------------------------------------------------- +# +# ImageSelect class +# +#------------------------------------------------------------------------- +class ImageSelect: + + last_path = "" + + def __init__(self, path, db, parent): + """Creates an edit window. Associates a person with the window.""" + self.path = path; + self.db = db + self.dataobj = None + self.parent = parent + self.canvas_list = [] + + def add_thumbnail(self, photo): + "should be overrridden" + pass + + def load_images(self): + "should be overrridden" + pass + + def create_add_dialog(self): + """Create the gnome dialog for selecting a new photo and entering + its description.""" + + if self.path == '': + return + + self.glade = gtk.glade.XML(const.imageselFile,"imageSelect") + window = self.glade.get_widget("imageSelect") + self.fname = self.glade.get_widget("fname") + self.image = self.glade.get_widget("image") + self.description = self.glade.get_widget("photoDescription") + self.external = self.glade.get_widget("private") + self.temp_name = "" + + self.glade.signal_autoconnect({ + "on_savephoto_clicked" : self.on_savephoto_clicked, + "on_name_changed" : self.on_name_changed, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + if ImageSelect.last_path != "": + self.glade.get_widget("photosel").set_default_path(ImageSelect.last_path) + window.show() + + def on_name_changed(self, obj): + """The filename has changed. Verify it and load the picture.""" + filename = self.fname.get_text() + + basename = os.path.basename(filename) + (root,ext) = os.path.splitext(basename) + old_title = self.description.get_text() + + if old_title == "" or old_title == self.temp_name: + self.description.set_text(root) + self.temp_name = root + + if os.path.isfile(filename): + type = Utils.get_mime_type(filename) + if type[0:5] == "image": + image = RelImage.scale_image(filename,const.thumbScale) + self.image.set_from_pixbuf(image) + else: + i = gtk.gdk.pixbuf_new_from_file(Utils.find_icon(type)) + self.image.set_from_pixbuf(i) + + def on_savephoto_clicked(self, obj): + """Save the photo in the dataobj object. (Required function)""" + filename = self.glade.get_widget("photosel").get_full_path(0) + ImageSelect.last_path = os.path.dirname(filename) + + description = self.description.get_text() + + if os.path.exists(filename) == 0: + gnome.ui.GnomeErrorDialog(_("That is not a valid file name.")); + return + + already_imported = None + for o in self.db.getObjectMap().values(): + if o.getPath() == filename: + already_imported = o + break + + if (already_imported): + oref = ObjectRef() + oref.setReference(already_imported) + self.dataobj.addPhoto(oref) + self.add_thumbnail(oref) + else: + type = Utils.get_mime_type(filename) + mobj = Photo() + if description == "": + description = os.path.basename(filename) + mobj.setDescription(description) + mobj.setMimeType(type) + self.savephoto(mobj) + + if type[0:5] == "image": + if self.external.get_active() == 0: + name = RelImage.import_media_object(filename,self.path, + mobj.getId()) + mobj.setLocal(1) + else: + name = filename + else: + if self.external.get_active() == 1: + name = filename + else: + name = RelImage.import_media_object(filename,self.path, + mobj.getId()) + mobj.setLocal(1) + mobj.setPath(name) + + self.parent.lists_changed = 1 + Utils.destroy_passed_object(obj) + self.load_images() + + def savephoto(self, photo): + """Save the photo in the dataobj object - must be overridden""" + pass + +#------------------------------------------------------------------------- +# +# Gallery class - This class handles all the logic underlying a +# picture gallery. This class does not load or contain the widget +# data structure to actually display the gallery. +# +#------------------------------------------------------------------------- +class Gallery(ImageSelect): + def __init__(self, dataobj, path, icon_list, db, parent): + ImageSelect.__init__(self, path, db, parent) + + t = [ + ('STRING', 0, 0), + ('text/plain',0,0), + ('text/uri-list',0,2), + ('application/x-rootwin-drop',0,1)] + + if path: + icon_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, t, + gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) + icon_list.connect("drag_data_received", + self.on_photolist_drag_data_received) + icon_list.drag_source_set(gtk.gdk.BUTTON1_MASK|gtk.gdk.BUTTON3_MASK,t, + gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) + icon_list.connect("drag_data_get", + self.on_photolist_drag_data_get) + + # Remember arguments + self.path = path; + self.dataobj = dataobj; + self.iconlist = icon_list; + self.root = self.iconlist.root() + + # Local object variables + self.selectedIcon = -1 + self.x = 0 + self.y = 0 + + def savephoto(self, photo): + """Save the photo in the dataobj object. (Required function)""" + self.db.addObject(photo) + oref = ObjectRef() + oref.setReference(photo) + self.dataobj.addPhoto(oref) + self.add_thumbnail(oref) + + def add_thumbnail(self, photo): + """Scale the image and add it to the IconList.""" + object = photo.getReference() + name = Utils.thumb_path(self.db.getSavePath(),object) + description = object.getDescription() + if len(description) > 20: + description = "%s..." % description[0:20] + + image = gtk.gdk.pixbuf_new_from_file(name) + x = image.get_width() + y = image.get_height() + + grp = self.root.add(gnome.canvas.CanvasGroup,x=self.cx,y=self.cy) + + xloc = (_IMAGEX-x)/2 + yloc = (_IMAGEX-y)/2 + + item = grp.add(gnome.canvas.CanvasPixbuf, + pixbuf=image, + x=xloc, + y=yloc) + text = grp.add(gnome.canvas.CanvasText, + x=_IMAGEX/2, + y=_IMAGEX, + anchor=gtk.ANCHOR_CENTER, + text=description) + + self.cx = 10 + _IMAGEX + self.cx + if self.cx + 10 + _IMAGEX > self.x: + self.cx = 10 + self.cy = self.cy + 10 + _IMAGEY + + item.show() + text.show() + self.canvas_list.append(grp) + self.canvas_list.append(item) + self.canvas_list.append(text) + + def load_images(self): + """clears the currentImages list to free up any cached + Imlibs. Then add each photo in the place's list of photos to the + photolist window.""" + + for item in self.canvas_list: + item.destroy() + + self.pos = 0 + self.cx = 10 + self.cy = 10 + + for photo in self.dataobj.getPhotoList(): + self.add_thumbnail(photo) + + (self.x,self.y) = self.iconlist.get_size() + if self.cy > self.y: + self.iconlist.set_scroll_region(0,0,self.x,self.cy) + else: + self.iconlist.set_scroll_region(0,0,self.x,self.y) + + def on_photo_select_icon(self, obj,iconNumber,event): + """User clicked on a photo. Remember which one.""" + self.selectedIcon = iconNumber + + def on_photolist_drag_data_received(self,w, context, x, y, data, info, time): + import urlparse + if data and data.format == 8: + icon_index = w.get_icon_at(x,y) + d = string.strip(string.replace(data.data,'\0',' ')) + protocol,site,file, j,k,l = urlparse.urlparse(d) + if protocol == "file": + name = file + mime = Utils.get_mime_type(name) + photo = Photo() + photo.setPath(name) + photo.setMimeType(mime) + basename = os.path.basename(name) + (root,ext) = os.path.splitext(basename) + photo.setDescription(root) + self.savephoto(photo) + if GrampsCfg.mediaref == 0: + name = RelImage.import_media_object(name,self.path,photo.getId()) + photo.setPath(name) + photo.setLocal(1) + self.parent.lists_changed = 1 + if GrampsCfg.globalprop: + Utils.modified() + GlobalMediaProperties(self.db,photo,None) + elif protocol != "": + import urllib + u = urllib.URLopener() + try: + tfile,headers = u.retrieve(d) + except IOError, msg: + t = _("Could not import %s") % d + + gnome.ui.GnomeErrorDialog("%s\n%s %d" % (t,msg[0],msg[1])) + return + mime = Utils.get_mime_type(tfile) + photo = Photo() + photo.setMimeType(mime) + photo.setDescription(d) + photo.setLocal(1) + photo.setPath(tfile) + self.db.addObject(photo) + oref = ObjectRef() + oref.setReference(photo) + self.dataobj.addPhoto(oref) + try: + id = photo.getId() + name = RelImage.import_media_object(tfile,self.path,id) + photo.setLocal(1) + photo.setPath(name) + except: + photo.setPath(tfile) + w.drag_finish(context, 1, 0, time) + return + self.add_thumbnail(oref) + self.parent.lists_changed = 1 + if GrampsCfg.globalprop: + Utils.modified() + GlobalMediaProperties(self.db,photo,None) + else: + if self.db.getObjectMap().has_key(data.data): + index = 0 + for p in self.dataobj.getPhotoList(): + if data.data == p.getReference().getId(): + if index == icon_index or icon_index == -1: + w.drag_finish(context, 0, 0, time) + return + else: + w.drag_finish(context, 1, 0, time) + nl = self.dataobj.getPhotoList() + item = nl[index] + if icon_index == 0: + del nl[index] + nl = [item] + nl + else: + del nl[index] + nl = nl[0:icon_index] + [item] + nl[icon_index:] + self.dataobj.setPhotoList(nl) + Utils.modified() + self.parent.lists_changed = 1 + self.load_images() + return + index = index + 1 + oref = ObjectRef() + oref.setReference(self.db.findObjectNoMap(data.data)) + self.dataobj.addPhoto(oref) + self.add_thumbnail(oref) + self.parent.lists_changed = 1 + if GrampsCfg.globalprop: + LocalMediaProperties(oref,self.path,self) + Utils.modified() + w.drag_finish(context, 1, 0, time) + else: + w.drag_finish(context, 0, 0, time) + + def on_photolist_drag_data_get(self,w, context, selection_data, info, time): + if info == 1: + return + if self.selectedIcon != -1: + ref = self.dataobj.getPhotoList()[self.selectedIcon] + id = ref.getReference().getId() + selection_data.set(selection_data.target, 8, id) + + def on_add_photo_clicked(self, obj): + """User wants to add a new photo. Create a dialog to find out + which photo they want.""" + self.create_add_dialog() + + def on_delete_photo_clicked(self, obj): + """User wants to delete a new photo. Remove it from the displayed + thumbnails, and remove it from the dataobj photo list.""" + icon = self.selectedIcon + if icon != -1: + self.icon_list.remove(icon) + list = self.dataobj.getPhotoList() + del list[icon] + self.dataobj.setPhotoList(list) + self.parent.lists_changed = 1 + if len(self.dataobj.getPhotoList()) == 0: + self.selectedIcon = -1 + else: + self.selectedIcon = 0 + self.icon_list.select_icon(0) + + def on_button_press_event(self, obj, event): + """Look for right-clicks on a picture and create a popup + menu of the available actions.""" + icon = self.selectedIcon + if icon == -1: + return + + if event.button == 3: + photo = self.dataobj.getPhotoList()[icon] + menu = gtk.GtkMenu() + item = gtk.GtkTearoffMenuItem() + item.show() + menu.append(item) + Utils.add_menuitem(menu,_("View in the default viewer"), + None,self.popup_view_photo) + object = photo.getReference() + if object.getMimeType()[0:5] == "image": + Utils.add_menuitem(menu,_("Edit with the GIMP"), + None,self.popup_edit_photo) + Utils.add_menuitem(menu,_("Edit Object Properties"),None, + self.popup_change_description) + if object.getLocal() == 0: + Utils.add_menuitem(menu,_("Convert to local copy"),None, + self.popup_convert_to_private) + menu.popup(None,None,None,0,0) + + def popup_view_photo(self, obj): + """Open this picture in a picture viewer""" + photo = self.dataobj.getPhotoList()[self.selectedIcon] + Utils.view_photo(photo.getReference()) + + def popup_edit_photo(self, obj): + """Open this picture in a picture editor""" + photo = self.dataobj.getPhotoList()[self.selectedIcon] + if os.fork() == 0: + os.execvp(const.editor,[const.editor, + photo.getReference().getPath()]) + + def popup_convert_to_private(self, obj): + """Copy this picture into gramps private database instead of + leaving it as an external data object.""" + photo = self.dataobj.getPhotoList()[self.selectedIcon] + object = photo.getReference() + name = RelImage.import_media_object(object.getPath(),self.path, + object.getId()) + object.setPath(name) + object.setLocal(1) + + def popup_change_description(self, obj): + """Bring up a window allowing the user to edit the description + of a picture.""" + if self.selectedIcon >=0: + photo = self.dataobj.getPhotoList()[self.selectedIcon] + LocalMediaProperties(photo,self.path,self) + +#------------------------------------------------------------------------- +# +# LocalMediaProperties +# +#------------------------------------------------------------------------- +class LocalMediaProperties: + + def __init__(self,photo,path,parent): + self.photo = photo + self.object = photo.getReference() + self.alist = photo.getAttributeList()[:] + self.lists_changed = 0 + self.parent = parent + + fname = self.object.getPath() + self.change_dialog = gtk.glade.XML(const.imageselFile, + "change_description") + descr_window = self.change_dialog.get_widget("description") + pixmap = self.change_dialog.get_widget("pixmap") + self.attr_type = self.change_dialog.get_widget("attr_type") + self.attr_value = self.change_dialog.get_widget("attr_value") + self.attr_details = self.change_dialog.get_widget("attr_details") + self.attr_list = self.change_dialog.get_widget("attr_list") + + descr_window.set_text(self.object.getDescription()) + mtype = self.object.getMimeType() + + self.pix = gtk.gdk.pixbuf_new_from_file(path) + pixmap.set_from_pixbuf(self.pix) + + self.change_dialog.get_widget("private").set_active(photo.getPrivacy()) + self.change_dialog.get_widget("gid").set_text(self.object.getId()) + + if self.object.getLocal(): + self.change_dialog.get_widget("path").set_text("") + else: + self.change_dialog.get_widget("path").set_text(fname) + + mt = Utils.get_mime_description(mtype) + self.change_dialog.get_widget("type").set_text(mt) + print self.photo + self.change_dialog.get_widget("notes").get_buffer().set_text(self.photo.getNote()) + self.change_dialog.signal_autoconnect({ + "on_cancel_clicked" : Utils.destroy_passed_object, + "on_up_clicked" : self.on_up_clicked, + "on_down_clicked" : self.on_down_clicked, + "on_ok_clicked" : self.on_ok_clicked, + "on_apply_clicked" : self.on_apply_clicked, + "on_attr_list_select_row" : self.on_attr_list_select_row, + "on_add_attr_clicked": self.on_add_attr_clicked, + "on_delete_attr_clicked" : self.on_delete_attr_clicked, + "on_update_attr_clicked" : self.on_update_attr_clicked, + }) + self.redraw_attr_list() + + def on_up_clicked(self,obj): + if len(obj.selection) == 0: + return + row = obj.selection[0] + if row != 0: + obj.select_row(row-1,0) + + def on_down_clicked(self,obj): + if len(obj.selection) == 0: + return + row = obj.selection[0] + if row != obj.rows-1: + obj.select_row(row+1,0) + + def redraw_attr_list(self): + Utils.redraw_list(self.alist,self.attr_list,disp_attr) + + def on_apply_clicked(self, obj): + priv = self.change_dialog.get_widget("private").get_active() + text = self.change_dialog.get_widget("notes").get_chars(0,-1) + note = self.photo.getNote() + if text != note or priv != self.photo.getPrivacy(): + self.photo.setNote(text) + self.photo.setPrivacy(priv) + self.parent.lists_changed = 1 + Utils.modified() + if self.lists_changed: + self.photo.setAttributeList(self.alist) + self.parent.lists_changed = 1 + Utils.modified() + + def on_ok_clicked(self, obj): + self.on_apply_clicked(obj) + Utils.destroy_passed_object(obj) + + def on_attr_list_select_row(self,obj,row,b,c): + attr = obj.get_row_data(row) + + self.attr_type.set_label(attr.getType()) + self.attr_value.set_text(attr.getValue()) + self.attr_details.set_text(Utils.get_detail_text(attr)) + + def on_update_attr_clicked(self,obj): + import AttrEdit + if len(obj.selection) > 0: + row = obj.selection[0] + attr = obj.get_row_data(row) + AttrEdit.AttributeEditor(self,attr,"Media Object", + Plugins.get_image_attributes()) + + def on_delete_attr_clicked(self,obj): + if Utils.delete_selected(obj,self.alist): + self.lists_changed = 1 + self.redraw_attr_list() + + def on_add_attr_clicked(self,obj): + import AttrEdit + AttrEdit.AttributeEditor(self,None,"Media Object", + Plugins.get_image_attributes()) + +#------------------------------------------------------------------------- +# +# GlobalMediaProperties +# +#------------------------------------------------------------------------- +class GlobalMediaProperties: + + def __init__(self,db,object,update): + self.object = object + self.alist = self.object.getAttributeList()[:] + self.lists_changed = 0 + self.db = db + self.update = update + self.refs = 0 + + self.path = self.db.getSavePath() + self.change_dialog = gtk.glade.XML(const.imageselFile,"change_global") + self.descr_window = self.change_dialog.get_widget("description") + self.notes = self.change_dialog.get_widget("notes") + pixmap = self.change_dialog.get_widget("pixmap") + self.attr_type = self.change_dialog.get_widget("attr_type") + self.attr_value = self.change_dialog.get_widget("attr_value") + self.attr_details = self.change_dialog.get_widget("attr_details") + self.attr_list = self.change_dialog.get_widget("attr_list") + + self.descr_window.set_text(self.object.getDescription()) + mtype = self.object.getMimeType() + pb = gtk.gdk.pixbuf_new_from_file(Utils.thumb_path(self.path,self.object)) + pixmap.set_from_pixbuf(pb) + + self.change_dialog.get_widget("gid").set_text(self.object.getId()) + self.makelocal = self.change_dialog.get_widget("makelocal") + + self.update_info() + + self.change_dialog.get_widget("type").set_text(Utils.get_mime_description(mtype)) + self.notes.get_buffer().set_text(self.object.getNote()) + self.change_dialog.signal_autoconnect({ + "on_cancel_clicked" : Utils.destroy_passed_object, + "on_up_clicked" : self.on_up_clicked, + "on_down_clicked" : self.on_down_clicked, + "on_ok_clicked" : self.on_ok_clicked, + "on_apply_clicked" : self.on_apply_clicked, + "on_attr_list_select_row": self.on_attr_list_select_row, + "on_add_attr_clicked" : self.on_add_attr_clicked, + "on_notebook_switch_page": self.on_notebook_switch_page, + "on_make_local_clicked" : self.on_make_local_clicked, + "on_delete_attr_clicked" : self.on_delete_attr_clicked, + "on_update_attr_clicked" : self.on_update_attr_clicked, + }) + self.redraw_attr_list() + + def on_up_clicked(self,obj): + if len(obj.selection) == 0: + return + row = obj.selection[0] + if row != 0: + obj.select_row(row-1,0) + + def on_down_clicked(self,obj): + if len(obj.selection) == 0: + return + row = obj.selection[0] + if row != obj.rows-1: + obj.select_row(row+1,0) + + def update_info(self): + fname = self.object.getPath() + if self.object.getLocal(): + self.change_dialog.get_widget("path").set_text("") + self.makelocal.set_sensitive(0) + else: + self.change_dialog.get_widget("path").set_text(fname) + self.makelocal.set_sensitive(1) + + def on_make_local_clicked(self, obj): + name = RelImage.import_media_object(self.object.getPath(), + self.path, + self.object.getId()) + self.object.setPath(name) + self.object.setLocal(1) + self.update_info() + if self.update != None: + self.update() + + def redraw_attr_list(self): + Utils.redraw_list(self.alist,self.attr_list,disp_attr) + + def button_press(self,obj,event): + if len(obj.selection) <= 0: + return + if event.button == 1 and event.type == GDK._2BUTTON_PRESS: + data = obj.get_row_data(obj.selection[0]) + if data != None: + data[0](data[1],data[2]) + + def display_refs(self): + if self.refs == 1: + return + self.refs = 1 + index = 0 + ref = self.change_dialog.get_widget("refinfo") + ref.connect('button-press-event',self.button_press) + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + for o in p.getPhotoList(): + if o.getReference() == self.object: + ref.append([_("Person"),p.getId(),GrampsCfg.nameof(p)]) + ref.set_row_data(index,(EditPerson.EditPerson,p,self.db)) + index = index + 1 + for p in self.db.getFamilyMap().values(): + for o in p.getPhotoList(): + if o.getReference() == self.object: + ref.append([_("Family"),p.getId(),Utils.family_name(p)]) + ref.set_row_data(index,(Marriage.Marriage,p,self.db)) + index = index + 1 + for key in self.db.getSourceKeys(): + p = self.db.getSource(key) + for o in p.getPhotoList(): + if o.getReference() == self.object: + ref.append([_("Source"),p.getId(),p.getTitle()]) + ref.set_row_data(index,(EditSource.EditSource,p,self.db)) + index = index + 1 + for key in self.db.getPlaceKeys(): + p = self.db.getPlace(key) + for o in p.getPhotoList(): + if o.getReference() == self.object: + ref.append([_("Place"),p.getId(),p.get_title()]) + ref.set_row_data(index,(EditPlace.EditPlace,p,self.db)) + index = index + 1 + + def on_notebook_switch_page(self,obj,junk,page): + if page == 3: + self.display_refs() + + def on_apply_clicked(self, obj): + text = self.notes.get_chars(0,-1) + desc = self.descr_window.get_text() + note = self.object.getNote() + if text != note or desc != self.object.getDescription(): + self.object.setNote(text) + self.object.setDescription(desc) + Utils.modified() + if self.lists_changed: + self.object.setAttributeList(self.alist) + Utils.modified() + if self.update != None: + self.update() + + def on_ok_clicked(self, obj): + self.on_apply_clicked(obj) + Utils.destroy_passed_object(obj) + + def on_attr_list_select_row(self,obj,row,b,c): + attr = obj.get_row_data(row) + + self.attr_type.set_label(attr.getType()) + self.attr_value.set_text(attr.getValue()) + self.attr_details.set_text(Utils.get_detail_text(attr)) + + def on_update_attr_clicked(self,obj): + import AttrEdit + if len(obj.selection) > 0: + row = obj.selection[0] + attr = obj.get_row_data(row) + AttrEdit.AttributeEditor(self,attr,"Media Object", + Plugins.get_image_attributes()) + + def on_delete_attr_clicked(self,obj): + if Utils.delete_selected(obj,self.alist): + self.lists_changed = 1 + self.redraw_attr_list() + + def on_add_attr_clicked(self,obj): + import AttrEdit + AttrEdit.AttributeEditor(self,None,"Media Object", + Plugins.get_image_attributes()) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def disp_attr(attr): + detail = Utils.get_detail_flags(attr) + return [const.display_pattr(attr.getType()),attr.getValue(),detail] + + +class DeleteMediaQuery: + + def __init__(self,media,db,update): + self.db = db + self.media = media + self.update = update + + def query_response(self): + del self.db.getObjectMap()[self.media.getId()] + Utils.modified() + + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + nl = [] + change = 0 + for photo in p.getPhotoList(): + if photo.getReference() != self.media: + nl.append(photo) + else: + change = 1 + if change: + p.setPhotoList(nl) + + for p in self.db.getFamilyMap().values(): + nl = [] + change = 0 + for photo in p.getPhotoList(): + if photo.getReference() != self.media: + nl.append(photo) + else: + change = 1 + if change: + p.setPhotoList(nl) + + for key in self.db.getSourceKeys(): + p = self.db.getSource(key) + nl = [] + change = 0 + for photo in p.getPhotoList(): + if photo.getReference() != self.media: + nl.append(photo) + else: + change = 1 + if change: + p.setPhotoList(nl) + + for key in self.db.getPlaceKeys(): + p = self.db.getPlace(key) + nl = [] + change = 0 + for photo in p.getPhotoList(): + if photo.getReference() != self.media: + nl.append(photo) + else: + change = 1 + if change: + p.setPhotoList(nl) + + if self.update: + self.update(0) + + diff --git a/gramps2/src/ImgManip.py b/gramps2/src/ImgManip.py new file mode 100644 index 000000000..31d852ff7 --- /dev/null +++ b/gramps2/src/ImgManip.py @@ -0,0 +1,168 @@ +# +# 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 const +import string + +#------------------------------------------------------------------------- +# +# Check for the python imaging library +# +#------------------------------------------------------------------------- +try: + import PIL.Image + import StringIO + PIL.Image.init() + no_pil = 0 +except: + import popen2 +# import GDK +# import GTK + import gtk +# import GdkImlib + no_pil = 1 + +class ImgManip: + def __init__(self,source): + self.src = source + + if no_pil: + + def size(self): + img = GdkImlib.Image(self.src) + return (img.rgb_width,img.rgb_height) + + def fmt_thumbnail(self,dest,width,height,cnv): + w = int(width) + h = int(height) + cmd = "%s -geometry %dx%d '%s' '%s:%s'" % (const.convert,w,h,self.src,cnv,dest) + os.system(cmd) + + def fmt_convert(self,dest,cnv): + cmd = "%s '%s' '%s:%s'" % (const.convert,self.src,cnv,dest) + os.system(cmd) + + def fmt_data(self,cnv): + cmd = "%s '%s' '%s:-'" % (const.convert,self.src,cnv) + r,w = popen2.popen2(cmd) + buf = r.read() + r.close() + w.close() + return buf + + def fmt_scale_data(self,x,y,cnv): + cmd = "%s -geometry %dx%d '%s' '%s:-'" % (const.convert,x,y,self.src,cnv) + r,w = popen2.popen2(cmd) + buf = r.read() + r.close() + w.close() + return buf + + else: + + def size(self): + return PIL.Image.open(self.src).size + + def fmt_thumbnail(self,dest,width,height,pil): + im = PIL.Image.open(self.src) + im.thumbnail((width,height)) + if im.mode != 'RGB': + im.draft('RGB',im.size) + im = im.convert("RGB") + im.save(dest,string.upper(pil)) + + def fmt_convert(self,dest,pil): + im = PIL.Image.open(self.src) + if im.mode != 'RGB': + im.draft('RGB',im.size) + im = im.convert("RGB") + im.save(dest,string.upper(pil)) + + def fmt_data(self,pil): + g = StringIO.StringIO() + im = PIL.Image.open(self.src) + if im.mode != 'RGB': + im.draft('RGB',im.size) + im = im.convert("RGB") + im.save(g,string.upper(pil)) + g.seek(0) + buf = g.read() + g.close() + return buf + + def fmt_scale_data(self,x,y,pil): + im = PIL.Image.open(self.src) + im.thumbnail((x,y)) + if im.mode != 'RGB': + im.draft('RGB',im.size) + im = im.convert("RGB") + return im.tostring(string.upper(pil),"RGB") + + def jpg_thumbnail(self,dest,width,height): + self.fmt_thumbnail(dest,width,height,"jpeg") + + def png_thumbnail(self,dest,width,height): + self.fmt_thumbnail(dest,width,height,"png") + + def eps_thumbnail(self,dest,width,height): + self.fmt_thumbnail(dest,width,height,"eps") + + def jpg_convert(self,dest): + self.fmt_convert(dest,"jpeg") + + def png_convert(self,dest): + self.fmt_convert(dest,"png") + + def eps_convert(self,dest): + self.fmt_convert(dest,"eps") + + def jpg_data(self): + return self.fmt_data("jpeg") + + def png_data(self): + return self.fmt_data("png") + + def eps_data(self): + return self.fmt_data("eps") + + def jpg_scale_data(self,x,y): + return self.fmt_scale_data(x,y,"jpeg") + + def png_scale_data(self,x,y): + return self.fmt_scale_data(x,y,"png") + + def eps_scale_data(self,x,y): + return self.fmt_scale_data(x,y,"eps") + + +if __name__ == "__main__": + + import sys + + img = ImgManip(sys.argv[1]) + img.jpg_thumbnail("foo.jpg",50,50) + img.png_thumbnail("foo.png",50,50) + img.eps_thumbnail("foo.eps",50,50) + + + + + diff --git a/gramps2/src/LocEdit.py b/gramps2/src/LocEdit.py new file mode 100644 index 000000000..72de8afc8 --- /dev/null +++ b/gramps2/src/LocEdit.py @@ -0,0 +1,116 @@ +# +# 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 gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +from RelLib import * + +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# LocationEditor class +# +#------------------------------------------------------------------------- +class LocationEditor: + + def __init__(self,parent,location): + self.parent = parent + self.location = location + self.top = gtk.glade.XML(const.dialogFile, "loc_edit") + self.window = self.top.get_widget("loc_edit") + self.city = self.top.get_widget("city") + self.state = self.top.get_widget("state") + self.parish = self.top.get_widget("parish") + self.county = self.top.get_widget("county") + self.country = self.top.get_widget("country") + + if parent.place: + name = _("Location Editor for %s") % parent.place.get_title() + else: + name = _("Location Editor") + + self.top.get_widget("locationTitle").set_text(name) + + if location != None: + self.city.set_text(location.get_city()) + self.county.set_text(location.get_county()) + self.country.set_text(location.get_country()) + self.state.set_text(location.get_state()) + self.parish.set_text(location.get_parish()) + + self.window.set_data("o",self) + self.top.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_loc_edit_ok_clicked" : self.on_location_edit_ok_clicked + }) + + def on_location_edit_ok_clicked(self,obj): + self.location = self.location + + city = self.city.get_text() + county = self.county.get_text() + country = self.country.get_text() + state = self.state.get_text() + parish = self.parish.get_text() + + if self.location == None: + self.location = Location() + self.parent.llist.append(self.location) + + self.update_location(city,parish,county,state,country) + + self.parent.redraw_location_list() + Utils.destroy_passed_object(obj) + + def update_location(self,city,parish,county,state,country): + if self.location.get_city() != city: + self.location.set_city(city) + self.parent.lists_changed = 1 + + if self.location.get_parish() != parish: + self.location.set_parish(parish) + self.parent.lists_changed = 1 + + if self.location.get_county() != county: + self.location.set_county(county) + self.parent.lists_changed = 1 + + if self.location.get_state() != state: + self.location.set_state(state) + self.parent.lists_changed = 1 + + if self.location.get_country() != country: + self.location.set_country(country) + self.parent.lists_changed = 1 + diff --git a/gramps2/src/Makefile.am b/gramps2/src/Makefile.am new file mode 100644 index 000000000..451a73044 --- /dev/null +++ b/gramps2/src/Makefile.am @@ -0,0 +1,59 @@ +# This is the src level Makefile for Gramps +SUBDIRS = docgen filters plugins data po + +# For intl. support, how do we compile? +CFLAGS = -fPIC -shared -O @CFLAGS@ @CPPFLAGS@ -I@includedir@ +LDFLAGS = @LDFLAGS@ -L@libdir@ @LIBS@ +CLEANFILES = ${INTLLIBS} +MOSTLYCLEANFILES = + +# What are the PYTHON scripts for this package that need to be handled? +# +# We only want optimized byte-compiled (.pyo) versions, no .pyc +# In principle, this is handled by PYCFILES and PYOFILES, but +# they don't seem to work so we edited the py-compile script instead +pkgpython_PYTHON = ${wildcard *.py} + +# Use GNU make's ':=' syntax for nice wildcard use. +# If not using GNU make, then list all files individually +GLADEFILES := ${wildcard *.glade} +GRAPHICS := ${wildcard *.xpm} ${wildcard *.png} ${wildcard *.jpg} + +# Other stuff that we need to install +pkgdata_DATA = ${INTLLIBS} ${GLADEFILES} ${GRAPHICS} gramps.desktop + +#EXTRA_DIST =@DISTLANGS@ + + +all: ${INTLLIBS} + +DIST_SOURCES = intl.c +dist_pkgdata_DATA = ${pkgdata_DATA} + +# These can prbably be done in a better or more elegant/generic way +# eventually (libtool?), but this works. +intl15.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P15_INCLUDES@ -DVER15 -o $@ intl.c +intl20.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P20_INCLUDES@ -DVER20 -o $@ intl.c +intl21.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P21_INCLUDES@ -DVER21 -o $@ intl.c +intl22.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P22_INCLUDES@ -DVER22 -o $@ intl.c + +# In principle the following rule slightly violates the automake/autoconf +# spirit of keeping each subdirectory as a separate entity unto itself. +# But, since the template depends on everything from here, we allow this +# one exception. +trans: po/template.po + ./build_po + +install-data-local: + ${INSTALL} -d ${prefix}/share/pixmaps + ${INSTALL_DATA} gramps.png ${prefix}/share/pixmaps + ${INSTALL} -d ${prefix}/share/gnome/apps/Applications + ${INSTALL_DATA} gramps.desktop ${prefix}/share/gnome/apps/Applications + +uninstall-local: + -rm ${prefix}/share/pixmaps/gramps.png + -rm ${prefix}/share/gnome/apps/Applications/gramps.desktop diff --git a/gramps2/src/Makefile.in b/gramps2/src/Makefile.in new file mode 100644 index 000000000..2ea043f3a --- /dev/null +++ b/gramps2/src/Makefile.in @@ -0,0 +1,478 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +BINSH = @BINSH@ +CC = @CC@ +DEPDIR = @DEPDIR@ +DISABLE_SCROLLKEEPER = @DISABLE_SCROLLKEEPER@ +GNOMEHELP = @GNOMEHELP@ +HAVE_GNOME_CONFIG = @HAVE_GNOME_CONFIG@ +HAVE_JW = @HAVE_JW@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +JW = @JW@ +LANGUAGES = @LANGUAGES@ +LIBS = @LIBS@ +MOFILES = @MOFILES@ +MSGFMT = @MSGFMT@ +P15_INCLUDES = @P15_INCLUDES@ +P20_INCLUDES = @P20_INCLUDES@ +P21_INCLUDES = @P21_INCLUDES@ +P22_INCLUDES = @P22_INCLUDES@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +PYTHON = @PYTHON@ +PYTHON22 = @PYTHON22@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RELEASE = @RELEASE@ +SCROLLKEEPER_CONFIG = @SCROLLKEEPER_CONFIG@ +SCROLLKEEPER_REQUIRED = @SCROLLKEEPER_REQUIRED@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSIONSTRING = @VERSIONSTRING@ +ZIP = @ZIP@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ + +# This is the src level Makefile for Gramps +SUBDIRS = docgen filters plugins data po + +# For intl. support, how do we compile? +CFLAGS = -fPIC -shared -O @CFLAGS@ @CPPFLAGS@ -I@includedir@ +LDFLAGS = @LDFLAGS@ -L@libdir@ @LIBS@ +CLEANFILES = ${INTLLIBS} +MOSTLYCLEANFILES = + +# What are the PYTHON scripts for this package that need to be handled? +# +# We only want optimized byte-compiled (.pyo) versions, no .pyc +# In principle, this is handled by PYCFILES and PYOFILES, but +# they don't seem to work so we edited the py-compile script instead +pkgpython_PYTHON = ${wildcard *.py} + +# Use GNU make's ':=' syntax for nice wildcard use. +# If not using GNU make, then list all files individually +GLADEFILES := ${wildcard *.glade} +GRAPHICS := ${wildcard *.xpm} ${wildcard *.png} ${wildcard *.jpg} + +# Other stuff that we need to install +pkgdata_DATA = ${INTLLIBS} ${GLADEFILES} ${GRAPHICS} gramps.desktop + +DIST_SOURCES = intl.c +dist_pkgdata_DATA = ${pkgdata_DATA} +subdir = src +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = const.py +py_compile = $(top_srcdir)/py-compile +DATA = $(dist_pkgdata_DATA) $(pkgdata_DATA) + + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = README $(dist_pkgdata_DATA) $(pkgpython_PYTHON) AUTHORS \ + ChangeLog Makefile.am Makefile.in NEWS configure.in const.py.in +DIST_SUBDIRS = $(SUBDIRS) +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +const.py: $(top_builddir)/config.status const.py.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +uninstall-info-am: +pkgpythonPYTHON_INSTALL = $(INSTALL_DATA) +install-pkgpythonPYTHON: $(pkgpython_PYTHON) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(pkgpythondir) + @list='$(pkgpython_PYTHON)'; dlist=''; for p in $$list; do\ + if test -f $(srcdir)/$$p; then \ + d=`echo "$$p" | sed -e 's,^.*/,,'`; \ + dlist="$$dlist $$d"; \ + echo " $(pkgpythonPYTHON_INSTALL) $(srcdir)/$$p $(DESTDIR)$(pkgpythondir)/$$d"; \ + $(pkgpythonPYTHON_INSTALL) $(srcdir)/$$p $(DESTDIR)$(pkgpythondir)/$$d; \ + else :; fi; \ + done; \ + PYTHON=$(PYTHON) $(py_compile) --basedir $(DESTDIR)$(pkgpythondir) $$dlist + +uninstall-pkgpythonPYTHON: + @$(NORMAL_UNINSTALL) + list='$(pkgpython_PYTHON)'; for p in $$list; do \ + d=`echo "$$p" | sed -e 's,^.*/,,'`; \ + rm -f $(DESTDIR)$(pkgpythondir)/$$d; \ + rm -f $(DESTDIR)$(pkgpythondir)/$${d}c; \ + rm -f $(DESTDIR)$(pkgpythondir)/$${d}o; \ + done +dist_pkgdataDATA_INSTALL = $(INSTALL_DATA) +install-dist_pkgdataDATA: $(dist_pkgdata_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + @list='$(dist_pkgdata_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(dist_pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f"; \ + $(dist_pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f; \ + done + +uninstall-dist_pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_pkgdata_DATA)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(pkgdatadir)/$$f"; \ + rm -f $(DESTDIR)$(pkgdatadir)/$$f; \ + done +pkgdataDATA_INSTALL = $(INSTALL_DATA) +install-pkgdataDATA: $(pkgdata_DATA) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) + @list='$(pkgdata_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f"; \ + $(pkgdataDATA_INSTALL) $$d$$p $(DESTDIR)$(pkgdatadir)/$$f; \ + done + +uninstall-pkgdataDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgdata_DATA)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(pkgdatadir)/$$f"; \ + rm -f $(DESTDIR)$(pkgdatadir)/$$f; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + $(mkinstalldirs) $(DESTDIR)$(pkgpythondir) $(DESTDIR)$(pkgdatadir) $(DESTDIR)$(pkgdatadir) + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: install-data-local install-dist_pkgdataDATA \ + install-pkgdataDATA install-pkgpythonPYTHON + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-dist_pkgdataDATA uninstall-info-am \ + uninstall-local uninstall-pkgdataDATA uninstall-pkgpythonPYTHON + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-recursive distclean distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-local \ + install-data-recursive install-dist_pkgdataDATA install-exec \ + install-exec-am install-exec-recursive install-info \ + install-info-am install-info-recursive install-man \ + install-pkgdataDATA install-pkgpythonPYTHON install-recursive \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am installdirs-recursive maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive mostlyclean \ + mostlyclean-generic mostlyclean-recursive tags tags-recursive \ + uninstall uninstall-am uninstall-dist_pkgdataDATA \ + uninstall-info-am uninstall-info-recursive uninstall-local \ + uninstall-pkgdataDATA uninstall-pkgpythonPYTHON \ + uninstall-recursive + + +#EXTRA_DIST =@DISTLANGS@ + +all: ${INTLLIBS} + +# These can prbably be done in a better or more elegant/generic way +# eventually (libtool?), but this works. +intl15.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P15_INCLUDES@ -DVER15 -o $@ intl.c +intl20.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P20_INCLUDES@ -DVER20 -o $@ intl.c +intl21.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P21_INCLUDES@ -DVER21 -o $@ intl.c +intl22.so: intl.c + $(CC) $(CFLAGS) $(LDFLAGS) @P22_INCLUDES@ -DVER22 -o $@ intl.c + +# In principle the following rule slightly violates the automake/autoconf +# spirit of keeping each subdirectory as a separate entity unto itself. +# But, since the template depends on everything from here, we allow this +# one exception. +trans: po/template.po + ./build_po + +install-data-local: + ${INSTALL} -d ${prefix}/share/pixmaps + ${INSTALL_DATA} gramps.png ${prefix}/share/pixmaps + ${INSTALL} -d ${prefix}/share/gnome/apps/Applications + ${INSTALL_DATA} gramps.desktop ${prefix}/share/gnome/apps/Applications + +uninstall-local: + -rm ${prefix}/share/pixmaps/gramps.png + -rm ${prefix}/share/gnome/apps/Applications/gramps.desktop +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gramps2/src/Marriage.py b/gramps2/src/Marriage.py new file mode 100644 index 000000000..4401bcf25 --- /dev/null +++ b/gramps2/src/Marriage.py @@ -0,0 +1,567 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2000 Donald N. Allingham +# +# This program is free software; you can redistribute it and/or modiy +# 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 pickle + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk +import gtk.glade +import gnome.ui + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- + +import const +import GrampsCfg +import Utils +import AutoComp +from QuestionDialog import QuestionDialog +from RelLib import * +import ImageSelect +from intl import gettext +_ = gettext + + +_temple_names = const.lds_temple_codes.keys() +_temple_names.sort() +_temple_names = [""] + _temple_names + +pycode_tgts = [('fevent', 0, 0), + ('fattr', 0, 1)] + +#------------------------------------------------------------------------- +# +# Marriage class +# +#------------------------------------------------------------------------- +class Marriage: + + def __init__(self,family,db,callback): + """Initializes the Marriage class, and displays the window""" + self.family = family + self.db = db + self.path = db.getSavePath() + self.cb = callback + self.pmap = {} + + for key in db.getPlaceKeys(): + p = db.getPlaceDisplay(key) + self.pmap[p[0]] = key + + self.top = gtk.glade.XML(const.marriageFile,"marriageEditor") + top_window = self.get_widget("marriageEditor") + self.icon_list = self.get_widget('iconlist') + self.gallery = ImageSelect.Gallery(family, self.path, self.icon_list, db, self) + + self.top.signal_autoconnect({ + "destroy_passed_object" : self.on_cancel_edit, + "on_up_clicked" : self.on_up_clicked, + "on_down_clicked" : self.on_down_clicked, + "on_add_attr_clicked" : self.on_add_attr_clicked, + "on_addphoto_clicked" : self.gallery.on_add_photo_clicked, + "on_attr_list_select_row" : self.on_attr_list_select_row, +# "on_combo_insert_text" : Utils.combo_insert_text, + "on_close_marriage_editor" : self.on_close_marriage_editor, + "on_delete_attr_clicked" : self.on_delete_attr_clicked, + "on_delete_event" : self.on_delete_event, + "on_lds_src_clicked" : self.lds_src_clicked, + "on_lds_note_clicked" : self.lds_note_clicked, + "on_deletephoto_clicked" : self.gallery.on_delete_photo_clicked, + "on_edit_properties_clicked": self.gallery.popup_change_description, + "on_marriageAddBtn_clicked" : self.on_add_clicked, + "on_marriageDeleteBtn_clicked" : self.on_delete_clicked, + "on_marriageEventList_select_row" : self.on_select_row, + "on_marriageUpdateBtn_clicked" : self.on_update_clicked, + "on_photolist_button_press_event" : self.gallery.on_button_press_event, + "on_photolist_select_icon" : self.gallery.on_photo_select_icon, + "on_update_attr_clicked" : self.on_update_attr_clicked, + }) + + text_win = self.get_widget("marriageTitle") + title = _("%s and %s") % (GrampsCfg.nameof(family.getFather()), + GrampsCfg.nameof(family.getMother())) + text_win.set_text(title) + + self.event_list = self.get_widget("marriageEventList") + + # widgets + self.date_field = self.get_widget("marriageDate") + self.place_field = self.get_widget("marriagePlace") + self.cause_field = self.get_widget("marriageCause") + self.name_field = self.get_widget("marriageEventName") + self.descr_field = self.get_widget("marriageDescription") + self.type_field = self.get_widget("marriage_type") + self.notes_field = self.get_widget("marriageNotes") + self.gid = self.get_widget("gid") + self.attr_list = self.get_widget("attr_list") + self.attr_type = self.get_widget("attr_type") + self.attr_value = self.get_widget("attr_value") + self.event_src_field = self.get_widget("event_srcinfo") + self.event_conf_field = self.get_widget("event_conf") + self.attr_src_field = self.get_widget("attr_srcinfo") + self.attr_conf_field = self.get_widget("attr_conf") + self.lds_date = self.get_widget("lds_date") + self.lds_temple = self.get_widget("lds_temple") + self.lds_status = self.get_widget("lds_status") + self.lds_place = self.get_widget("lds_place") + + self.elist = family.getEventList()[:] + self.alist = family.getAttributeList()[:] + self.lists_changed = 0 + + # set initial data + self.gallery.load_images() + + self.event_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING, + gobject.TYPE_STRING) + cnum = 0 + for name in [_('Event'),_('Date'),_('Place')]: + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn(name,renderer,text=cnum) + cnum = cnum + 1 + self.event_list.append_column(column) + self.event_list.set_model(self.event_model) + + self.attr_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING) + cnum = 0 + for name in [_('Attribute'),_('Value')]: + renderer = gtk.CellRendererText() + column = gtk.TreeViewColumn(name,renderer,text=cnum) + cnum = cnum + 1 + self.attr_list.append_column(column) + self.attr_list.set_model(self.attr_model) + + self.addr_model = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING) + + self.type_field.set_popdown_strings(const.familyRelations) + frel = const.display_frel(family.getRelationship()) + self.type_field.entry.set_text(frel) + self.gid.set_text(family.getId()) + self.gid.set_editable(GrampsCfg.id_edit) + + self.lds_temple.set_popdown_strings(_temple_names) + + ord = self.family.getLdsSeal() + if ord: + if ord.getPlace(): + self.lds_place.entry.set_text(ord.getPlace().get_title()) + self.lds_date.set_text(ord.getDate()) + if ord.getTemple() != "": + name = const.lds_temple_to_abrev[ord.getTemple()] + else: + name = "" + self.lds_temple.entry.set_text(name) + self.seal_stat = ord.getStatus() + else: + self.lds_temple.entry.set_text("") + self.seal_stat = 0 + self.autoplace = AutoComp.AutoCombo(self.lds_place,self.pmap.keys()) + + self.build_seal_menu() + + self.event_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, + pycode_tgts,gtk.gdk.ACTION_COPY) + self.event_list.drag_source_set(gtk.gdk.BUTTON1_MASK, + pycode_tgts, gtk.gdk.ACTION_COPY) + self.event_list.connect('drag_data_get', self.ev_source_drag_data_get) + self.event_list.connect('drag_data_received', + self.ev_dest_drag_data_received) + + self.attr_list.drag_dest_set(gtk.DEST_DEFAULT_ALL,pycode_tgts, + gtk.gdk.ACTION_COPY) + self.attr_list.drag_source_set(gtk.gdk.BUTTON1_MASK, pycode_tgts, + gtk.gdk.ACTION_COPY) + self.attr_list.connect('drag_data_get', self.at_source_drag_data_get) + self.attr_list.connect('drag_data_received', + self.at_dest_drag_data_received) + + # set notes data + self.notes_buffer = self.notes_field.get_buffer() + self.notes_buffer.set_text(family.getNote()) + + self.redraw_event_list() + self.redraw_attr_list() + top_window.show() + + def build_seal_menu(self): + menu = gtk.Menu() + index = 0 + for val in const.lds_ssealing: + menuitem = gtk.MenuItem(val) + menuitem.set_data("val",index) + menuitem.connect('activate',self.set_lds_seal) + menuitem.show() + menu.append(menuitem) + index = index + 1 + self.lds_status.set_menu(menu) + self.lds_status.set_history(self.seal_stat) + + def set_lds_seal(self,obj): + self.seal_stat = obj.get_data("val") + + def lds_src_clicked(self,obj): + import Sources + ord = self.family.getLdsSeal() + if ord == None: + ord = LdsOrd() + self.family.setLdsSeal(ord) + Sources.SourceSelector(ord.getSourceRefList(),self) + + def lds_note_clicked(self,obj): + import NoteEdit + ord = self.family.getLdsSeal() + if ord == None: + ord = LdsOrd() + self.family.setLdsSeal(ord) + NoteEdit.NoteEditor(ord) + + def on_up_clicked(self,obj): + if len(obj.selection) == 0: + return + row = obj.selection[0] + if row != 0: + obj.select_row(row-1,0) + + def on_down_clicked(self,obj): + if len(obj.selection) == 0: + return + row = obj.selection[0] + if row != obj.rows-1: + obj.select_row(row+1,0) + + def ev_dest_drag_data_received(self,widget,context,x,y,selection_data,info,time): + if selection_data and selection_data.data: + exec 'data = %s' % selection_data.data + exec 'mytype = "%s"' % data[0] + exec 'family = "%s"' % data[1] + if family == self.family.getId() or mytype != 'fevent': + return + foo = pickle.loads(data[2]); + for src in foo.getSourceRefList(): + base = src.getBase() + newbase = self.db.findSourceNoMap(base.getId()) + src.setBase(newbase) + place = foo.getPlace() + if place: + foo.setPlace(self.db.findPlaceNoMap(place.getId())) + self.elist.append(foo) + self.lists_changed = 1 + self.redraw_event_list() + + def ev_source_drag_data_get(self,widget, context, selection_data, info, time): + ev = widget.get_row_data(widget.focus_row) + + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('fevent',self.family.getId(),pickled)); + selection_data.set(selection_data.target, bits_per, data) + + def at_dest_drag_data_received(self,widget,context,x,y,selection_data,info,time): + if selection_data and selection_data.data: + exec 'data = %s' % selection_data.data + exec 'mytype = "%s"' % data[0] + exec 'family = "%s"' % data[1] + if family == self.family.getId() or mytype != 'fattr': + return + foo = pickle.loads(data[2]); + for src in foo.getSourceRefList(): + base = src.getBase() + newbase = self.db.findSourceNoMap(base.getId()) + src.setBase(newbase) + self.alist.append(foo) + self.lists_changed = 1 + self.redraw_attr_list() + + def at_source_drag_data_get(self,widget, context, selection_data, info, time): + ev = widget.get_row_data(widget.focus_row) + bits_per = 8; # we're going to pass a string + pickled = pickle.dumps(ev); + data = str(('fattr',self.family.getId(),pickled)); + selection_data.set(selection_data.target, bits_per, data) + + #------------------------------------------------------------------------- + # + # + # + #------------------------------------------------------------------------- + def update_lists(self): + self.family.setEventList(self.elist) + self.family.setAttributeList(self.alist) + + def redraw_attr_list(self): + Utils.redraw_list(self.alist,self.attr_model,disp_attr) + + def redraw_event_list(self): + Utils.redraw_list(self.elist,self.event_model,disp_event) + + def get_widget(self,name): + return self.top.get_widget(name) + + def did_data_change(self): + changed = 0 + relation = self.type_field.entry.get_text() + if const.save_frel(relation) != self.family.getRelationship(): + changed = 1 + + text = self.notes_buffer.get_text(self.notes_buffer.get_start_iter(), + self.notes_buffer.get_end_iter(),gtk.FALSE) + if text != self.family.getNote(): + changed = 1 + + if self.lists_changed: + changed = 1 + + idval = self.gid.get_text() + if self.family.getId() != idval: + changed = 1 + + date = self.lds_date.get_text() + temple = self.lds_temple.entry.get_text() + if const.lds_temple_codes.has_key(temple): + temple = const.lds_temple_codes[temple] + else: + temple = "" + + place = Utils.get_place_from_list(self.lds_place) + + ord = self.family.getLdsSeal() + if not ord: + if date or temple or place or self.seal_stat: + changed = 1 + else: + d = Date() + d.set(date) + if compare_dates(d,ord.getDateObj()) != 0 or \ + ord.getTemple() != temple or \ + ord.getPlace() != place or \ + ord.getStatus() != self.seal_stat: + changed = 1 + + return changed + + def cancel_callback(self): + Utils.destroy_passed_object(self.quit) + + def on_cancel_edit(self,obj): + + if self.did_data_change(): + global quit + self.quit = obj + QuestionDialog(_('Abandon Changes'), + _("Data was modified. Are you sure you " + "want to abandon your changes?"), + _('Abandon Changes'),self.cancel_callback, + _('Continue Editing')) + else: + Utils.destroy_passed_object(obj) + + def on_delete_event(self,obj,b): + self.on_cancel_edit(obj) + + def on_close_marriage_editor(self,obj): + idval = self.gid.get_text() + family = self.family + if idval != family.getId(): + m = self.db.getFamilyMap() + if not m.has_key(idval): + if m.has_key(family.getId()): + del m[family.getId()] + m[idval] = family + family.setId(idval) + Utils.modified() + else: + msg1 = _("GRAMPS ID value was not changed.") + GnomeWarningDialog("%s" % msg1) + + relation = self.type_field.entry.get_text() + father = self.family.getFather() + mother = self.family.getMother() + if father and mother: + if const.save_frel(relation) != self.family.getRelationship(): + if father.getGender() == mother.getGender(): + self.family.setRelationship("Partners") + else: + val = const.save_frel(relation) + if val == "Partners": + val = "Unknown" + if father.getGender() == Person.female or \ + mother.getGender() == Person.male: + self.family.setFather(mother) + self.family.setMother(father) + self.family.setRelationship(val) + Utils.modified() + + text = self.notes_buffer.get_text(self.notes_buffer.get_start_iter(), + self.notes_buffer.get_end_iter(),gtk.FALSE) + if text != self.family.getNote(): + self.family.setNote(text) + Utils.modified() + + date = self.lds_date.get_text() + temple = self.lds_temple.entry.get_text() + if const.lds_temple_codes.has_key(temple): + temple = const.lds_temple_codes[temple] + else: + temple = "" + place = Utils.get_place_from_list(self.lds_place) + + ord = self.family.getLdsSeal() + if not ord: + if date or temple or place or self.seal_stat: + ord = LdsOrd() + ord.setDate(date) + ord.setTemple(temple) + ord.setStatus(self.seal_stat) + ord.setPlace(place) + self.family.setLdsSeal(ord) + Utils.modified() + else: + d = Date() + d.set(date) + if compare_dates(d,ord.getDateObj()) != 0: + ord.setDateObj(d) + Utils.modified() + if ord.getTemple() != temple: + ord.setTemple(temple) + Utils.modified() + if ord.getStatus() != self.seal_stat: + ord.setStatus(self.seal_stat) + Utils.modified() + if ord.getPlace() != place: + ord.setPlace(place) + Utils.modified() + + Utils.destroy_passed_object(self.get_widget("marriageEditor")) + + self.update_lists() + if self.lists_changed: + Utils.modified() + + def on_add_clicked(self,obj): + import EventEdit + name = Utils.family_name(self.family) + EventEdit.EventEditor(self,name,const.marriageEvents, + const.save_pevent,None,None,0,self.cb) + + def on_update_clicked(self,obj): + import EventEdit + if len(obj.selection) <= 0: + return + + event = obj.get_row_data(obj.selection[0]) + name = Utils.family_name(self.family) + EventEdit.EventEditor(self,name,const.marriageEvents, + const.save_pevent,event,None,0,self.cb) + + def on_delete_clicked(self,obj): + if Utils.delete_selected(obj,self.elist): + self.lists_changed = 1 + self.redraw_event_list() + + def on_select_row(self,obj,row,b,c): + event = obj.get_row_data(row) + + self.date_field.set_text(event.getDate()) + self.place_field.set_text(event.getPlaceName()) + self.cause_field.set_text(event.getCause()) + self.name_field.set_label(const.display_fevent(event.getName())) + if len(event.getSourceRefList()) > 0: + psrc = event.getSourceRefList()[0] + self.event_src_field.set_text(psrc.getBase().getTitle()) + self.event_conf_field.set_text(const.confidence[psrc.getConfidence()]) + else: + self.event_src_field.set_text('') + self.event_conf_field.set_text('') + self.descr_field.set_text(event.getDescription()) + + def on_attr_list_select_row(self,obj,row,b,c): + attr = obj.get_row_data(row) + + self.attr_type.set_label(const.display_fattr(attr.getType())) + self.attr_value.set_text(attr.getValue()) + if len(attr.getSourceRefList()) > 0: + psrc = attr.getSourceRefList()[0] + self.attr_src_field.set_text(psrc.getBase().getTitle()) + self.attr_conf_field.set_text(const.confidence[psrc.getConfidence()]) + else: + self.attr_src_field.set_text('') + self.attr_conf_field.set_text('') + + def on_update_attr_clicked(self,obj): + import AttrEdit + if len(obj.selection) > 0: + row = obj.selection[0] + attr = obj.get_row_data(row) + father = self.family.getFather() + mother = self.family.getMother() + if father and mother: + name = _("%s and %s") % (father.getPrimaryName().getName(), + mother.getPrimaryName().getName()) + elif father: + name = father.getPrimaryName().getName() + else: + name = mother.getPrimaryName().getName() + AttrEdit.AttributeEditor(self,attr,name,const.familyAttributes) + + def on_delete_attr_clicked(self,obj): + if Utils.delete_selected(obj,self.alist): + self.lists_changed = 1 + self.redraw_attr_list() + + def on_add_attr_clicked(self,obj): + import AttrEdit + father = self.family.getFather() + mother = self.family.getMother() + if father and mother: + name = _("%s and %s") % (father.getPrimaryName().getName(), + mother.getPrimaryName().getName()) + elif father: + name = father.getPrimaryName().getName() + else: + name = mother.getPrimaryName().getName() + AttrEdit.AttributeEditor(self,None,name,const.familyAttributes) + + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def disp_attr(attr): + return [const.display_fattr(attr.getType()),attr.getValue()] + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +def disp_event(event): + return [const.display_fevent(event.getName()), + event.getQuoteDate(), + event.getPlaceName()] + diff --git a/gramps2/src/MediaView.py b/gramps2/src/MediaView.py new file mode 100644 index 000000000..ba6421860 --- /dev/null +++ b/gramps2/src/MediaView.py @@ -0,0 +1,356 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2001 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 string + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gobject +import gtk +import gtk.gdk + +import ImageSelect + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +from RelLib import * +from QuestionDialog import QuestionDialog +import Utils +import os +import GrampsCfg +import const +import RelImage + +#------------------------------------------------------------------------- +# +# internationalization +# +#------------------------------------------------------------------------- +from intl import gettext as _ + +_column_headers = [(_('Title'),4,350), (_('ID'),1,50), (_('Type'),2,70), + ('Path',3,150), ('',4,0) ] + +#------------------------------------------------------------------------- +# +# MediaView +# +#------------------------------------------------------------------------- +class MediaView: + def __init__(self,db,glade,update): + self.db = db + self.list = glade.get_widget("media_list") + self.mid = glade.get_widget("mid") + self.mtype = glade.get_widget("mtype") + self.mdesc = glade.get_widget("mdesc") + self.mpath = glade.get_widget("mpath") + self.mdetails = glade.get_widget("mdetails") + self.preview = glade.get_widget("preview") + + self.id2col = {} + self.selection = self.list.get_selection() + + colno = 0 + for title in _column_headers: + renderer = gtk.CellRendererText () + column = gtk.TreeViewColumn (title[0], renderer, text=colno) + colno = colno + 1 + column.set_clickable (gtk.TRUE) + if title[0] == '': + column.set_visible(gtk.FALSE) + else: + column.set_resizable(gtk.TRUE) + column.set_visible(gtk.TRUE) + column.set_sort_column_id(title[1]) + column.set_min_width(title[2]) + self.list.append_column(column) + + self.list.set_search_column(0) + self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.list.set_model(self.model) + self.list.get_column(0).clicked() + + t = [ ('STRING', 0, 0), + ('text/plain',0,0), + ('text/uri-list',0,2), + ('application/x-rootwin-drop',0,1)] + + self.list.drag_source_set(gtk.gdk.BUTTON1_MASK|gtk.gdk.BUTTON3_MASK, + t,gtk.gdk.ACTION_COPY) + self.list.drag_dest_set(gtk.DEST_DEFAULT_ALL, + t,gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_MOVE) + + self.update = update + self.list.connect('button-press-event',self.on_button_press_event) + self.selection.connect('changed',self.on_select_row) + + def change_db(self,db): + self.db = db + + def on_select_row(self,obj): + fexists = 1 + + store,iter = self.selection.get_selected() + id = store.get_value(iter,1) + + mobj = self.db.findObjectNoMap(id) + type = mobj.getMimeType() + type_name = Utils.get_mime_description(type) + path = mobj.getPath() + thumb_path = Utils.thumb_path(self.db.getSavePath(),mobj) + pexists = os.path.exists(path) + if pexists and os.path.exists(thumb_path): + self.preview.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(thumb_path)) + else: + self.preview.set_from_pixbuf(Utils.find_icon(type)) + if not pexists: + fexists = 0 + + self.mid.set_text(mobj.getId()) + self.mtype.set_text(type_name) + self.mdesc.set_text(mobj.getDescription()) + if len(path) == 0 or fexists == 0: + self.mpath.set_text(_("The file no longer exists")) + elif path[0] == "/": + self.mpath.set_text(path) + else: + self.mpath.set_text("") + self.mdetails.set_text(Utils.get_detail_text(mobj,0)) + + def on_button_press_event(self,obj,event): + store,iter = self.selection.get_selected() + if not iter: + return + id = store.get_value(iter,1) + + object = self.db.findObjectNoMap(id) + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + ImageSelect.GlobalMediaProperties(self.db,object,self.load_media) + elif event.button == 3: + menu = gtk.Menu() + item = gtk.TearoffMenuItem() + item.show() + menu.append(item) + self.obj = object + Utils.add_menuitem(menu,_("View in the default viewer"),None,self.popup_view_photo) + if object.getMimeType()[0:5] == "image": + Utils.add_menuitem(menu,_("Edit with the GIMP"),\ + None,self.popup_edit_photo) + Utils.add_menuitem(menu,_("Edit Object Properties"),None, + self.popup_change_description) + if object.getLocal() == 0: + Utils.add_menuitem(menu,_("Convert to local copy"),None, + self.popup_convert_to_private) + menu.popup(None,None,None,0,0) + + def popup_view_photo(self, obj): + Utils.view_photo(self.obj) + + def popup_edit_photo(self, obj): + if os.fork() == 0: + os.execvp(const.editor,[const.editor, self.obj.getPath()]) + + def popup_convert_to_private(self, obj): + path = self.db.getSavePath() + id = self.obj.getId() + name = RelImage.import_object(self.obj.getPath(),path,id) + if name: + self.obj.setPath(name) + self.obj.setLocal(1) + + def popup_change_description(self, obj): + ImageSelect.GlobalMediaProperties(self.db,self.obj,self.load_media) + + def load_media(self): + self.model.clear() + self.id2col = {} + + objects = self.db.getObjectMap().values() + + for src in objects: + title = src.getDescription() + id = src.getId() + type = Utils.get_mime_description(src.getMimeType()) + if src.getLocal(): + path = "" + else: + path = src.getPath() + details = Utils.get_detail_flags(src,0) + stitle = string.upper(title) + + iter = self.model.append() + self.id2col[id] = iter + self.model.set(iter, 0, title, 1, id, 2, type, 3, path, 4, stitle) + +# if index > 0: +# self.list.select_row(current_row,0) +# self.list.moveto(current_row) +# self.preview.show() +# else: +# self.mid.set_text("") +# self.mtype.set_text("") +# self.mdesc.set_text("") +# self.mpath.set_text("") +# self.mdetails.set_text("") +# self.preview.hide() + +# if current_row < self.list.rows: +# self.list.moveto(current_row) +# else: +# self.list.moveto(0) +# self.list.thaw() + + def create_add_dialog(self,obj): + """Add a new media object to the media list""" + import AddMedia + AddMedia.AddMediaObject(self.db,self.load_media) + + def on_edit_media_clicked(self,obj): + """Edit the properties of an existing media object in the media list""" + if len(self.list.selection) <= 0: + return + object = self.list.get_row_data(self.list.selection[0]) + ImageSelect.GlobalMediaProperties(self.db,object,self.load_media) + + def on_delete_clicked(self,obj): + if len(self.list.selection) <= 0: + return + else: + index = self.list.selection[0] + mobj = self.list.get_row_data(index) + if self.is_object_used(mobj): + ans = ImageSelect.DeleteMediaQuery(mobj,self.db,self.update) + QuestionDialog(_('Delete Object'), + _("This media object is currently being used. " + "Delete anyway?"), + _('Delete Object'),ans.query_response, + _('Keep Object')) + else: + map = self.db.getObjectMap() + del map[mobj.getId()] + Utils.modified() + self.update(0) + + def is_media_object_used(self,mobj): + for p in self.db.getFamilyMap().values(): + for o in p.getPhotoList(): + if o.getReference() == mobj: + return 1 + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + for o in p.getPhotoList(): + if o.getReference() == mobj: + return 1 + for key in self.db.getSourceKeys(): + p = self.db.getSource(key) + for o in p.getPhotoList(): + if o.getReference() == mobj: + return 1 + for key in self.db.getPlaceKeys(): + p = self.db.getPlace(key) + for o in p.getPhotoList(): + if o.getReference() == mobj: + return 1 + return 0 + + def on_drag_data_get(self,w, context, selection_data, info, time): + if info == 1: + return + d = w.get_row_data(w.focus_row) + id = d.getId() + selection_data.set(selection_data.target, 8, id) + + def on_drag_data_received(self,w, context, x, y, data, info, time): + import urlparse + if data and data.format == 8: + d = string.strip(string.replace(data.data,'\0',' ')) + protocol,site,file, j,k,l = urlparse.urlparse(d) + if protocol == "file": + name = file + mime = Utils.get_mime_type(name) + photo = Photo() + photo.setPath(name) + photo.setMimeType(mime) + description = os.path.basename(name) + photo.setDescription(description) + self.db.addObject(photo) + Utils.modified() + w.drag_finish(context, 1, 0, time) + self.load_media() + if GrampsCfg.mediaref == 0: + name = RelImage.import_media_object(name, + self.db.getSavePath(), + photo.getId()) + if name: + photo.setPath(name) + photo.setLocal(1) + Utils.modified() + if GrampsCfg.globalprop: + ImageSelect.GlobalMediaProperties(self.db,photo,self.load_media) + elif protocol != "": + import urllib + u = urllib.URLopener() + try: + tfile,headers = u.retrieve(d) + except IOError, msg: + t = _("Could not import %s") % d + + gnome.ui.GnomeErrorDialog("%s\n%s %d" % (t,msg[0],msg[1])) + return + mime = Utils.get_mime_type(tfile) + photo = Photo() + photo.setMimeType(mime) + photo.setDescription(d) + photo.setLocal(1) + photo.setPath(tfile) + self.db.addObject(photo) + oref = ObjectRef() + oref.setReference(photo) + try: + id = photo.getId() + path = self.db.getSavePath() + name = RelImage.import_media_object(tfile,path,id) + if name: + photo.setLocal(1) + photo.setPath(name) + except: + photo.setPath(tfile) + w.drag_finish(context, 1, 0, time) + return + Utils.modified() + if GrampsCfg.globalprop: + ImageSelect.GlobalMediaProperties(self.db,photo,None) + else: + w.drag_finish(context, 0, 0, time) + + diff --git a/gramps2/src/MergeData.py b/gramps2/src/MergeData.py new file mode 100644 index 000000000..8fa2b43db --- /dev/null +++ b/gramps2/src/MergeData.py @@ -0,0 +1,881 @@ +# +# 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 RelLib +import Utils +import GrampsCfg +import const + +from intl import gettext +_ = gettext + +import string +import gtk.glade + +#------------------------------------------------------------------------- +# +# Merge People +# +#------------------------------------------------------------------------- +class MergePeople: + + def __init__(self,db,person1,person2,update,ep_update=None): + self.db = db + self.p1 = person1 + self.p2 = person2 + self.update = update + self.ep_update = ep_update + + self.glade = gtk.glade.XML(const.mergeFile,"merge") + self.top = self.glade.get_widget("merge") + self.altname = self.glade.get_widget("altname") + self.altbirth = self.glade.get_widget("altbirth") + self.altdeath = self.glade.get_widget("altdeath") + self.family_list = db.getFamilyMap().values() + + self.glade.signal_autoconnect({ + "on_merge_clicked" : self.on_merge_clicked, + "on_next_clicked" : self.on_merge_edit_clicked, + "destroy_passed_object" : Utils.destroy_passed_object, + }) + + fname = GrampsCfg.nameof(person1) + mname = GrampsCfg.nameof(person2) + label_text = "Merge %s and %s" % (fname,mname) + self.glade.get_widget("progress").set_text(label_text) + f1 = person1.getMainParents() + f2 = person2.getMainParents() + + name1 = GrampsCfg.nameof(person1) + death1 = person1.getDeath().getDate() + dplace1 = self.place_name(person1.getDeath()) + birth1 = person1.getBirth().getDate() + bplace1 = self.place_name(person1.getBirth()) + + name2 = GrampsCfg.nameof(person2) + death2 = person2.getDeath().getDate() + dplace2 = self.place_name(person2.getDeath()) + birth2 = person2.getBirth().getDate() + bplace2 = self.place_name(person2.getBirth()) + + if f2 and not f1: + self.glade.get_widget("bfather2").set_active(1) + else: + self.glade.get_widget("bfather1").set_active(1) + + if f1: + father1 = name_of(f1.getFather()) + mother1 = name_of(f1.getMother()) + else: + father1 = "" + mother1 = "" + + if f2: + father2 = name_of(f2.getFather()) + mother2 = name_of(f2.getMother()) + else: + father2 = "" + mother2 = "" + + self.set_field(self.glade.get_widget("id1_text"),person1.getId()) + self.set_field(self.glade.get_widget("id2_text"),person2.getId()) + self.set_field(self.glade.get_widget("name1_text"),name1) + self.set_field(self.glade.get_widget("name2_text"),name2) + + self.bname1 = self.glade.get_widget("bname1") + self.bname1.set_active(1) + + self.set_field(self.glade.get_widget("birth1_text"),birth1) + self.set_field(self.glade.get_widget("birth2_text"),birth2) + self.set_field(self.glade.get_widget("bplace1_text"),bplace1) + self.set_field(self.glade.get_widget("bplace2_text"),bplace2) + + if ((not birth1 and not bplace1) and (birth2 or bplace2) or + (not birth1 or not bplace1) and (birth2 and bplace2)): + self.glade.get_widget('bbirth2').set_active(1) + else: + self.glade.get_widget('bbirth1').set_active(1) + + if ((not death1 and not dplace1) and (death2 or dplace2) or + (not death1 or not dplace1) and (death2 and dplace2)): + self.glade.get_widget('death2').set_active(1) + else: + self.glade.get_widget('death1').set_active(1) + + self.set_field(self.glade.get_widget("death1_text"),death1) + self.set_field(self.glade.get_widget("dplace1_text"),dplace1) + self.set_field(self.glade.get_widget("death2_text"),death2) + self.set_field(self.glade.get_widget("dplace2_text"),dplace2) + + self.set_field(self.glade.get_widget("father1"),father1) + self.set_field(self.glade.get_widget("father2"),father2) + self.set_field(self.glade.get_widget("mother1"),mother1) + self.set_field(self.glade.get_widget("mother2"),mother2) + + self.build_spouse_list(person1,self.glade.get_widget('spouse1')) + self.build_spouse_list(person2,self.glade.get_widget('spouse2')) + + if name1 != name2: + self.altname.set_sensitive(1) + self.altname.set_active(1) + else: + self.altname.set_sensitive(0) + self.altname.set_active(0) + + if birth1 and birth2 and birth1 != birth2: + self.altbirth.set_active(1) + if bplace1 and bplace2 or bplace1 != bplace2: + self.altbirth.set_active(1) + else: + self.altbirth.set_active(0) + + if death1 and death2 and death1 != death2: + self.altdeath.set_active(1) + if dplace1 and dplace2 or dplace1 != dplace2: + self.altdeath.set_active(1) + else: + self.altdeath.set_active(0) + + def build_spouse_list(self,person,widget): + plist = person.getFamilyList() + + length = min(len(plist),3) + widget.clear() + for index in range(0,3): + if index < length and plist[index]: + if person.getGender() == RelLib.Person.male: + spouse = plist[index].getMother() + else: + spouse = plist[index].getFather() + + if spouse == None: + name = "unknown" + else: + sname = GrampsCfg.nameof(spouse) + name = "%s (%s)" % (sname,spouse.getId()) + widget.append([name]) + + def set_field(self,widget,value): + """Sets the string of the entry field at positions it a space 0""" + widget.set_text(value) + widget.set_position(0) + + def place_name(self,event): + place = event.getPlace() + if place: + return "%s (%s)" % (place.get_title(),place.getId()) + else: + return "" + + def empty(self,junk): + pass + + def on_merge_edit_clicked(self,obj): + import EditPerson + self.on_merge_clicked(obj) + # This needs to be fixed to provide an update call + EditPerson.EditPerson(self.p1,self.db,self.ep_update) + + def copy_note(self,one,two): + if one.getNote() != two.getNote(): + one.setNote("%s\n\n%s" % (one.getNote(),two.getNote())) + + def copy_sources(self,one,two): + slist = one.getSourceRefList()[:] + for xsrc in two.getSourceRefList(): + for src in slist: + if src.are_equal(xsrc): + break + else: + one.addSourceRef(xsrc) + + def on_merge_clicked(self,obj): + Utils.modified() + + list = self.p1.getAlternateNames()[:] + for xdata in self.p2.getAlternateNames(): + for data in list: + if data.are_equal(xdata): + self.copy_note(xdata,data) + self.copy_sources(xdata,data) + break + else: + self.p1.addAlternateName(xdata) + + list = self.p1.getAttributeList()[:] + for xdata in self.p2.getAttributeList(): + for data in list: + if data.getType() == xdata.getType() and \ + data.getValue() == xdata.getValue(): + self.copy_note(xdata,data) + self.copy_sources(xdata,data) + break + else: + self.p1.addAttribute(xdata) + + list = self.p1.getEventList()[:] + for xdata in self.p2.getEventList(): + for data in list: + if data.are_equal(xdata): + self.copy_note(xdata,data) + self.copy_sources(xdata,data) + break + else: + self.p1.addEvent(xdata) + + list = self.p1.getUrlList()[:] + for xdata in self.p2.getUrlList(): + for data in list: + if data.are_equal(xdata): + break + else: + self.p1.addUrl(xdata) + + self.id2 = self.glade.get_widget("id2") + old_id = self.p1.getId() + if self.id2.get_active(): + self.p1.setId(self.p2.getId()) + + if self.bname1.get_active(): + if self.altname.get_active(): + self.p1.addAlternateName(self.p2.getPrimaryName()) + else: + if self.altname.get_active(): + self.p1.addAlternateName(self.p1.getPrimaryName()) + self.p1.setPrimaryName(self.p2.getPrimaryName()) + + alt = self.glade.get_widget("altbirth").get_active() + if self.glade.get_widget("bbirth2").get_active(): + if alt: + event = self.p1.getBirth() + event.setName("Alternate Birth") + self.p1.addEvent(event) + self.p1.setBirth(self.p2.getBirth()) + else: + if alt: + event = self.p2.getBirth() + event.setName("Alternate Birth") + self.p1.addEvent(event) + + alt = self.glade.get_widget("altdeath").get_active() + if self.glade.get_widget("bbirth2").get_active(): + if alt: + event = self.p1.getDeath() + event.setName("Alternate Death") + self.p1.addEvent(event) + self.p1.setDeath(self.p2.getDeath()) + else: + if alt: + event = self.p2.getDeath() + event.setName("Alternate Death") + self.p1.addEvent(event) + + if self.glade.get_widget("bfather2").get_active(): + orig_family = self.p1.getMainParents() + if orig_family: + orig_family.removeChild(self.p1) + + source_family = self.p2.getMainParents() + self.p1.setMainParents(source_family) + + if source_family: + if self.p2 in source_family.getChildList(): + source_family.removeChild(self.p2) + if self.p1 not in source_family.getChildList(): + source_family.addChild(self.p1) + else: + source_family = self.p2.getMainParents() + if source_family: + source_family.removeChild(self.p2) + self.p2.setMainParents(None) + + self.merge_families() + + for photo in self.p2.getPhotoList(): + self.p1.addPhoto(photo) + + if self.p1.getNickName() == "": + self.p1.setNickName(self.p2.getNickName()) + + if self.p2.getNote() != "": + old_note = self.p1.getNote() + if old_note: + old_note = old_note + "\n\n" + self.p1.setNote(old_note + self.p2.getNote()) + + try: + self.db.removePerson(self.p2.getId()) + self.db.buildPersonDisplay(self.p1.getId(),old_id) + except: + print "%s is not in the person map!" % (GrampsCfg.nameof(self.p2)) + self.update(self.p1,self.p2,old_id) + Utils.destroy_passed_object(self.top) + + def find_family(self,family): + if self.p1.getGender() == RelLib.Person.male: + mother = family.getMother() + father = self.p1 + else: + father = family.getFather() + mother = self.p1 + + 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.p2.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.p1.getFamilyList(): + continue + + tgt_family = self.find_family(src_family) + + # + # This is the case where a new family to be added to the + # p1 as a result of the merge already exists as a + # family. In this case, we need to remove the old source + # family (with the pre-merge identity of the p1) from + # both the parents + # + if tgt_family in self.p1.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 + + for child in src_family.getChildList(): + if child not in tgt_family.getChildList(): + parents = child.getParentList() + tgt_family.addChild(child) + if child.getMainParents() == src_family: + child.setMainParents(tgt_family) + i = 0 + for fam in parents[:]: + if fam[0] == src_family: + parents[i] = (tgt_family,fam[1],fam[2]) + i = i + 1 + + # 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 p2 family, and delete the family. Not sure + # what to do about marriage/divorce date/place yet. + + # transfer child to new family, alter children to + # point to the correct family + + for child in src_family.getChildList(): + if child not in tgt_family.getChildList(): + parents = child.getParentList() + tgt_family.addChild(child) + if child.getMainParents() == src_family: + child.setMainParents(tgt_family) + i = 0 + for fam in parents[:]: + if fam[0] == src_family: + parents[i] = (tgt_family,fam[1],fam[2]) + i = i + 1 + + # add family events from the old to the new + for event in src_family.getEventList(): + tgt_family.addEvent(event) + + # 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: + if src_family not in self.p1.getFamilyList(): + self.p1.addFamily(src_family) + if self.p1.getGender() == RelLib.Person.male: + src_family.setFather(self.p1) + else: + src_family.setMother(self.p1) + self.remove_marriage(src_family,self.p2) + + # a little debugging here + + for fam in self.db.getFamilyMap().values(): + if self.p2 in fam.getChildList(): + fam.removeChild(self.p2) + fam.addChild(self.p1) + if self.p2 == fam.getFather(): + fam.setFather(self.p1) + if self.p2 == fam.getMother(): + fam.setMother(self.p1) + if fam.getFather() == None and fam.getMother() == None: + self.delete_empty_family(fam) + + def remove_marriage(self,family,person): + if person: + person.removeFamily(family) + if family.getFather() == None and family.getMother() == None: + self.delete_empty_family(family) + + def delete_empty_family(self,family): + for child in family.getChildList(): + if child.getMainParents() == family: + child.setMainParents(None) + else: + child.removeAltFamily(family) + self.db.deleteFamily(family) + +def compare_people(p1,p2): + + name1 = p1.getPrimaryName() + name2 = p2.getPrimaryName() + + chance = name_match(name1,name2) + if chance == -1.0 : + return -1.0 + + birth1 = p1.getBirth() + death1 = p1.getDeath() + birth2 = p2.getBirth() + death2 = p2.getDeath() + + value = date_match(birth1.getDateObj(),birth2.getDateObj()) + if value == -1.0 : + return -1.0 + chance = chance + value + + value = date_match(death1.getDateObj(),death2.getDateObj()) + if value == -1.0 : + return -1.0 + chance = chance + value + + value = place_match(birth1.getPlace(),birth2.getPlace()) + if value == -1.0 : + return -1.0 + chance = chance + value + + value = place_match(death1.getPlace(),death2.getPlace()) + if value == -1.0 : + return -1.0 + chance = chance + value + + ancestors = [] + ancestors_of(p1,ancestors) + if p2 in ancestors: + return -1.0 + + ancestors = [] + ancestors_of(p2,ancestors) + if p1 in ancestors: + return -1.0 + + f1 = p1.getMainParents() + f2 = p2.getMainParents() + + if f1 and f1.getFather(): + dad1 = f1.getFather().getPrimaryName() + else: + dad1 = None + + if f2 and f2.getFather(): + dad2 = f2.getFather().getPrimaryName() + else: + dad2 = None + + value = name_match(dad1,dad2) + + if value == -1.0: + return -1.0 + + chance = chance + value + + if f1 and f1.getMother(): + mom1 = f1.getMother().getPrimaryName() + else: + mom1 = None + + if f2 and f2.getMother(): + mom2 = f2.getMother().getPrimaryName() + else: + mom2 = None + + value = name_match(mom1,mom2) + if value == -1.0: + return -1.0 + + 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.0 + else: + fname1 = GrampsCfg.nameof(father1) + fname2 = GrampsCfg.nameof(father2) + value = name_match(fname1,fname2) + if value != -1.0: + chance = chance + value + else: + mother1 = f1.getMother() + mother2 = f2.getMother() + if mother1 and mother2: + if mother1 == mother2: + chance = chance + 1.0 + else: + mname1 = GrampsCfg.nameof(mother1) + mname2 = GrampsCfg.nameof(mother2) + value = name_match(mname1,mname2) + if value != -1.0: + chance = chance + value + + return chance + +#----------------------------------------------------------------- +# +# +# +#----------------------------------------------------------------- +def name_compare(s1,s2): + return s1 == s2 + +#----------------------------------------------------------------- +# +# +# +#----------------------------------------------------------------- +def date_match(date1,date2): + if date1.getDate() == "" or date2.getDate() == "": + return 0.0 + if date1.getDate() == date2.getDate(): + return 1.0 + + if date1.isRange() or date2.isRange(): + return range_compare(date1,date2) + + date1 = date1.get_start_date() + date2 = date2.get_start_date() + + if date1.getYear() == date2.getYear(): + if date1.getMonth() == date2.getMonth(): + return 0.75 + if not date1.getMonthValid() or not date2.getMonthValid(): + return 0.75 + else: + return -1.0 + else: + return -1.0 + +#----------------------------------------------------------------- +# +# +# +#----------------------------------------------------------------- +def range_compare(date1,date2): + d1_start = date1.get_start_date() + d2_start = date2.get_start_date() + d1_stop = date1.get_stop_date() + d2_stop = date2.get_stop_date() + + if date1.isRange() and date2.isRange(): + if d1_start >= d2_start and d1_start <= d2_stop or \ + d2_start >= d1_start and d2_start <= d1_stop or \ + d1_stop >= d2_start and d1_stop <= d2_stop or \ + d2_stop >= d1_start and d2_stop <= d1_stop: + return 0.5 + else: + return -1.0 + elif date2.isRange(): + if d1_start >= d2_start and d1_start <= d2_stop: + return 0.5 + else: + return -1.0 + else: + if d2_start >= d1_start and d2_start <= d1_stop: + return 0.5 + else: + return -1.0 + +#--------------------------------------------------------------------- +# +# +# +#--------------------------------------------------------------------- +def name_match(name,name1): + + if not name1 or not name: + return 0 + + srn1 = name.getSurname() + sfx1 = name.getSuffix() + srn2 = name1.getSurname() + sfx2 = name1.getSuffix() + + if not 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 list_reduce(list1,list2) + else: + return list_reduce(list2,list1) + +#--------------------------------------------------------------------- +# +# +# +#--------------------------------------------------------------------- +def list_reduce(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 name_compare(name,name2): + value = value + 0.25 + break + if value == 0: + return -1 + else: + return min(value,1) + +#--------------------------------------------------------------------- +# +# +# +#--------------------------------------------------------------------- +def place_match(p1,p2): + if p1 == p2: + return 1 + + if p1 == None: + name1 = "" + else: + name1 = p1.get_title() + + if p2 == None: + name2 = "" + else: + name2 = p2.get_title() + + 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 name_compare(name,name2): + value = value + 0.25 + break + if value == 0: + return -1 + else: + return min(value,1) + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +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.getMainParents() + if f1 != None: + ancestors_of(f1.getFather(),list) + ancestors_of(f1.getMother(),list) + +#--------------------------------------------------------------------- +# +# +# +#--------------------------------------------------------------------- +def name_of(p): + if not p: + return "" + return "%s (%s)" % (GrampsCfg.nameof(p),p.getId()) + +#------------------------------------------------------------------------- +# +# Merge Places +# +#------------------------------------------------------------------------- +class MergePlaces: + """ + Merges to places into a single place. Displays a dialog box that + allows the places to be combined into one. + """ + def __init__(self,database,place1,place2,update): + self.db = database + self.p1 = place1 + self.p2 = place2 + self.update = update + + self.glade = gtk.glade.XML(const.mergeFile,"merge_places") + self.top = self.glade.get_widget("merge_places") + self.glade.get_widget("title1_text").set_text(place1.get_title()) + self.glade.get_widget("title2_text").set_text(place2.get_title()) + self.t3 = self.glade.get_widget("title3_text") + self.t3.set_text(place1.get_title()) + + self.glade.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_merge_places_clicked" : self.on_merge_places_clicked, + }) + self.top.show() + + def on_merge_places_clicked(self,obj): + """ + Performs the merge of the places when the merge button is clicked. + """ + t2active = self.glade.get_widget("title2").get_active() + + old_id = self.p1.getId() + + if t2active: + self.p1.set_title(self.p2.get_title()) + elif self.glade.get_widget("title3").get_active(): + self.p1.set_title(self.t3.get_text()) + + # Set longitude + if self.p1.get_longitude() == "" and self.p2.get_longitude() != "": + self.p1.set_longitude(self.p2.get_longitude()) + + # Set latitude + if self.p1.get_latitude() == "" and self.p2.get_latitude() != "": + self.p1.set_latitude(self.p2.get_latitude()) + + # Add URLs from P2 to P1 + for url in self.p2.getUrlList(): + self.p1.addUrl(url) + + # Copy photos from P2 to P1 + for photo in self.p2.getPhotoList(): + self.p1.addPhoto(photo) + + # Copy sources from P2 to P1 + for source in self.p2.getSourceRefList(): + self.p1.addSource(source) + + # Add notes from P2 to P1 + note = self.p2.getNote() + if note != "": + if self.p1.getNote() == "": + self.p1.setNote(note) + elif self.p1.getNote() != note: + self.p1.setNote("%s\n\n%s" % (self.p1.getNote(),note)) + + if t2active: + list = [self.p1.get_main_location()] + self.p1.get_alternate_locations() + self.p1.set_main_location(self.p2.get_main_location()) + for l in list: + if not l.is_empty(): + self.p1.add_alternate_locations(l) + else: + list = [self.p2.get_main_location()] + self.p2.get_alternate_locations() + for l in list: + if not l.is_empty(): + self.p1.add_alternate_locations(l) + + # loop through people, changing event references to P2 to P1 + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + for event in [p.getBirth(), p.getDeath()] + p.getEventList(): + if event.getPlace() == self.p2: + event.setPlace(self.p1) + + # loop through families, changing event references to P2 to P1 + for f in self.db.getFamilyMap().values(): + for event in f.getEventList(): + if event.getPlace() == self.p2: + event.setPlace(self.p1) + + self.db.removePlace(self.p2.getId()) + self.db.buildPlaceDisplay(self.p1.getId(),old_id) + + self.update(self.p1.getId()) + Utils.modified() + Utils.destroy_passed_object(obj) + diff --git a/gramps2/src/NEWS b/gramps2/src/NEWS new file mode 100644 index 000000000..e69de29bb diff --git a/gramps2/src/NameEdit.py b/gramps2/src/NameEdit.py new file mode 100644 index 000000000..edb5b2baf --- /dev/null +++ b/gramps2/src/NameEdit.py @@ -0,0 +1,160 @@ +# +# 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 gtk.glade + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import AutoComp +import Sources +from RelLib import * + +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# NameEditor class +# +#------------------------------------------------------------------------- +class NameEditor: + + def __init__(self,parent,name): + self.parent = parent + self.name = name + self.top = gtk.glade.XML(const.dialogFile, "name_edit") + self.window = self.top.get_widget("name_edit") + self.given_field = self.top.get_widget("alt_given") + self.title_field = self.top.get_widget("alt_title") + self.surname_field = self.top.get_widget("alt_last") + self.suffix_field = self.top.get_widget("alt_suffix") + self.type_field = self.top.get_widget("name_type") + self.note_field = self.top.get_widget("alt_note") + self.slist = self.top.get_widget('slist') + slist = self.top.get_widget("alt_surname_list") + self.combo = AutoComp.AutoCombo(slist,self.parent.db.getSurnames()) + self.priv = self.top.get_widget("priv") + + types = const.NameTypesMap.keys() + types.sort() + self.type_field.set_popdown_strings(types) + self.typecomp = AutoComp.AutoEntry(self.type_field.entry,types) + + if self.name: + self.srcreflist = self.name.getSourceRefList() + else: + self.srcreflist = [] + + full_name = parent.person.getPrimaryName().getName() + + self.top.get_widget("altTitle").set_text( + _("Alternate Name Editor for %s") % full_name) + + self.sourcetab = Sources.SourceTab(self.srcreflist, self.parent, + self.top, self.slist, + self.top.get_widget('add_src'), + self.top.get_widget('del_src')) + + self.note_buffer = self.note_field.get_buffer() + + if name != None: + self.given_field.set_text(name.getFirstName()) + self.surname_field.set_text(name.getSurname()) + self.title_field.set_text(name.getTitle()) + self.suffix_field.set_text(name.getSuffix()) + self.type_field.entry.set_text(_(name.getType())) + self.priv.set_active(name.getPrivacy()) + self.note_buffer.set_text(name.getNote()) + + self.top.signal_autoconnect({ + "destroy_passed_object" : Utils.destroy_passed_object, + "on_name_edit_ok_clicked" : self.on_name_edit_ok_clicked, + }) + + def on_name_edit_ok_clicked(self,obj): + first = self.given_field.get_text() + last = self.surname_field.get_text() + title = self.title_field.get_text() + suffix = self.suffix_field.get_text() + note = self.note_buffer.get_text(self.note_buffer.get_start_iter(), + self.note_buffer.get_end_iter(),gtk.FALSE) + priv = self.priv.get_active() + + type = self.type_field.entry.get_text() + + if const.NameTypesMap.has_key(type): + type = const.NameTypesMap[type] + else: + type = "Also Known As" + + if self.name == None: + self.name = Name() + self.parent.nlist.append(self.name) + + self.name.setSourceRefList(self.srcreflist) + + self.update_name(first,last,suffix,title,type,note,priv) + self.parent.lists_changed = 1 + + self.parent.redraw_name_list() + Utils.destroy_passed_object(obj) + + def update_name(self,first,last,suffix,title,type,note,priv): + + if self.name.getFirstName() != first: + self.name.setFirstName(first) + self.parent.lists_changed = 1 + + if self.name.getSurname() != last: + self.name.setSurname(last) + self.parent.db.addSurname(last) + self.parent.lists_changed = 1 + + if self.name.getSuffix() != suffix: + self.name.setSuffix(suffix) + self.parent.lists_changed = 1 + + if self.name.getTitle() != title: + self.name.setTitle(title) + self.parent.lists_changed = 1 + + if self.name.getType() != type: + self.name.setType(type) + self.parent.lists_changed = 1 + + if self.name.getNote() != note: + self.name.setNote(note) + self.parent.lists_changed = 1 + + if self.name.getPrivacy() != priv: + self.name.setPrivacy(priv) + self.parent.lists_changed = 1 + + diff --git a/gramps2/src/NoteEdit.py b/gramps2/src/NoteEdit.py new file mode 100644 index 000000000..b77537e89 --- /dev/null +++ b/gramps2/src/NoteEdit.py @@ -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 +# + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk +import gnome.ui + +#------------------------------------------------------------------------- +# +# gramps modules +# +#------------------------------------------------------------------------- +import Utils +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# NoteEditor +# +#------------------------------------------------------------------------- +class NoteEditor: + """Displays a simple text editor that allows a person to edit a note""" + def __init__(self,data): + + self.data = data + self.draw() + + def draw(self): + """Displays the NoteEditor window""" + title = "%s - GRAMPS" % _("Edit Note") + + self.top = gtk.Dialog(title) + self.top.set_default_size(450,300) + + vbox = gtk.VBox() + self.top.vbox.pack_start(vbox,gtk.TRUE,gtk.TRUE,0) + vbox.pack_start(gtk.Label(_("Edit Note")), gtk.FALSE, gtk.FALSE, 10) + + vbox.pack_start(gtk.HSeparator(), gtk.FALSE, gtk.TRUE, 5) + self.entry = gtk.TextView() + self.entry.set_editable(gtk.TRUE) + self.entry.show() + + scroll = gtk.ScrolledWindow() + scroll.add(self.entry) + scroll.set_policy (gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) + scroll.show() + vbox.pack_start(scroll, gtk.TRUE, gtk.TRUE, 0) + + self.entry.get_buffer().set_text(self.data.getNote()) + + self.top.add_button(gtk.STOCK_OK,0) + self.top.add_button(gtk.STOCK_CANCEL,1) + self.top.show_all() + + if self.top.run() == 0: + self.on_save_note_clicked() + else: + self.cancel() + + def cancel(self): + """Closes the window without saving the note""" + self.top.destroy() + + def on_save_note_clicked(self): + """Saves the note and closes the window""" + buffer = self.entry.get_buffer() + text = buffer.get_text(buffer.get_start_iter(), + buffer.get_end_iter(),gtk.FALSE) + if text != self.data.getNote(): + self.data.setNote(text) + Utils.modified() + self.top.destroy() + diff --git a/gramps2/src/PaperMenu.py b/gramps2/src/PaperMenu.py new file mode 100644 index 000000000..d2bcf2a3c --- /dev/null +++ b/gramps2/src/PaperMenu.py @@ -0,0 +1,70 @@ +# +# 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 GrampsCfg + +from intl import gettext +_ = gettext + +paper_sizes = [ + TextDoc.PaperStyle("Letter",27.94,21.59), + TextDoc.PaperStyle("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): + + index = 0 + myMenu = gtk.Menu() + for paper in paper_sizes: + name = paper.get_name() + menuitem = gtk.MenuItem(name) + menuitem.set_data("i",paper) + menuitem.show() + myMenu.append(menuitem) + if name == GrampsCfg.paper_preference: + myMenu.set_active(index) + index = index + 1 + main_menu.set_menu(myMenu) + +def make_orientation_menu(main_menu): + + myMenu = gtk.Menu() + menuitem = gtk.MenuItem(_("Portrait")) + menuitem.set_data("i",TextDoc.PAPER_PORTRAIT) + menuitem.show() + myMenu.append(menuitem) + + menuitem = gtk.MenuItem(_("Landscape")) + menuitem.set_data("i",TextDoc.PAPER_LANDSCAPE) + menuitem.show() + myMenu.append(menuitem) + + main_menu.set_menu(myMenu) + diff --git a/gramps2/src/PedView.py b/gramps2/src/PedView.py new file mode 100644 index 000000000..1909268b4 --- /dev/null +++ b/gramps2/src/PedView.py @@ -0,0 +1,486 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2001 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 +# + +_PAD = 3 +_CANVASPAD = 3 +_PERSON = "p" + +import gtk +import gtk.gdk +import gnome.canvas +import pango + +import GrampsCfg + +from intl import gettext as _ + +class DispBox: + + def __init__(self,root,style,x,y,w,h,person,change): + shadow = _PAD + xpad = _PAD + + self.change = change + self.x = x + self.y = y + self.w = w + self.h = h + self.person = person + self.root = root + + self.name = person.getPrimaryName().getName() + self.exp = "%s\nb. %s\nd. %s" % (self.name,person.getBirth().getDate(), + person.getDeath().getDate()) + + self.group = self.root.add(gnome.canvas.CanvasGroup,x=x,y=y) + self.shadow = self.group.add(gnome.canvas.CanvasRect, + x1=shadow, + y1=shadow, + x2=w+shadow, + y2=h+shadow, + outline_color_gdk=style.dark[gtk.STATE_NORMAL], + fill_color_gdk=style.dark[gtk.STATE_NORMAL]) + + # draw the real box + self.bkgnd = self.group.add(gnome.canvas.CanvasRect, + x1=0, + y1=0, + x2=w, + y2=h, + outline_color_gdk=style.bg[gtk.STATE_NORMAL], + fill_color_gdk=style.white) + + font = gtk.gdk.font_from_description(style.font_desc) + self.textbox = self.group.add(gnome.canvas.CanvasText, + x=xpad, + y=h/2.0, + text=self.name, + fill_color_gdk=style.text[gtk.STATE_NORMAL], + font=font, anchor=gtk.ANCHOR_WEST) + self.group.connect('event',self.group_event) + self.group.set_data('p',person) + + def cleanup(self): + self.shadow.destroy() + self.bkgnd.destroy() + self.textbox.destroy() + self.group.destroy() + + def group_event(self,obj,event): + """Handle events over a drawn box. Doubleclick would edit, + shift doubleclick would change the active person, entering + the box expands it to display more information, leaving a + box returns it to the original size and information""" + + if event.type == gtk.gdk._2BUTTON_PRESS: + return 1 + elif event.type == gtk.gdk.ENTER_NOTIFY: + self.expand() + return 0 + elif event.type == gtk.gdk.LEAVE_NOTIFY: + self.shrink() + return 0 + return 0 + + def expand(self): + """Expand a box to include additional information""" + self.group.raise_to_top() + self.textbox.set(text=self.exp) + self.bkgnd.set(y1=-self.h,y2=self.h*2) + self.shadow.set(y1=-self.h+_PAD,y2=self.h*2+_PAD) + + def shrink(self): + """Expand a box to include additional information""" + self.group.raise_to_top() + self.textbox.set(text=self.name) + self.bkgnd.set(y1=0,y2=self.h) + self.shadow.set(y1=_PAD,y2=self.h+_PAD) + +#------------------------------------------------------------------------- +# +# PedigreeView +# +#------------------------------------------------------------------------- +class PedigreeView: + def __init__(self,canvas,update,status_bar,change_active,lp): + self.canvas = canvas + self.canvas_items = [] + self.boxes = [] + self.root = self.canvas.root() + self.active_person = None + self.x1 = 0 + self.x2 = 0 + self.y1 = 0 + self.y2 = 0 + self.update = update + self.sb = status_bar + self.change_active_person = change_active + self.load_person = lp + self.presel_descendants = [] + + def load_canvas(self, person): + """Redraws the pedigree view window, using the passed person + as the root person of the tree.""" + + for i in self.canvas_items: + i.destroy() + for i in self.boxes: + i.cleanup() + + if person is not self.active_person: + del self.presel_descendants[:] + self.active_person = person + if person == None: + return + + h = 0 + w = 0 + (x2,y2) = self.canvas.get_size() + + self.canvas.set_scroll_region(0,0,x2,y2) + + style = self.canvas.get_style() + font = gtk.gdk.font_from_description(style.font_desc) + + list = [None]*31 + self.find_tree(self.active_person,0,1,list) + + # determine the largest string width and height for calcuation + # of box sizes. + + a = pango.Layout(self.canvas.get_pango_context()) + + for t in list: + if t: + for n in [t[0].getPrimaryName().getName(), + "b. %s" % t[0].getBirth().getDate(), + "d. %s" % t[0].getDeath().getDate()]: + a.set_text(n,len(n)) + (w1,h1) = a.get_pixel_size() + h = max(h,h1) + w = max(w,w1) + cpad = 10 + w = w+_PAD + + cw = x2-(2*cpad)-10-h + ch = y2-(2*cpad) + + if 5*w < cw and 24*h < ch: + gen = 31 + xdiv = 5.0 + elif 4*w < cw and 12*h < ch: + gen = 15 + xdiv = 4.0 + else: + gen = 7 + xdiv = 3.0 + + xpts = self.build_x_coords(cw/xdiv,_CANVASPAD+h) + ypts = self.build_y_coords((ch-h)/32.0, h) + + self.canvas_items = [] + for family in self.active_person.getFamilyList(): + if len(family.getChildList()) > 0: + button,arrow = self.make_arrow_button(gtk.ARROW_LEFT, + self.on_show_child_menu) + item = self.root.add(gnome.canvas.CanvasWidget, widget=button, + x=_CANVASPAD, y=ypts[0]+(h/2.0), + height=h, width=h, + size_pixels=1, anchor=gtk.ANCHOR_WEST) + self.canvas_items = [item, button, arrow] + break + else: + self.canvas_items = [] + + if list[1]: + p = list[1] + self.add_parent_button(p[0],x2-_PAD,ypts[1],h) + + if list[2]: + p = list[2] + self.add_parent_button(p[0],x2-_PAD,ypts[2],h) + + gen_no = len(self.presel_descendants) + 1 + for i in range(int(xdiv)): + item = self.root.add(gnome.canvas.CanvasText, x=(cw*i/xdiv + cpad), y=h, + text=str(gen_no), + font=font, + anchor=gtk.ANCHOR_WEST) + self.canvas_items.append(item) + gen_no = gen_no + 1 + + for i in range(gen): + if list[i]: + if i < int(gen/2.0): + findex = (2*i)+1 + mindex = findex+1 + if list[findex]: + p = list[findex] + self.draw_canvas_line(xpts[i], ypts[i], xpts[findex], + ypts[findex], h, w, p[0], style, p[1]) + if list[mindex]: + p = list[mindex] + self.draw_canvas_line(xpts[i],ypts[i], xpts[mindex], + ypts[mindex], h, w, p[0], style, p[1]) + p = list[i] + box = DispBox(self.root,style,xpts[i],ypts[i],w,h,p[0], + self.change_active_person) + self.boxes.append(box) + self.change_active_person(person) + + def make_arrow_button(self,direction,function): + """Make a button containing an arrow with the attached callback""" + + arrow = gtk.Arrow(direction,gtk.SHADOW_NONE) + button = gtk.Button() + button.add(arrow) + button.connect("clicked",function) + arrow.show() + button.show() + return (button, arrow) + + def on_show_child_menu(self,obj): + """User clicked button to move to child of active person""" + + if self.presel_descendants: + # Go to a previously selected child. + person = self.presel_descendants.pop(-1) + self.active_person = person + self.load_canvas(person) + elif self.active_person: + # Build and display the menu attached to the left pointing arrow + # button. The menu consists of the children of the current root + # person of the tree. Attach a child to each menu item. + myMenu = gtk.Menu() + for family in self.active_person.getFamilyList(): + for child in family.getChildList(): + menuitem = gtk.MenuItem(GrampsCfg.nameof(child)) + myMenu.append(menuitem) + menuitem.set_data(_PERSON,child) + menuitem.connect("activate",self.on_childmenu_changed) + menuitem.show() + myMenu.popup(None,None,None,0,0) + return 1 + + def on_childmenu_changed(self,obj): + """Callback for the pulldown menu selection, changing to the person + attached with menu item.""" + + person = obj.get_data(_PERSON) + if person: + self.load_canvas(person) + return 1 + + def add_parent_button(self,parent,x,y,h): + """Add a button with a right pointing button on the main group at + the specified location. Attach the passed parent and the callback + to the button.""" + + button,arrow = self.make_arrow_button(gtk.ARROW_RIGHT,self.change_to_parent) + button.set_data(_PERSON,parent) + + item = self.root.add(gnome.canvas.CanvasWidget, widget=button, x=x, y=y+(h/2), + height=h, width=h, size_pixels=1, + anchor=gtk.ANCHOR_EAST) + self.canvas_items.append(arrow) + self.canvas_items.append(item) + self.canvas_items.append(button) + + def change_to_parent(self,obj): + """Callback to right pointing arrow button. Gets the person + attached to the button and change the root person to that + person, redrawing the view.""" + person = obj.get_data(_PERSON) + if self.active_person: + self.presel_descendants.append(self.active_person) + self.active_person = person + self.load_canvas(person) + + def draw_canvas_line(self,x1,y1,x2,y2,h,w,data,style,ls): + """Draw an two segment line between the x,y point pairs. Attach + a event callback and data to the line.""" + + startx = x1+(w/2.0) + pts = [startx,y1, startx,y2+(h/2.0), x2,y2+(h/2.0)] + item = self.root.add(gnome.canvas.CanvasLine, width_pixels=2, + points=pts, line_style=ls, + fill_color_gdk=style.black) + item.set_data(_PERSON,data) + item.connect("event",self.line_event) + self.canvas_items.append(item) + + def build_x_coords(self,x,cpad): + """Build the array of x coordinates for the possible positions + on the pedegree view.""" + return [cpad] + [x+cpad]*2 + [x*2+cpad]*4 + [x*3+cpad]*8 + [x*4+cpad]*16 + + def build_y_coords(self, y, top_pad): + """Build the array of y coordinates for the possible positions + on the pedegree view.""" + res = [ y*16.0, y*8.0, y*24.0, y*4.0, y*12.0, y*20.0, y*28.0, y*2.0, + y*6.0, y*10.0, y*14.0, y*18.0, y*22.0, y*26.0, y*30.0, y, + y*3.0, y*5.0, y*7.0, y*9.0, y*11.0, y*13.0, y*15.0, y*17.0, + y*19.0, y*21.0, y*23.0, y*25.0, y*27.0, y*29.0, y*31.0 ] + return map(lambda coord, top_pad=top_pad: coord + top_pad, res) + + def add_box(self, x, y, bwidth, bheight, person, style): + """Draw a box of the specified size at the specified location. + The box consists of a shadow box for effect, the real box + that contains the information, and the basic text + information. For convience, the all the subelements are + grouped into a GNOME canvas group.""" + + shadow = _PAD + xpad = _PAD + + name = person.getPrimaryName().getName() + group = self.root.add(gnome.canvas.CanvasGroup,x=x,y=y) + self.canvas_items.append(group) + + # draw the shadow box + item = group.add(gnome.canvas.CanvasRect, x1=shadow, y1=shadow, + x2=bwidth+shadow, y2=bheight+shadow, + outline_color_gdk=style.dark[gtk.STATE_NORMAL], + fill_color_gdk=style.dark[gtk.STATE_NORMAL]) + self.canvas_items.append(item) + + # draw the real box + item = group.add(gnome.canvas.CanvasRect, x1=0, y1=0, x2=bwidth, y2=bheight, + outline_color_gdk=style.bg[gtk.STATE_NORMAL], + fill_color_gdk=style.white) + self.canvas_items.append(item) + + # Write the text + + font = gtk.gdk.font_from_description(style.font_desc) + + item = group.add(gnome.canvas.CanvasText, x=xpad, y=bheight/2.0, text=name, + fill_color_gdk=style.text[gtk.STATE_NORMAL], + font=font, anchor=gtk.ANCHOR_WEST) + self.canvas_items.append(item) + group.connect('event',self.box_event) + group.set_data('p',person) + + def box_event(self,obj,event): + """Handle events over a drawn box. Doubleclick would edit, + shift doubleclick would change the active person, entering + the box expands it to display more information, leaving a + box returns it to the original size and information""" + + if event.type == gtk.gdk._2BUTTON_PRESS: +# if event.button == 1: +# person = obj.get_data(_PERSON) +# if (event.state & gtk.gdk.SHIFT_MASK) or (event.state & gtk.gdk.CONTROL_MASK): +# self.change_active_person(person) +# del self.presel_descendants[:] +# self.load_canvas(person) +# else: +# self.load_person(person) + return 1 + elif event.type == gtk.gdk.ENTER_NOTIFY: + self.expand_box(obj) + return 0 + elif event.type == gtk.gdk.LEAVE_NOTIFY: + self.shrink_box(obj) + return 0 + return 0 + + def shrink_box(self,obj): + """Shrink an exanded box back down to normal size""" + box = self.group_map[obj][1] + x,y,w,h = box.get_bounds() + box.set(x1=x,y1=y,x2=w,y2=h/3) + box2 = self.group_map[obj][2] + x,y,w,h1 = box2.get_bounds() + person = obj.get_data('p') + n = person.getPrimaryName().getName() + box2.set(text=n) + self.update() + self.canvas.update_now() + + def expand_box(self,obj): + """Expand a box to include additional information""" + obj.raise_to_top() + x,y,w,h = box.get_bounds() + box.set(x1=x,y1=y,x2=w,y2=h*3) + box2 = self.group_map[obj][0] + x,y,w,h1 = box2.get_bounds() + box2.set(x1=x,y1=y,x2=w,y2=(3*h)+_PAD) + person = obj.get_data('p') + color = self.canvas.get_style().text[gtk.STATE_NORMAL] + n = "%s\nb. %s.\nd. %s" % (person.getPrimaryName().getName(), + person.getBirth().getDate(), + person.getDeath().getDate()) + box2 = self.group_map[obj][2] + box2.set(text=n) + box2.show() + msg = _("Doubleclick to edit, Shift-Doubleclick to make the active person") + self.sb.set_status(msg) + + def line_event(self,obj,event): + """Catch X events over a line and respond to the ones we care about""" + + person = obj.get_data(_PERSON) + style = self.canvas.get_style() + + if event.type == gtk.gdk._2BUTTON_PRESS: + if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: + self.load_canvas(person) + elif event.type == gtk.gdk.ENTER_NOTIFY: + obj.set(fill_color_gdk=style.bg[gtk.STATE_SELECTED], + width_pixels=4) + name = GrampsCfg.nameof(person) + msg = _("Double clicking will make %s the active person") % name + self.sb.set_status(msg) + elif event.type == gtk.gdk.LEAVE_NOTIFY: + obj.set(fill_color_gdk=style.black, width_pixels=2) + self.update() + + def on_canvas1_event(self,obj,event): + """Handle resize events over the canvas, redrawing if the size changes""" + + if event.type == gtk.gdk.EXPOSE: + x1,y1,x2,y2 = self.canvas.get_allocation() + if self.x1 != x1 or self.x2 != x2 or \ + self.y1 != y1 or self.y2 != y2: + self.x1 = x1; self.x2 = x2 + self.y1 = y1; self.y2 = y2 + self.load_canvas(self.active_person) + return 0 + + def find_tree(self,person,index,depth,list,val=0): + """Recursively build a list of ancestors""" + + if depth > 5 or person == None: + return + (family,m,f) = person.getMainParentsRel() + if family: + mrel = (m != "Birth") + frel = (f != "Birth") + + list[index] = (person,val) + if family != None: + father = family.getFather() + if father != None: + self.find_tree(father,(2*index)+1,depth+1,list,frel) + mother = family.getMother() + if mother != None: + self.find_tree(mother,(2*index)+2,depth+1,list,mrel) + diff --git a/gramps2/src/PlaceView.py b/gramps2/src/PlaceView.py new file mode 100644 index 000000000..30c165f9f --- /dev/null +++ b/gramps2/src/PlaceView.py @@ -0,0 +1,225 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2001 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 +# + +""" +Handles the place view for GRAMPS. +""" + +#------------------------------------------------------------------------- +# +# GTK modules +# +#------------------------------------------------------------------------- +import gobject +import gtk +import gtk.gdk + +#------------------------------------------------------------------------- +# +# Gramps modules +# +#------------------------------------------------------------------------- +from RelLib import * +from QuestionDialog import QuestionDialog + +import EditPlace +import Utils +import GrampsCfg + +from intl import gettext as _ + +_column_headers = [ + (_('Place Name'),7,200), + (_('ID'),1,50), + (_('Church Parish'),8,75), + (_('City'),9,75), + (_('County'),10,75), + (_('State'),11,75), + (_('Country'),12,75), + (_(''),7,0), + (_(''),8,0), + (_(''),9,0), + (_(''),10,0), + (_(''),11,0), + (_(''),12,0)] + +#------------------------------------------------------------------------- +# +# PlaceView class +# +#------------------------------------------------------------------------- +class PlaceView: + + def __init__(self,db,glade,update): + self.db = db + self.glade = glade + self.list = glade.get_widget("place_list") + self.update_display= update + + self.active = None + + self.id2col = {} + self.selection = self.list.get_selection() + colno = 0 + for title in _column_headers: + renderer = gtk.CellRendererText () + column = gtk.TreeViewColumn (title[0], renderer, text=colno) + colno = colno + 1 + column.set_clickable (gtk.TRUE) + if title[0] == '': + column.set_visible(gtk.FALSE) + else: + column.set_resizable(gtk.TRUE) + column.set_visible(gtk.TRUE) + column.set_sort_column_id(title[1]) + column.set_min_width(title[2]) + self.list.append_column(column) + + self.list.set_search_column(0) + self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING, + gobject.TYPE_STRING) + self.list.set_model(self.model) + self.list.get_column(0).clicked() + + def change_db(self,db): + self.db = db + + def load_places(self,id=None): + """Rebuilds the entire place view. This can be very time consuming + on large databases, and should only be called when absolutely + necessary""" + + self.model.clear() + self.id2col = {} + + for key in self.db.getPlaceKeys(): + val = self.db.getPlaceDisplay(key) + + iter = self.model.append() + self.id2col[key] = iter + self.model.set(iter, + 0, val[0], 1, val[1], 2, val[2], 3, val[3], + 4, val[4], 5, val[5], 6, val[6], 7, val[7], + 8, val[8], 9, val[9], 10, val[10], 11, val[11], + 12, val[12] + ) + self.list.connect('button-press-event',self.button_press) + + def merge(self): + if len(self.place_list.selection) != 2: + msg = _("Exactly two places must be selected to perform a merge") + gnome.ui.GnomeErrorDialog(msg) + else: + import MergeData + p1 = self.place_list.get_row_data(self.place_list.selection[0]) + p2 = self.place_list.get_row_data(self.place_list.selection[1]) + p1 = self.db.getPlace(p1) + p2 = self.db.getPlace(p2) + MergeData.MergePlaces(self.db,p1,p2,self.load_places) + + def button_press(self,obj,event): + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + store,iter = self.selection.get_selected() + id = store.get_value(iter,1) + + place = self.db.getPlace(id) + EditPlace.EditPlace(self,place,self.update_display) + return 1 + + def insert_place(self,place): + self.place_list.append(place.getDisplayInfo()) + self.place_list.set_row_data(self.place_list.rows-1,place.getId()) + + def new_place_after_edit(self,place): + self.db.addPlace(place) + self.update(0) + + def update_display(self,place): + self.db.buildPlaceDisplay(place.getId()) + self.update(0) + + def on_add_place_clicked(self,obj): + EditPlace.EditPlace(self,Place(),self.new_place_after_edit) + + def moveto(self,row): + self.place_list.unselect_all() + self.place_list.select_row(row,0) + self.place_list.moveto(row) + + def on_delete_clicked(self,obj): + if len(obj.selection) == 0: + return + elif len(obj.selection) > 1: + msg = _("Currently, you can only delete one place at a time") + gnome.ui.GnomeErrorDialog(msg) + return + else: + index = obj.selection[0] + + used = 0 + place = self.db.getPlace(obj.get_row_data(index)) + for key in self.db.getPersonKeys(): + p = self.db.getPerson(key) + event_list = [p.getBirth(), p.getDeath()] + p.getEventList() + if p.getLdsBaptism(): + event_list.append(p.getLdsBaptism()) + if p.getLdsEndowment(): + event_list.append(p.getLdsEndowment()) + if p.getLdsSeal(): + event_list.append(p.getLdsSeal()) + for event in event_list: + if event.getPlace() == place: + used = 1 + + for f in self.db.getFamilyMap().values(): + event_list = f.getEventList() + if f.getLdsSeal(): + event_list.append(f.getLdsSeal()) + for event in event_list: + if event.getPlace() == place: + used = 1 + + if used == 1: + ans = EditPlace.DeletePlaceQuery(place,self.db,self.update_display) + QuestionDialog(_('Delete Place'), + _("This place is currently being used. Delete anyway?"), + _('Delete Place'),ans.query_response, + _('Keep Place')) + else: + obj.remove(index) + self.db.removePlace(place.getId()) + Utils.modified() + + def on_edit_clicked(self,obj): + """Display the selected places in the EditPlace display""" + list_store, iter = self.selection.get_selected() + if iter: + id = list_store.get_value(iter,1) + place = self.db.getPlace(id) + EditPlace.EditPlace(self, place, self.update_display) + + + + diff --git a/gramps2/src/Plugins.py b/gramps2/src/Plugins.py new file mode 100644 index 000000000..e86f3df56 --- /dev/null +++ b/gramps2/src/Plugins.py @@ -0,0 +1,648 @@ +# +# 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 +# + +""" +The core of the GRAMPS plugin system. This module provides tasks to load +plugins from specfied directories, build menus for the different categories, +and provide dialog to select and execute plugins. + +Plugins are divided into several categories. This are: reports, tools, +filters, importer, exporters, and document generators. +""" + +#------------------------------------------------------------------------- +# +# GTK libraries +# +#------------------------------------------------------------------------- +#import GdkImlib +import gtk +import gtk.glade + +#------------------------------------------------------------------------- +# +# Standard Python modules +# +#------------------------------------------------------------------------- +import traceback +import os +import sys +from re import compile + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +import const +import Utils +import GrampsCfg +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# Global lists +# +#------------------------------------------------------------------------- +_reports = [] +_tools = [] +_imports = [] +_exports = [] +_success = [] +_failed = [] +_expect = [] +_attempt = [] +_loaddir = [] +_textdoc = [] +_drawdoc = [] +_failmsg = [] + +_unavailable = _("No description was provided"), +#------------------------------------------------------------------------- +# +# Exception Strings +# +#------------------------------------------------------------------------- +MissingLibraries = _("Missing Libraries") + +#------------------------------------------------------------------------- +# +# Constants +# +#------------------------------------------------------------------------- +DOCSTRING = "d" +IMAGE = "i" +TASK = "f" +TITLE = "t" +STATUS = "s" + +#------------------------------------------------------------------------- +# +# PluginDialog interface class +# +#------------------------------------------------------------------------- +class PluginDialog: + """Displays the dialog box that allows the user to select the + report that is desired.""" + + def __init__(self,db,active,list,msg): + """Display the dialog box, and build up the list of available + reports. This is used to build the selection tree on the left + hand side of the dailog box.""" + + self.db = db + self.active = active + self.update = None + + self.dialog = gtk.glade.XML(const.pluginsFile,"report") + self.dialog.signal_autoconnect({ + "on_report_apply_clicked" : self.on_apply_clicked, + "on_report_ok_clicked" : self.on_apply_clicked, + "on_tree_select_row" : self.on_node_selected, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + self.tree = self.dialog.get_widget("tree") + self.top = self.dialog.get_widget("report") + self.img = self.dialog.get_widget("image") + self.description = self.dialog.get_widget("description") + self.status = self.dialog.get_widget("report_status") + self.label = self.dialog.get_widget("report_label") + self.title = self.dialog.get_widget("title") + + self.run_tool = None + self.build_tree(list) + self.title.set_text(msg) + self.top.set_title("%s - GRAMPS" % msg) + + def on_apply_clicked(self,obj): + """Execute the selected report""" + + Utils.destroy_passed_object(obj) + if self.run_tool: + if self.update: + self.run_tool(self.db,self.active,self.update) + else: + self.run_tool(self.db,self.active) + + def on_node_selected(self,obj,node,other): + """Updates the informational display on the right hand side of + the dialog box with the description of the selected report""" + + data = self.tree.node_get_row_data(node) + if not data: + return + task = data[1] + title = data[0] + doc = data[2] + xpm = data[3] + status = data[4] + + #image = GdkImlib.create_image_from_xpm(xpm) + self.description.set_text(doc) + self.status.set_text(": %s" % status) + self.label.show() + #self.img.load_imlib(image) + self.title.set_text(title) + + self.dialog.get_widget("title").set_text(title) + self.run_tool = task + + def build_tree(self,list): + """Populates a GtkTree with each menu item assocated with a entry + in the lists. The list must consist of a tuples with the following + format: + + (task_to_call, category, report name, description, image, status) + + Items in the same category are grouped under the same submen. The + task_to_call is bound to the 'select' callback of the menu entry.""" + + # build the tree items and group together based on the category name + item_hash = {} + for report in list: + t = (report[2],report[0],report[3],report[4],report[5]) + if item_hash.has_key(report[1]): + item_hash[report[1]].append(t) + else: + item_hash[report[1]] = [t] + + # add a submenu for each category, and populate it with the + # GtkTreeItems that are associated with it. + key_list = item_hash.keys() + key_list.sort() + prev = None + for key in key_list: + data = item_hash[key] + node = self.tree.insert_node(None,prev,[key],is_leaf=0,expanded=1) + self.tree.node_set_row_data(node,0) + next = None + data.sort() + data.reverse() + for item in data: + next = self.tree.insert_node(node,next,[item[0]],is_leaf=1,expanded=1) + self.tree.node_set_row_data(next,item) + +#------------------------------------------------------------------------- +# +# ReportPlugins interface class +# +#------------------------------------------------------------------------- +class ReportPlugins(PluginDialog): + """Displays the dialog box that allows the user to select the + report that is desired.""" + + def __init__(self,db,active): + """Display the dialog box, and build up the list of available + reports. This is used to build the selection tree on the left + hand side of the dailog box.""" + PluginDialog.__init__(self,db,active,_reports,_("Report Selection")) + +#------------------------------------------------------------------------- +# +# ToolPlugins interface class +# +#------------------------------------------------------------------------- +class ToolPlugins(PluginDialog): + """Displays the dialog box that allows the user to select the tool + that is desired.""" + + def __init__(self,db,active,update): + """Display the dialog box, and build up the list of available + reports. This is used to build the selection tree on the left + hand side of the dailog box.""" + + PluginDialog.__init__(self,db,active,_tools,_("Tool Selection")) + self.update = update + +#------------------------------------------------------------------------- +# +# PluginStatus +# +#------------------------------------------------------------------------- +class PluginStatus: + """Displays a dialog showing the status of loaded plugins""" + + def __init__(self): + import cStringIO + + self.glade = gtk.glade.XML(const.pluginsFile,"plugstat") + self.top = self.glade.get_widget("plugstat") + window = self.glade.get_widget("text") + self.glade.signal_autoconnect({ + 'on_close_clicked' : self.close + }) + + info = cStringIO.StringIO() + info.write(_("The following modules could not be loaded:")) + info.write("\n\n") + + for (file,msg) in _expect: + info.write("%s: %s\n\n" % (file,msg)) + + for (file,msgs) in _failmsg: + error = str(msgs[0]) + if error[0:11] == "exceptions.": + error = error[11:] + info.write("%s: %s\n" % (file,error) ) + traceback.print_exception(msgs[0],msgs[1],msgs[2],None,info) + info.write('\n') + info.seek(0) + window.get_buffer().set_text(info.read()) + + def close(self,obj): + self.top.destroy() + +#------------------------------------------------------------------------- +# +# load_plugins +# +#------------------------------------------------------------------------- +def load_plugins(direct): + """Searches the specified directory, and attempts to load any python + modules that it finds, adding name to the _attempts list. If the module + successfully loads, it is added to the _success list. Each plugin is + responsible for registering itself in the correct manner. No attempt + is done in this routine to register the tasks.""" + + global _success,_failed,_attempt,_loaddir + + # if the directory does not exist, do nothing + if not os.path.isdir(direct): + return + + # if the path has not already been loaded, save it in the _loaddir + # list for use on reloading + + if direct not in _loaddir: + _loaddir.append(direct) + + # add the directory to the python search path + sys.path.append(direct) + + pymod = compile(r"^(.*)\.py$") + + # loop through each file in the directory, looking for files that + # have a .py extention, and attempt to load the file. If it succeeds, + # add it to the _success list. If it fails, add it to the _failure + # list + + for file in os.listdir(direct): + name = os.path.split(file) + match = pymod.match(name[1]) + if not match: + continue + _attempt.append(file) + plugin = match.groups()[0] + try: + a = __import__(plugin) + _success.append(a) + except MissingLibraries,msg: + _expect.append((file,msg)) + except: + _failmsg.append((file,sys.exc_info())) + +#------------------------------------------------------------------------- +# +# reload_plugins +# +#------------------------------------------------------------------------- +def reload_plugins(obj): + """Treated as a callback, causes all plugins to get reloaded. This is + useful when writing and debugging a plugin""" + + pymod = compile(r"^(.*)\.py$") + + # attempt to reload all plugins that have succeeded + # in the past + for plugin in _success: + try: + reload(plugin) + except: + _failmsg.append((plugin,sys.exc_info())) + + # attempt to load the plugins that have failed in the past + + for plugin in _failed: + try: + __import__(plugin) + except: + _failmsg.append((plugin,sys.exc_info())) + + # attempt to load any new files found + for dir in _loaddir: + for file in os.listdir(dir): + name = os.path.split(file) + match = pymod.match(name[1]) + if not match: + continue + if file in _attempt: + return + _attempt.append(file) + plugin = match.groups()[0] + try: + a = __import__(plugin) + _success.append(a) + except: + _failmsg.append((file,sys.exc_info())) + +#------------------------------------------------------------------------- +# +# Plugin registering +# +#------------------------------------------------------------------------- +def register_export(task, name): + """Register an export filter, taking the task and name""" + _exports.append((task, name)) + +def register_import(task, name): + """Register an import filter, taking the task and name""" + _imports.append((task, name)) + +def register_report(task, name, + category=_("Uncategorized"), + description=_unavailable, + xpm=None, + status=_("Unknown")): + """Register a report with the plugin system""" + + if xpm == None: + xpm = no_image() + _reports.append((task, category, name, description, xpm, status)) + +def register_tool(task, name, + category=_("Uncategorized"), + description=_unavailable, + xpm=None, + status=_("Unknown")): + """Register a tool with the plugin system""" + if xpm == None: + xpm = no_image() + _tools.append((task, category, name, description, xpm, status)) + + +def register_text_doc(name,classref, table, paper, style): + """Register a text document generator""" + for n in _textdoc: + if n[0] == name: + return + _textdoc.append((name,classref,table,paper,style)) + +def register_draw_doc(name,classref): + """Register a drawing document generator""" + for n in _drawdoc: + if n[0] == name: + return + _drawdoc.append((name,classref)) + +#------------------------------------------------------------------------- +# +# Image attributes +# +#------------------------------------------------------------------------- +_image_attributes = [] +def register_image_attribute(name): + if name not in _image_attributes: + _image_attributes.append(name) + +def get_image_attributes(): + return _image_attributes + +#------------------------------------------------------------------------- +# +# Building pulldown menus +# +#------------------------------------------------------------------------- +def build_menu(top_menu,list,callback): + report_menu = gtk.Menu() + report_menu.show() + + hash = {} + for report in list: + if hash.has_key(report[1]): + hash[report[1]].append((report[2],report[0])) + else: + hash[report[1]] = [(report[2],report[0])] + + catlist = hash.keys() + catlist.sort() + for key in catlist: + entry = gtk.MenuItem(key) + entry.show() + report_menu.append(entry) + submenu = gtk.Menu() + submenu.show() + entry.set_submenu(submenu) + list = hash[key] + list.sort() + for name in list: + subentry = gtk.MenuItem(name[0]) + subentry.show() + subentry.connect("activate",callback,name[1]) + submenu.append(subentry) + top_menu.set_submenu(report_menu) + +#------------------------------------------------------------------------- +# +# build_report_menu +# +#------------------------------------------------------------------------- +def build_report_menu(top_menu,callback): + build_menu(top_menu,_reports,callback) + +#------------------------------------------------------------------------- +# +# build_tools_menu +# +#------------------------------------------------------------------------- +def build_tools_menu(top_menu,callback): + build_menu(top_menu,_tools,callback) + +#------------------------------------------------------------------------- +# +# build_export_menu +# +#------------------------------------------------------------------------- +def build_export_menu(top_menu,callback): + myMenu = gtk.Menu() + + for report in _exports: + item = gtk.MenuItem(report[1]) + item.connect("activate", callback ,report[0]) + item.show() + myMenu.append(item) + top_menu.set_submenu(myMenu) + +#------------------------------------------------------------------------- +# +# build_import_menu +# +#------------------------------------------------------------------------- +def build_import_menu(top_menu,callback): + myMenu = gtk.Menu() + + for report in _imports: + item = gtk.MenuItem(report[1]) + item.connect("activate", callback ,report[0]) + item.show() + myMenu.append(item) + top_menu.set_submenu(myMenu) + +#------------------------------------------------------------------------- +# +# get_text_doc_menu +# +#------------------------------------------------------------------------- +def get_text_doc_menu(main_menu,tables,callback,obj=None): + + index = 0 + myMenu = gtk.Menu() + _textdoc.sort() + for item in _textdoc: + if tables and item[2] == 0: + continue + name = item[0] + menuitem = gtk.MenuItem(name) + menuitem.set_data("name",item[1]) + menuitem.set_data("styles",item[4]) + menuitem.set_data("paper",item[3]) + menuitem.set_data("obj",obj) + if callback: + menuitem.connect("activate",callback) + menuitem.show() + myMenu.append(menuitem) + if name == GrampsCfg.output_preference: + myMenu.set_active(index) + callback(menuitem) + index = index + 1 + main_menu.set_menu(myMenu) + +#------------------------------------------------------------------------- +# +# get_text_doc_list +# +#------------------------------------------------------------------------- +def get_text_doc_list(): + l = [] + _textdoc.sort() + for item in _textdoc: + l.append(item[0]) + return l + +#------------------------------------------------------------------------- +# +# get_draw_doc_list +# +#------------------------------------------------------------------------- +def get_draw_doc_list(): + + l = [] + _drawdoc.sort() + for item in _drawdoc: + l.append(item[0]) + return l + +#------------------------------------------------------------------------- +# +# get_draw_doc_menu +# +#------------------------------------------------------------------------- +def get_draw_doc_menu(main_menu,callback=None,obj=None): + + index = 0 + myMenu = gtk.Menu() + for (name,classref) in _drawdoc: + menuitem = gtk.MenuItem(name) + menuitem.set_data("name",classref) + menuitem.set_data("obj",obj) + if callback: + menuitem.connect("activate",callback) + menuitem.show() + myMenu.append(menuitem) + if name == GrampsCfg.goutput_preference: + myMenu.set_active(index) + if callback: + callback(menuitem) + index = index + 1 + main_menu.set_menu(myMenu) + +#------------------------------------------------------------------------- +# +# no_image +# +#------------------------------------------------------------------------- +def no_image(): + """Returns XPM data for basic 48x48 icon""" + return [ + "48 48 5 1", + " c None", + ". c #999999", + "+ c #FFFFCC", + "@ c #000000", + "# c #CCCCCC", + " ", + " ", + " ", + " ", + " ", + " ", + " .......... ", + " .++++++++. ", + " .++++++++. ", + " @@@.++++++++. ", + " @##.++++++++. ", + " @# .++++++++. ", + " .......... @# .......... ", + " .++++++++. @# ", + " .++++++++. @# ", + " @@@.++++++++.@@@@# ", + " @##.++++++++.###@# .......... ", + " @# .++++++++. @# .++++++++. ", + " @# .......... @# .++++++++. ", + " @# @@@.++++++++. ", + " @# ##.++++++++. ", + " @# .++++++++. ", + " .......... @# .......... ", + " .++++++++. @# ", + " .++++++++. @# ", + " .++++++++.@@@@# ", + " .++++++++.###@# ", + " .++++++++. @# .......... ", + " .......... @# .++++++++. ", + " @# .++++++++. ", + " @# @@@.++++++++. ", + " @# @##.++++++++. ", + " @# .......... @# .++++++++. ", + " @# .++++++++. @# .......... ", + " @# .++++++++. @# ", + " @@@.++++++++.@@@@# ", + " ##.++++++++.###@# ", + " .++++++++. @# .......... ", + " .......... @# .++++++++. ", + " @# .++++++++. ", + " @@@.++++++++. ", + " ##.++++++++. ", + " .++++++++. ", + " .......... ", + " ", + " ", + " ", + " "] diff --git a/gramps2/src/QuestionDialog.py b/gramps2/src/QuestionDialog.py new file mode 100644 index 000000000..3e9a408dc --- /dev/null +++ b/gramps2/src/QuestionDialog.py @@ -0,0 +1,61 @@ +# +# 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 gnome.ui +import gtk + +class QuestionDialog: + def __init__(self,title,msg,blabel1,task1,blabel2,task2=None): + title = '%s - GRAMPS' % title + + self.top = gtk.Dialog() + self.top.set_title(title) + label = gtk.Label(msg) + label.show() + hbox = gtk.HBox() + image = gtk.Image() + image.set_from_stock(gtk.STOCK_DIALOG_QUESTION,gtk.ICON_SIZE_DIALOG) + hbox.set_spacing(10) + hbox.pack_start(image) + hbox.add(label) + self.top.vbox.pack_start(hbox) + self.top.set_default_size(300,150) + self.task2 = task2 + self.task1 = task1 + self.top.add_button(gtk.STOCK_YES,0) + self.top.add_button(gtk.STOCK_NO,1) + self.top.set_response_sensitive(1,gtk.TRUE) + self.top.set_response_sensitive(0,gtk.TRUE) + self.top.show_all() + if self.top.run(): + self.my_task2() + else: + self.my_task1() + + def my_task1(self): + if self.task1: + self.task1() + self.top.destroy() + + def my_task2(self): + if self.task2: + self.task2() + self.top.destroy() + diff --git a/gramps2/src/QuickAdd.py b/gramps2/src/QuickAdd.py new file mode 100644 index 000000000..9a5fa18e5 --- /dev/null +++ b/gramps2/src/QuickAdd.py @@ -0,0 +1,60 @@ +# +# 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 gtk.glade + +import Utils +import AutoComp +import const +import RelLib + +class QuickAdd: + def __init__(self,db,sex,callback): + self.db = db + self.callback = callback + + self.xml = gtk.glade.XML(const.gladeFile,"addperson") + self.xml.get_widget(sex).set_active(1) + self.xml.signal_autoconnect({ + "on_addfather_close": self.close, + "destroy_passed_object" : Utils.destroy_passed_object + }) + + self.window = self.xml.get_widget("addperson") + self.c = AutoComp.AutoCombo(self.xml.get_widget("surnameCombo"), + self.db.getSurnames()) + + def close(self,obj): + surname = self.xml.get_widget("surname").get_text() + given = self.xml.get_widget("given").get_text() + person = RelLib.Person() + name = person.getPrimaryName() + name.setSurname(surname) + name.setFirstName(given) + self.db.addPerson(person) + if self.xml.get_widget("male").get_active(): + person.setGender(RelLib.Person.male) + self.father = person + else: + person.setGender(RelLib.Person.female) + self.mother = person + Utils.modified() + Utils.destroy_passed_object(self.window) + self.callback(person) diff --git a/gramps2/src/README b/gramps2/src/README new file mode 100644 index 000000000..e69de29bb diff --git a/gramps2/src/ReadXML.py b/gramps2/src/ReadXML.py new file mode 100644 index 000000000..bc6932f73 --- /dev/null +++ b/gramps2/src/ReadXML.py @@ -0,0 +1,199 @@ +# +# 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 string +import os + +#------------------------------------------------------------------------- +# +# Gnome/GTK +# +#------------------------------------------------------------------------- +import gnome.ui #import GnomeErrorDialog + +#------------------------------------------------------------------------- +# +# Gramps Modules +# +#------------------------------------------------------------------------- +from RelLib import * +from GrampsParser import GrampsParser, GrampsImportParser +from intl import gettext +_ = gettext + +#------------------------------------------------------------------------- +# +# Try to detect the presence of gzip +# +#------------------------------------------------------------------------- +try: + import gzip + gzip_ok = 1 +except: + gzip_ok = 0 + +#------------------------------------------------------------------------- +# +# Initialization function for the module. Called to start the reading +# of data. +# +#------------------------------------------------------------------------- +def importData(database, filename, callback): + + basefile = os.path.dirname(filename) + database.smap = {} + database.pmap = {} + database.fmap = {} + + parser = GrampsImportParser(database,callback,basefile) + + if gzip_ok: + use_gzip = 1 + try: + f = gzip.open(filename,"r") + f.read(1) + f.close() + except IOError,msg: + use_gzip = 0 + else: + use_gzip = 0 + + try: + if use_gzip: + xml_file = gzip.open(filename,"rb") + else: + xml_file = open(filename,"r") + except IOError,msg: + GnomeErrorDialog(_("%s could not be opened\n") % filename + str(msg)) + return 0 + except: + GnomeErrorDialog(_("%s could not be opened\n") % filename) + return 0 + + try: + parser.parse(xml_file) + except IOError,msg: + GnomeErrorDialog(_("Error reading %s") % filename + "\n" + str(msg)) + import traceback + traceback.print_exc() + return 0 + except: + import DisplayTrace + DisplayTrace.DisplayTrace() + return 0 + + xml_file.close() + return 1 + +#------------------------------------------------------------------------- +# +# Initialization function for the module. Called to start the reading +# of data. +# +#------------------------------------------------------------------------- +def loadData(database, filename, callback=None): + + basefile = os.path.dirname(filename) + database.smap = {} + database.pmap = {} + database.fmap = {} + + filename = os.path.normpath(filename) + + parser = GrampsParser(database,callback,basefile) + + if gzip_ok: + use_gzip = 1 + try: + f = gzip.open(filename,"r") + f.read(1) + f.close() + except IOError,msg: + use_gzip = 0 + else: + use_gzip = 0 + + try: + if use_gzip: + xml_file = gzip.open(filename,"rb") + else: + xml_file = open(filename,"r") + except IOError,msg: + filemsg = _("%s could not be opened\n") % filename + GnomeErrorDialog(filemsg + str(msg)) + return 0 + except: + GnomeErrorDialog(_("%s could not be opened\n") % filename) + return 0 + + try: + parser.parse(xml_file) + except IOError,msg: + errmsg = "%s\n%s" % (_("Error reading %s") % filename,str(msg)) + GnomeErrorDialog(errmsg) + import traceback + traceback.print_exc() + return 0 + except: + GnomeErrorDialog(_("Error reading %s") % filename) + import traceback + traceback.print_exc() + return 0 + + xml_file.close() + return 1 + +#------------------------------------------------------------------------- +# +# Initialization function for the module. Called to start the reading +# of data. +# +#------------------------------------------------------------------------- +def loadRevision(database, file, filename, revision, callback=None): + + basefile = os.path.dirname(filename) + database.smap = {} + database.pmap = {} + database.fmap = {} + + parser = GrampsParser(database,callback,basefile) + + filename = _("%s (revision %s)") % (filename,revision) + + try: + parser.parse(file) + except IOError,msg: + errmsg = "%s\n%s" % (_("Error reading %s") % filename, str(msg)) + GnomeErrorDialog(errmsg) + import traceback + traceback.print_exc() + return 0 + except: + import DisplayTrace + DisplayTrace.DisplayTrace() + return 0 + + file.close() + return 1 diff --git a/gramps2/src/RelImage.py b/gramps2/src/RelImage.py new file mode 100644 index 000000000..924b33360 --- /dev/null +++ b/gramps2/src/RelImage.py @@ -0,0 +1,179 @@ +# +# 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 +import string + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk +#from gnome.ui import GnomeErrorDialog, GnomeWarningDialog + +#------------------------------------------------------------------------- +# +# Gramps modules +# +#------------------------------------------------------------------------- +import const +import Utils +import ImgManip +from intl import gettext +_ = gettext + + +#------------------------------------------------------------------------- +# +# import_media_object +# +#------------------------------------------------------------------------- +def import_media_object(filename,path,base): + import shutil + + if not os.path.exists(filename): + GnomeErrorDialog(_("Could not import %s\nThe file has been moved or deleted") % filename) + return "" + + ext = os.path.splitext(filename)[1] + + type = Utils.get_mime_type(filename) + if type[0:5] == "image": + name = "%s/%s%s" % (path,base,ext) + #base = "%s%s" % (base,ext) + + thumb = "%s/.thumb" % (path) + + try: + if not os.path.exists(thumb): + os.mkdir(thumb) + except IOError,msg: + GnomeErrorDialog(_("Could not create %s") % thumb + "\n" + str(msg)) + return "" + except: + GnomeErrorDialog(_("Could not create %s") % thumb) + return "" + + try: + path = "%s/%s.jpg" % (thumb,base) + mk_thumb(filename,path,const.thumbScale) + except: + GnomeErrorDialog(_("Error creating the thumbnail : %s")) + return "" + + try: + shutil.copy(filename,name) + except IOError,msg: + GnomeErrorDialog(_("Error copying %s") % filename + "\n" + msg) + return "" + + else: + bname = os.path.basename(filename) + l = string.split(bname,'.') + name = "%s/%s.%s" % (path,base,l[-1]) + shutil.copy(filename,name) + + return name + +#------------------------------------------------------------------------- +# +# scale_image +# +#------------------------------------------------------------------------- +def scale_image(path,size): + try: + image1 = gtk.gdk.pixbuf_new_from_file(path) + except: + GnomeWarningDialog(_("Could not load image file %s") % path) + return gtk.gdk.pixbuf_new_from_file(const.icon) + + width = image1.get_width() + height = image1.get_height() + + scale = size / float(max(width,height)) + try: + image1.scale_simple(int(scale*width), int(scale*height), gtk.gdk.INTERP_BILINEAR) + return image1 + except: + GnomeWarningDialog(_("Could not load image file %s") % path) + return gtk.gdk.pixbuf_new_from_file(const.icon) + +#------------------------------------------------------------------------- +# +# scale_image +# +#------------------------------------------------------------------------- +def mk_thumb(source,dest,size): + dir = os.path.dirname(dest) + + source = os.path.normpath(source) + dest = os.path.normpath(dest) + + try: + if not os.path.exists(dir): + os.mkdir(dir) + except IOError,msg: + GnomeErrorDialog(_("Could not create %s") % dir + "\n" + str(msg)) + return + except: + GnomeErrorDialog(_("Could not create %s") % dir) + return + + if os.path.exists(dest): + try: + os.remove(dest) + except IOError,msg: + errmsg = _("Could not replace %s") % dir + GnomeErrorDialog(errmsg + "\n" + msg) + return + + if not os.path.exists(source): + GnomeErrorDialog(_("Could not create a thumbnail for %s\nThe file has been moved or deleted") % source) + + try: + img = ImgManip.ImgManip(source) + img.jpg_thumbnail(dest,size,size) + except: + import sys + msg = "%s\n%s %s" % (source,sys.exc_type,sys.exc_value) + GnomeErrorDialog(_("Could not create a thumbnail for %s") % msg) + return + +#------------------------------------------------------------------------- +# +# scale_image +# +#------------------------------------------------------------------------- +def check_thumb(source,dest,size): + if not os.path.isfile(source): + return 0 + if not os.path.isfile(dest): + mk_thumb(source,dest,size) + elif os.path.getmtime(source) > os.path.getmtime(dest): + mk_thumb(source,dest,size) + return 1 + + diff --git a/gramps2/src/RelLib.py b/gramps2/src/RelLib.py new file mode 100644 index 000000000..29c953498 --- /dev/null +++ b/gramps2/src/RelLib.py @@ -0,0 +1,2404 @@ +# +# 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 +# + +"""The core library of the GRAMPS database""" + +__author__ = "Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# standard python modules +# +#------------------------------------------------------------------------- +from re import compile +from string import strip, upper +import os + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +from Date import Date, compare_dates, not_too_old +import sort +import const + +#------------------------------------------------------------------------- +# +# Attempt to load the ZODB libraries, otherwise provide alternates +# +#------------------------------------------------------------------------- +try: + from ZODB import Persistent +except ImportError: + class Persistent: + """Dummy class used if ZODB is not installed on the system""" + pass + +#------------------------------------------------------------------------- +# +# Confidence levels +# +#------------------------------------------------------------------------- + +CONF_VERY_HIGH = 4 +CONF_HIGH = 3 +CONF_NORMAL = 2 +CONF_LOW = 1 +CONF_VERY_LOW = 0 + +#------------------------------------------------------------------------- +# +# ID regular expression +# +#------------------------------------------------------------------------- +_id_reg = compile("%\d+d") + + +def extlist(lst): + """Returns a copy of the passed list""" + return lst[:] # Make a copy. + +def extmap(map): + """Returns a map""" + return map + + +class SourceNote(Persistent): + """Base class for storing source references and notes""" + + def __init__(self,source=None): + """Create a new SourceNote, copying from source if not None""" + + self.source_list = [] + + if source: + if len(source.source_list) > 0: + for sref in source.source_list: + self.source_list.append(SourceRef(sref)) + if source.note: + self.note = Note(source.note.get()) + else: + self.note = None + else: + self.note = None + + def addSourceRef(self,id) : + """Set the source reference""" + self.source_list.append(id) + self._p_changed = 1 + + def getSourceRefList(self) : + """Return the source reference""" + return extlist(self.source_list) + + def setSourceRefList(self,list) : + """Replaces the source reference""" + self.source_list = list + + def setNote(self,text): + """Set the note to the given text""" + if self.note == None: + self.note = Note() + self.note.set(text) + + def getNote(self): + """Return the current note""" + if self.note == None: + return "" + else: + return self.note.get() + + def setNoteObj(self,obj): + """Change the note object instance to obj""" + self.note = obj + + def getNoteObj(self): + """Return in note instance, not just the text""" + return self.note + + def unique_note(self): + """Creates a unique instance of the current note""" + self.note = Note(self.note.get()) + +class LdsOrd(SourceNote): + """LDS Ordinance support""" + def __init__(self,source=None): + """Creates a LDS Ordinance instance""" + SourceNote.__init__(self,source) + if source: + self.famc = source.famc + self.date = Date(source.date) + self.temple = source.temple + self.status = source.status + self.place = source.place + else: + self.famc = None + self.date = None + self.temple = "" + self.status = 0 + self.place = None + + def getPlaceName(self): + """returns the title of the Place associated with the Ordinance""" + if self.place: + return self.place.get_title() + else: + return "" + + def setPlace(self,place): + """sets the Place instance of the Event""" + self.place = place + + def getPlace(self): + """returns the Place instance of the Event""" + return self.place + + def setFamily(self,family): + """Sets the family associated with the LDS ordinance""" + self.famc = family + + def getFamily(self): + """Gets the family associated with the LDS ordinance""" + return self.famc + + def setStatus(self,val): + """Sets the status of the LDS ordinance""" + self.status = val + + def getStatus(self): + """Gets the status of the LDS ordinance""" + return self.status + + def setDate(self, date) : + """attempts to sets the date of the LdsOrd instance""" + if not self.date: + self.date = Date() + self.date.set(date) + + def getDate(self) : + """returns a string representation of the date of the LdsOrd instance""" + if self.date: + return self.date.getDate() + return "" + + def getDateObj(self): + """returns the Date object associated with the LdsOrd""" + if not self.date: + self.date = Date() + return self.date + + def setDateObj(self,date): + """sets the Date object associated with the LdsOrd""" + self.date = date + + def setTemple(self,temple): + """Sets the temple assocated with the LDS ordinance""" + self.temple = temple + + def getTemple(self): + """Gets the temple assocated with the LDS ordinance""" + return self.temple + + def are_equal(self,other): + """returns 1 if the spdcified ordinance is the same as the instance""" + if other == None: + return 0 + if (self.famc != other.famc or + self.place != other.place or + self.temple != other.temple or + compare_dates(self.getDateObj(),other.getDateObj()) or + len(self.getSourceRefList()) != len(other.getSourceRefList())): + return 0 + + index = 0 + olist = other.getSourceRefList() + for a in self.getSourceRefList(): + if not a.are_equal(olist[index]): + return 0 + index = index + 1 + return 1 + +class DataObj(SourceNote): + """Base class for data elements, providing source, note, and privacy data""" + + def __init__(self,source=None): + """Create a new DataObj, copying data from a source object if provided""" + SourceNote.__init__(self,source) + + if source: + self.private = source.private + else: + self.private = 0 + + def setPrivacy(self,val): + """Sets or clears the privacy flag of the data""" + self.private = val + + def getPrivacy(self): + """Returns the privacy level of the data""" + return self.private + +class Place(SourceNote): + """Contains information related to a place, including multiple address + information (since place names can change with time), longitude, latitude, + a collection of images and URLs, a note and a source""" + + def __init__(self,source=None): + """Creates a new Place object. + + source - Object to copy. If none supplied, create an empty place object""" + + SourceNote.__init__(self,source) + if source: + self.long = source.log + self.lat = source.lat + self.title = source.title + self.main_loc = Location(source.main_loc) + self.alt_loc = [] + for loc in source.alt_loc: + self.alt_loc = Location(loc) + self.id = source.id + self.urls = [] + for u in source.urls: + self.urls.append(Url(u)) + self.photoList = [] + for photo in source.photoList: + self.photoList.append(ObjectRef(photo)) + else: + self.long = "" + self.lat = "" + self.title = "" + self.main_loc = None + self.alt_loc = [] + self.id = "" + self.urls = [] + self.photoList = [] + + def getUrlList(self): + """Return the list of URLs""" + return extlist(self.urls) + + def setUrlList(self,list): + """Replace the current URL list with the new one""" + self.urls = list + + def addUrl(self,url): + """Add a URL to the URL list""" + self.urls.append(url) + self._p_changed = 1 + + def setId(self,id): + """Sets the gramps ID for the place object""" + self.id = id + + def getId(self): + """Returns the gramps ID for the place object""" + return self.id + + def set_title(self,name): + """Sets the title of the place object""" + self.title = name + + def get_title(self): + """Returns the title of the place object""" + return self.title + + def set_longitude(self,long): + """Sets the longitude of the place""" + self.long = long + + def get_longitude(self): + """Returns the longitude of the place""" + return self.long + + def set_latitude(self,long): + """Sets the latitude of the place""" + self.lat = long + + def get_latitude(self): + """Returns the latitude of the place""" + return self.lat + + def get_main_location(self): + """Returns the Location object representing the primary information""" + if not self.main_loc: + self.main_loc = Location() + return self.main_loc + + def set_main_location(self,loc): + """Assigns the main location to the Location object passed""" + self.main_loc = loc + + def get_alternate_locations(self): + """Returns a list of alternate location information objects""" + return extlist(self.alt_loc) + + def set_alternate_locations(self,list): + """Replaces the current alternate location list with the new one""" + self.alt_loc = list + + def add_alternate_locations(self,loc): + """Adds a Location to the alternate location list""" + if loc not in self.alt_loc: + self.alt_loc.append(loc) + self._p_changed = 1 + + def addPhoto(self,photo): + """Adds a Photo object to the place object's image list""" + self.photoList.append(photo) + self._p_changed = 1 + + def getPhotoList(self): + """Returns the list of Photo objects""" + return extlist(self.photoList) + + def setPhotoList(self,list): + """Sets the list of Photo objects""" + self.photoList = list + + def getDisplayInfo(self): + """Gets the display information associated with the object. This includes + the information that is used for display and for sorting. Returns a list + consisting of 13 strings. These are: Place Title, Place ID, Main Location + Parish, Main Location County, Main Location City, Main Location State/Province, + Main Location Country, upper case Place Title, upper case Parish, upper + case city, upper case county, upper case state, upper case country""" + + if self.main_loc: + return [self.title,self.id,self.main_loc.parish,self.main_loc.city, + self.main_loc.county,self.main_loc.state,self.main_loc.country, + upper(self.title), upper(self.main_loc.parish), + upper(self.main_loc.city), upper(self.main_loc.county), + upper(self.main_loc.state), upper(self.main_loc.country)] + else: + return [self.title,self.id,'','','','','',upper(self.title), '','','','',''] + +class Researcher(Persistent): + """Contains the information about the owner of the database""" + + def __init__(self): + """Initializes the Researcher object""" + self.name = "" + self.addr = "" + self.city = "" + self.state = "" + self.country = "" + self.postal = "" + self.phone = "" + self.email = "" + + def getName(self): + """returns the database owner's name""" + return self.name + + def getAddress(self): + """returns the database owner's address""" + return self.addr + + def getCity(self): + """returns the database owner's city""" + return self.city + + def getState(self): + """returns the database owner's state""" + return self.state + + def getCountry(self): + """returns the database owner's country""" + return self.country + + def getPostalCode(self): + """returns the database owner's postal code""" + return self.postal + + def getPhone(self): + """returns the database owner's phone number""" + return self.phone + + def getEmail(self): + """returns the database owner's email""" + return self.email + + def set(self,name,addr,city,state,country,postal,phone,email): + """sets the information about the database owner""" + if name: + self.name = strip(name) + if addr: + self.addr = strip(addr) + if city: + self.city = strip(city) + if state: + self.state = strip(state) + if country: + self.country = strip(country) + if postal: + self.postal = strip(postal) + if phone: + self.phone = strip(phone) + if email: + self.email = strip(email) + +class Location(Persistent): + """Provides information about a place, including city, county, state, + and country. Multiple Location objects can represent the same place, + since names of citys, countys, states, and even countries can change + with time""" + + def __init__(self,source=None): + """creates a Location object, copying from the source object if it exists""" + if source: + self.city = source.city + self.parish = source.parish + self.county = source.county + self.state = source.state + self.country = source.country + else: + self.city = "" + self.parish = "" + self.county = "" + self.state = "" + self.country = "" + + def is_empty(self): + return self.city=="" and self.county=="" and self.state=="" and self.country=="" + + def set_city(self,data): + """sets the city name of the Location object""" + self.city = data + + def get_city(self): + """returns the city name of the Location object""" + return self.city + + def set_parish(self,data): + """sets the religious parish name""" + self.parish = data + + def get_parish(self): + """gets the religious parish name""" + return self.parish + + def set_county(self,data): + """sets the county name of the Location object""" + self.county = data + + def get_county(self): + """returns the county name of the Location object""" + return self.county + + def set_state(self,data): + """sets the state name of the Location object""" + self.state = data + + def get_state(self): + """returns the state name of the Location object""" + return self.state + + def set_country(self,data): + """sets the country name of the Location object""" + self.country = data + + def get_country(self): + """returns the country name of the Location object""" + return self.country + +class Note(Persistent): + """Provides general text information""" + + def __init__(self,text = ""): + """create a new Note object from the passed string""" + self.text = text + + def set(self,text): + """set the note contents to the passed string""" + self.text = text + + def get(self): + """return the note contents""" + return self.text + + def append(self,text): + """adds the text to the note's contents""" + self.text = self.text + text + +class Photo(SourceNote): + """Containter for information about an image file, including location, + description and privacy""" + + def __init__(self,source=None): + """Create a new Photo object, copying from the source if provided""" + + SourceNote.__init__(self,source) + + self.attrlist = [] + if source: + self.path = source.path + self.mime = source.mime + self.local = source.local + self.desc = source.desc + self.id = source.id + for attr in source.attrlist: + self.attrlist.append(Attribute(attr)) + else: + self.id = "" + self.local = 0 + self.path = "" + self.mime = "" + self.desc = "" + + def setLocal(self,val): + """set or clear the local flag""" + self.local = val + + def getLocal(self): + """return the local flag""" + return self.local + + def setId(self,id): + """Sets the gramps ID for the place object""" + self.id = id + + def getId(self): + """Returns the gramps ID for the place object""" + return self.id + + def setMimeType(self,type): + self.mime = type + + def getMimeType(self): + return self.mime + + def setPath(self,path): + """set the file path to the passed path""" + self.path = os.path.normpath(path) + + def getPath(self): + """return the file path""" + return self.path + + def setDescription(self,text): + """sets the description of the image""" + self.desc = text + + def getDescription(self): + """returns the description of the image""" + return self.desc + + def addAttribute(self,attr): + """Adds a propery to the Photo object. This is not used by gramps, + but provides a means for XML users to attach other properties to + the image""" + self.attrlist.append(attr) + self._p_changed = 1 + + def getAttributeList(self): + """returns the property list associated with the image""" + return extlist(self.attrlist) + + def setAttributeList(self,list): + self.attrlist = list + + +class ObjectRef(Persistent): + """Object reference class""" + def __init__(self,source=None): + self.attrlist = [] + if source: + self.private = source.private + self.ref = source.ref + self.note = Note(source.note) + for attr in source.attrlist: + self.attrlist.append(Attribute(attr)) + else: + self.private = 0 + self.ref = None + self.note = None + + def setPrivacy(self,val): + """Sets or clears the privacy flag of the data""" + self.private = val + + def getPrivacy(self): + """Returns the privacy level of the data""" + return self.private + + def setReference(self,obj): + self.ref = obj + + def getReference(self): + return self.ref + + def setNote(self,text): + """Set the note to the given text""" + if self.note == None: + self.note = Note() + self.note.set(text) + + def getNote(self): + """Return the current note""" + if self.note == None: + return "" + else: + return self.note.get() + + def setNoteObj(self,obj): + """Change the note object instance to obj""" + self.note = obj + + def getNoteObj(self): + """Return in note instance, not just the text""" + return self.note + + def unique_note(self): + """Creates a unique instance of the current note""" + self.note = Note(self.note.get()) + + def addAttribute(self,attr): + """Adds a propery to the Photo object. This is not used by gramps, + but provides a means for XML users to attach other properties to + the image""" + self.attrlist.append(attr) + self._p_changed = 1 + + def getAttributeList(self): + """returns the property list associated with the image""" + return extlist(self.attrlist) + + def setAttributeList(self,list): + """sets the property list associated with the image""" + self.attrlist = list + + +class Attribute(DataObj): + """Provides a simple key/value pair for describing properties. Used + by the Person and Family objects to store descriptive information.""" + + def __init__(self,source=None): + """creates a new Attribute object, copying from the source if provided""" + DataObj.__init__(self,source) + + if source: + self.type = source.type + self.value = source.value + else: + self.type = "" + self.value = "" + + def setType(self,val): + """sets the type (or key) of the Attribute instance""" + self.type = val + + def getType(self): + """returns the type (or key) or the Attribute instance""" + return self.type + + def setValue(self,val): + """sets the value of the Attribute instance""" + self.value = val + + def getValue(self): + """returns the value of the Attribute instance""" + return self.value + + +class Address(DataObj): + """Provides address information for a person""" + + def __init__(self,source=None): + """Creates a new Address instance, copying from the source + if provided""" + DataObj.__init__(self,source) + + if source: + self.street = source.street + self.city = source.city + self.state = source.state + self.country = source.country + self.postal = source.postal + self.date = Date(source.date) + else: + self.street = "" + self.city = "" + self.state = "" + self.country = "" + self.postal = "" + self.date = Date() + + def setDate(self,text): + """attempts to sets the date that the person lived at the address + from the passed string""" + self.date.set(text) + + def getDate(self): + """returns a string representation of the date that the person + lived at the address""" + return self.date.getDate() + + def getPrefDate(self): + """returns a string representation of the date that the person + lived at the address""" + return self.date.getPrefDate() + + def getDateObj(self): + """returns the Date object associated with the Address""" + return self.date + + def setDateObj(self,obj): + """sets the Date object associated with the Address""" + self.date = obj + + def setStreet(self,val): + """sets the street portion of the Address""" + self.street = val + + def getStreet(self): + """returns the street portion of the Address""" + return self.street + + def setCity(self,val): + """sets the city portion of the Address""" + self.city = val + + def getCity(self): + """returns the city portion of the Address""" + return self.city + + def setState(self,val): + """sets the state portion of the Address""" + self.state = val + + def getState(self): + """returns the state portion of the Address""" + return self.state + + def setCountry(self,val): + """sets the country portion of the Address""" + self.country = val + + def getCountry(self): + """returns the country portion of the Address""" + return self.country + + def setPostal(self,val): + """sets the postal code of the Address""" + self.postal = val + + def getPostal(self): + """returns the postal code of the Address""" + return self.postal + + +class Name(DataObj): + """Provides name information about a person. A person may have more + that one name throughout his or her life.""" + + def __init__(self,source=None): + """creates a new Name instance, copying from the source if provided""" + DataObj.__init__(self,source) + + if source: + self.FirstName = source.FirstName + self.Surname = source.Surname + self.Suffix = source.Suffix + self.Title = source.Title + self.type = source.type + else: + self.FirstName = "" + self.Surname = "" + self.Suffix = "" + self.Title = "" + self.type = "" + + def setType(self,type): + """sets the type of the Name instance""" + self.type = type + + def getType(self): + """returns the type of the Name instance""" + return self.type + + def setFirstName(self,name): + """sets the given name for the Name instance""" + self.FirstName = name + + def setSurname(self,name): + """sets the surname (or last name) for the Name instance""" + self.Surname = name + + def setSuffix(self,name): + """sets the suffix (such as Jr., III, etc.) for the Name instance""" + self.Suffix = name + + def getFirstName(self): + """returns the given name for the Name instance""" + return self.FirstName + + def getSurname(self): + """returns the surname (or last name) for the Name instance""" + return self.Surname + + def getSuffix(self): + """returns the suffix for the Name instance""" + return self.Suffix + + def setTitle(self,title): + """sets the title (Dr., Reverand, Captain) for the Name instance""" + self.Title = title + + def getTitle(self): + """returns the title for the Name instance""" + return self.Title + + def getName(self): + """returns a name string built from the components of the Name + instance, in the form of Surname, Firstname""" + + if (self.Suffix == ""): + return "%s, %s" % (self.Surname, self.FirstName) + else: + return "%s, %s %s" % (self.Surname, self.FirstName, self.Suffix) + + def getRegularName(self): + """returns a name string built from the components of the Name + instance, in the form of Firstname Surname""" + if (self.Suffix == ""): + return "%s %s" % (self.FirstName, self.Surname) + else: + return "%s %s, %s" % (self.FirstName, self.Surname, self.Suffix) + + def are_equal(self,other): + """compares to names to see if they are equal, return 0 if they + are not""" + if self.FirstName != other.FirstName: + return 0 + if self.Surname != other.Surname: + return 0 + if self.Suffix != other.Suffix: + return 0 + if self.Title != other.Title: + return 0 + if self.type != other.type: + return 0 + if self.private != other.private: + return 0 + if self.getNote() != other.getNote(): + return 0 + if len(self.getSourceRefList()) != len(other.getSourceRefList()): + return 0 + index = 0 + olist = other.getSourceRefList() + for a in self.getSourceRefList(): + if not a.are_equal(olist[index]): + return 0 + index = index + 1 + return 1 + +class Url(Persistent): + """Contains information related to internet Uniform Resource Locators, + allowing gramps to store information about internet resources""" + + def __init__(self,source=None): + """creates a new URL instance, copying from the source if present""" + if source: + self.path = source.path + self.desc = source.desc + self.private = source.private + else: + self.path = "" + self.desc = "" + self.private = 0 + + def setPrivacy(self,val): + """sets the privacy flag for the URL instance""" + self.private = val + + def getPrivacy(self): + """returns the privacy flag for the URL instance""" + return self.private + + def set_path(self,path): + """sets the URL path""" + self.path = path + + def get_path(self): + """returns the URL path""" + return self.path + + def set_description(self,description): + """sets the description of the URL""" + self.desc = description + + def get_description(self): + """returns the description of the URL""" + return self.desc + + def are_equal(self,other): + """returns 1 if the specified URL is the same as the instance""" + if other == None: + return 0 + if self.path != other.path: + return 0 + if self.desc != other.desc: + return 0 + return 1 + + +class Person(Persistent): + """Represents an individual person in the gramps database""" + + unknown = 2 + male = 1 + female = 0 + + def __init__(self): + """creates a new Person instance""" + + self.id = "" + self.PrimaryName = None + self.EventList = [] + self.FamilyList = [] + self.AltFamilyList = [] + self.photoList = [] + self.nickname = "" + self.alternateNames = [] + self.gender = 2 + self.death = None + self.birth = None + self.addressList = [] + self.attributeList = [] + self.urls = [] + self.note = None + self.paf_uid = "" + self.position = None + self.ancestor = None + self.lds_bapt = None + self.lds_endow = None + self.lds_seal = None + + def getDisplayInfo(self): + if self.gender == Person.male: + gender = const.male + elif self.gender == Person.female: + gender = const.female + else: + gender = const.unknown + bday = self.getBirth().getDateObj() + dday = self.getDeath().getDateObj() + return [self.getPrimaryName().getName(),self.id,gender, + bday.getQuoteDate(), dday.getQuoteDate(), + sort.build_sort_name(self.getPrimaryName()), + sort.build_sort_date(bday),sort.build_sort_date(dday)] + + + def setPrimaryName(self,name): + """sets the primary name of the Person to the specified + Name instance""" + self.PrimaryName = name + + def getPrimaryName(self): + """returns the Name instance marked as the Person's primary name""" + if not self.PrimaryName: + self.PrimaryName = Name() + return self.PrimaryName + + def setPafUid(self,val): + """sets Personal Ancestral File UID value""" + self.paf_uid = val + + def getPafUid(self) : + """returns the Personal Ancestral File UID value""" + return self.paf_uid + + def getAlternateNames(self): + """returns the list of alternate Names""" + return extlist(self.alternateNames) + + def setAlternateNames(self,list): + """changes the list of alternate names to the passed list""" + self.alternateNames = list + + def addAlternateName(self,name): + """adds an alternate Name instance to the list""" + self.alternateNames.append(name) + self._p_changed = 1 + + def getUrlList(self): + """returns the list of URL instances""" + return extlist(self.urls) + + def setUrlList(self,list): + """sets the list of URL instances to list""" + self.urls = list + + def addUrl(self,url): + """adds a URL instance to the list""" + self.urls.append(url) + self._p_changed = 1 + + def setId(self,id): + """sets the gramps ID for the Person""" + self.id = str(id) + + def getId(self): + """returns the gramps ID for the Person""" + return self.id + + def setNickName(self,name): + """sets the nickname for the Person""" + self.nickname = name + + def getNickName(self) : + """returns the nickname for the Person""" + return self.nickname + + def setGender(self,val) : + """sets the gender of the Person""" + self.gender = val + + def getGender(self) : + """returns the gender of the Person""" + return self.gender + + def setBirth(self,event) : + """sets the birth event to the passed event""" + self.birth = event + + def setDeath(self,event) : + """sets the death event to the passed event""" + self.death = event + + def getBirth(self) : + """returns the birth event""" + if self.birth == None: + self.birth = Event() + self.birth.name = "Birth" + return self.birth + + def getDeath(self) : + """returns the death event""" + if self.death == None: + self.death = Event() + self.death.name = "Death" + return self.death + + def addPhoto(self,photo): + """adds a Photo instance to the image list""" + self.photoList.append(photo) + self._p_changed = 1 + + def getPhotoList(self): + """returns the list of Photos""" + return extlist(self.photoList) + + def setPhotoList(self,list): + """Sets the list of Photo objects""" + self.photoList = list + + def addEvent(self,event): + """adds an Event to the event list""" + self.EventList.append(event) + self._p_changed = 1 + + def getEventList(self): + """returns the list of Event instances""" + return extlist(self.EventList) + + def setEventList(self,list): + """sets the event list to the passed list""" + self.EventList = list + + def addFamily(self,family): + """adds the specified Family instance to the list of + families/marriages/partnerships in which the person is a + parent or spouse""" + self.FamilyList.append(family) + self._p_changed = 1 + + def setPreferred(self,family): + if family in self.FamilyList: + self.FamilyList.remove(family) + self.FamilyList = [family] + self.FamilyList + + def getFamilyList(self) : + """returns the list of Family instances in which the + person is a parent or spouse""" + return extlist(self.FamilyList) + + def clearFamilyList(self) : + self.FamilyList = [] + + def removeFamily(self,family): + """removes the specified Family instance from the list + of marriages/partnerships""" + if family in self.FamilyList: + self.FamilyList.remove(family) + self._p_changed = 1 + + def addAddress(self,address): + """adds the Address instance to the list of addresses""" + self.addressList.append(address) + self._p_changed = 1 + + def removeAddress(self,address): + """removes the Address instance from the list of addresses""" + if address in self.addressList: + self.addressList.remove(address) + self._p_changed = 1 + + def getAddressList(self): + """returns the list of addresses""" + return extlist(self.addressList) + + def setAddressList(self,list): + """sets the address list to the specified list""" + self.addressList = list + + def addAttribute(self,attribute): + """adds an Attribute instance to the attribute list""" + self.attributeList.append(attribute) + self._p_changed = 1 + + def removeAttribute(self,attribute): + """removes the specified Attribute instance from the attribute list""" + if attribute in self.attributeList: + self.attributeList.remove(attribute) + self._p_changed = 1 + + def getAttributeList(self): + """returns the attribute list""" + return extlist(self.attributeList) + + def setAttributeList(self,list): + """sets the attribute list to the specified list""" + self.attributeList = list + + def getParentList(self): + """returns the list of alternate Family instances, in which the Person + is a child of the family, but not a natural child of both parents""" + return extlist(self.AltFamilyList) + + def addAltFamily(self,family,mrel,frel): + """adds a Family to the alternate family list, indicating the + relationship to the mother (mrel) and the father (frel)""" + self.AltFamilyList.append((family,mrel,frel)) + self._p_changed = 1 + + def clearAltFamilyList(self): + self.AltFamilyList = [] + + def removeAltFamily(self,family): + """removes a Family instance from the alternate family list""" + for f in self.AltFamilyList[:]: + if f[0] == family: + self.AltFamilyList.remove(f) + self._p_changed = 1 + return f + else: + return None + + def has_family(self,family): + for f in self.AltFamilyList: + if f[0] == family: + return f + else: + return None + + def setMainParents(self,family): + """sets the main Family of the Person, the Family in which the + Person is a natural born child""" + f = self.removeAltFamily(family) + if f: + self.AltFamilyList = [f] + self.AltFamilyList + + def getMainParents(self): + """returns the main Family of the Person, the Family in which the + Person is a natural born child""" + if len(self.AltFamilyList) == 0: + return None + else: + return self.AltFamilyList[0][0] + + def getMainParentsRel(self): + """returns the main Family of the Person, the Family in which the + Person is a natural born child""" + if len(self.AltFamilyList) == 0: + return (None,None,None) + else: + return self.AltFamilyList[0] + + def setNote(self,text): + """sets the note attached to the Person to the passed text""" + if self.note == None: + self.note = Note() + self.note.set(text) + + def getNote(self) : + """returns the text of the note attached to the Person""" + if self.note == None: + return "" + else: + return self.note.get() + + def setNoteObj(self,note): + """sets the Note instance attached to the Person""" + self.note = note + + def getNoteObj(self): + """returns the Note instance attached to the Person""" + if self.note == None: + self.note = Note() + return self.note + + def unique_note(self): + """Creates a unique instance of the current note""" + self.note = Note(self.note.get()) + + def setPosition(self,pos): + """sets a graphical location pointer for graphic display (x,y)""" + self.position = pos + + def getPosition(self): + """returns a graphical location pointer for graphic display (x,y)""" + return self.position + + def setAncestor(self, value): + """set ancestor flag and recurse""" + self.ancestor = value + for (family,m,f) in self.AltFamilyList: + if family.Father: + # Don't waste time if the ancestor is already flagged. + # This will happen when cousins marry. + if not family.Father.getAncestor(): + family.Father.setAncestor(value) + if family.getMother(): + if not family.Mother.getAncestor(): + family.Mother.setAncestor(value) + + def getAncestor(self): + return self.ancestor + + def setLdsBaptism(self,ord): + self.lds_bapt = ord + + def getLdsBaptism(self): + return self.lds_bapt + + def setLdsEndowment(self,ord): + self.lds_endow = ord + + def getLdsEndowment(self): + return self.lds_endow + + def setLdsSeal(self,ord): + self.lds_seal = ord + + def getLdsSeal(self): + return self.lds_seal + + def probablyAlive(self): + if self.death.getDate() != "": + return 0 + if self.birth.getDate() != "": + return not_too_old(self.birth.getDateObj().get_start_date()) + return 1 + + +class Event(DataObj): + """Event record, recording the event type, description, place, and date + of a particular event""" + + def __init__(self,source=None): + """creates a new Event instance, copying from the source if present""" + + DataObj.__init__(self,source) + + if source: + self.place = source.place + self.date = Date(source.date) + self.description = source.description + self.name = source.name + self.cause = source.cause + else: + self.place = None + self.date = None + self.description = "" + self.name = "" + self.cause = "" + + def is_empty(self): + date = self.getDateObj() + place = self.getPlace() + description = self.description + name = self.name + if (not name or name == "Birth" or name == "Death") and \ + date.isEmpty() and not place and not description: + return 1 + else: + return 0 + + def set(self,name,date,place,description): + """sets the name, date, place, and description of an Event instance""" + self.name = name + self.place = place + self.description = description + self.setDate(date) + + def are_equal(self,other): + """returns 1 if the specified event is the same as the instance""" + if other == None: + return 0 + if (self.name != other.name or self.place != other.place or + self.description != other.description or self.cause != other.cause or + self.private != other.private or + compare_dates(self.getDateObj(),other.getDateObj()) or + len(self.getSourceRefList()) != len(other.getSourceRefList())): + return 0 + + index = 0 + olist = other.getSourceRefList() + for a in self.getSourceRefList(): + if not a.are_equal(olist[index]): + return 0 + index = index + 1 + + return 1 + + def setName(self,name): + """sets the name of the Event""" + self.name = name + + def getName(self): + """returns the name of the Event""" + return self.name + + def setPlace(self,place): + """sets the Place instance of the Event""" + self.place = place + + def getPlace(self): + """returns the Place instance of the Event""" + return self.place + + def setCause(self,cause): + """sets the cause of the Event""" + self.cause = cause + + def getCause(self): + """returns the cause of the Event""" + return self.cause + + def getPlaceName(self): + """returns the title of the Place associated with the Event""" + if self.place: + return self.place.get_title() + else: + return "" + + def setDescription(self,description): + """sets the description of the Event instance""" + self.description = description + + def getDescription(self) : + """returns the description of the Event instance""" + return self.description + + def setDate(self, date) : + """attempts to sets the date of the Event instance""" + if not self.date: + self.date = Date() + self.date.set(date) + + def getDate(self) : + """returns a string representation of the date of the Event instance""" + if self.date: + return self.date.getDate() + return "" + + def getPrefDate(self) : + """returns a string representation of the date of the Event instance""" + if self.date: + return self.date.getDate() + return "" + + def getQuoteDate(self) : + """returns a string representation of the date of the Event instance, + enclosing the results in quotes if it is not a valid date""" + if self.date: + return self.date.getQuoteDate() + return "" + + def getDateObj(self): + """returns the Date object associated with the Event""" + if not self.date: + self.date = Date() + return self.date + + def setDateObj(self,date): + """sets the Date object associated with the Event""" + self.date = date + + +class Family(Persistent): + """Represents a family unit in the gramps database""" + + def __init__(self): + """creates a new Family instance""" + self.Father = None + self.Mother = None + self.Children = [] + self.Marriage = None + self.Divorce = None + self.type = "Married" + self.EventList = [] + self.id = "" + self.photoList = [] + self.note = Note() + self.attributeList = [] + self.position = None + self.lds_seal = None + + def setLdsSeal(self,ord): + self.lds_seal = ord + + def getLdsSeal(self): + return self.lds_seal + + def setPosition(self,pos): + """sets a graphical location pointer for graphic display (x,y)""" + self.position = pos + + def getPosition(self): + """returns a graphical location pointer for graphic display (x,y)""" + return self.position + + def addAttribute(self,attribute) : + """adds an Attribute instance to the attribute list""" + self.attributeList.append(attribute) + self._p_changed = 1 + + def removeAttribute(self,attribute): + """removes the specified Attribute instance from the attribute list""" + if attribute in self.attributeList: + self.attributeList.remove(attribute) + self._p_changed = 1 + + def getAttributeList(self) : + """returns the attribute list""" + return extlist(self.attributeList) + + def setAttributeList(self,list) : + """sets the attribute list to the specified list""" + self.attributeList = list + + def getNote(self): + """returns the text of the note attached to the Family""" + return self.note.get() + + def setNote(self,text): + """sets the note attached to the Family to the passed text""" + self.note.set(text) + + def getNoteObj(self): + """returns the Note instance attached to the Family""" + return self.note + + def unique_note(self): + """Creates a unique instance of the current note""" + self.note = Note(self.note.get()) + + def setNoteObj(self,obj): + """sets the Note instance attached to the Family""" + self.note = obj + + def setId(self,id) : + """sets the gramps ID for the Family""" + self.id = str(id) + + def getId(self) : + """returns the gramps ID for the Family""" + return self.id + + def setRelationship(self,type): + """assigns a string indicating the relationship between the + father and the mother""" + self.type = type + + def getRelationship(self): + """returns a string indicating the relationship between the + father and the mother""" + return self.type + + def setFather(self,person): + """sets the father of the Family to the specfied Person""" + update = self.someChildIsAncestor() + if update and self.Father: + self.Father.setAncestor(0) + self.Father = person + if update and self.Father: + self.Father.setAncestor(1) + + def getFather(self): + """returns the father of the Family""" + return self.Father + + def setMother(self,person): + """sets the mother of the Family to the specfied Person""" + update = self.someChildIsAncestor() + if self.Mother and update: + self.Mother.setAncestor(0) + self.Mother = person + if update and self.Mother: + self.Mother.setAncestor(1) + + def getMother(self): + """returns the mother of the Family""" + return self.Mother + + def addChild(self,person): + """adds the specfied Person as a child of the Family, adding it + to the child list""" + if person not in self.Children: + self.Children.append(person) + self._p_changed = 1 + if person.getAncestor(): + if self.Father: + self.Father.setAncestor(1) + if self.Mother: + self.Mother.setAncestor(1) + + def removeChild(self,person): + """removes the specified Person from the child list""" + if person in self.Children: + self.Children.remove(person) + self._p_changed = 1 + if person.getAncestor(): + if self.Father: + self.Father.setAncestor(0) + if self.Mother: + self.Mother.setAncestor(0) + + def getChildList(self): + """returns the list of children""" + return extlist(self.Children) + + def setChildList(self, list): + """sets the list of children""" + self.Children = list + + def getMarriage(self): + """returns the marriage event of the Family. Obsolete""" + for e in self.EventList: + if e.getName() == "Marriage": + return e + return None + + def getDivorce(self): + """returns the divorce event of the Family. Obsolete""" + for e in self.EventList: + if e.getName() == "Divorce": + return e + return None + + def addEvent(self,event): + """adds an Event to the event list""" + self.EventList.append(event) + self._p_changed = 1 + + def getEventList(self) : + """returns the list of Event instances""" + return extlist(self.EventList) + + def setEventList(self,list) : + """sets the event list to the passed list""" + self.EventList = list + + def addPhoto(self,photo): + """Adds a Photo object to the Family instance's image list""" + self.photoList.append(photo) + self._p_changed = 1 + + def getPhotoList(self): + """Returns the list of Photo objects""" + return extlist(self.photoList) + + def setPhotoList(self,list): + """Sets the list of Photo objects""" + self.photoList = list + + def someChildIsAncestor(self): + for child in self.Children: + if (child.getAncestor()): + return 1 + return None + +class Source(Persistent): + """A record of a source of information""" + + def __init__(self): + """creates a new Source instance""" + self.title = "" + self.author = "" + self.pubinfo = "" + self.callno = "" + self.note = Note() + self.photoList = [] + self.id = "" + + def getDisplayInfo(self): + return [self.title,self.id,self.author,upper(self.title), + upper(self.author)] + + def setId(self,newId): + """sets the gramps' ID for the Source instance""" + self.id = str(newId) + + def getId(self): + """returns the gramps' ID of the Source instance""" + return self.id + + def addPhoto(self,photo): + """Adds a Photo object to the Source instance's image list""" + self.photoList.append(photo) + self._p_changed = 1 + + def getPhotoList(self): + """Returns the list of Photo objects""" + return extlist(self.photoList) + + def setPhotoList(self,list): + """Sets the list of Photo objects""" + self.photoList = list + + def setTitle(self,title): + """sets the title of the Source""" + self.title = title + + def getTitle(self): + """returns the title of the Source""" + return self.title + + def setNote(self,text): + """sets the text of the note attached to the Source""" + self.note.set(text) + + def getNote(self): + """returns the text of the note attached to the Source""" + return self.note.get() + + def setNoteObj(self,obj): + """sets the Note instance attached to the Source""" + self.note = obj + + def getNoteObj(self): + """returns the Note instance attached to the Source""" + return self.note + + def unique_note(self): + """Creates a unique instance of the current note""" + self.note = Note(self.note.get()) + + def setAuthor(self,author): + """sets the author of the Source""" + self.author = author + + def getAuthor(self): + """returns the author of the Source""" + return self.author + + def setPubInfo(self,text): + """sets the publication information of the Source""" + self.pubinfo = text + + def getPubInfo(self): + """returns the publication information of the Source""" + return self.pubinfo + + def setCallNumber(self,val): + """sets the call number (or some identification indicator) + of the Source""" + self.callno = val + + def getCallNumber(self): + """returns the call number (or some identification indicator) + of the Source""" + return self.callno + +class SourceRef(Persistent): + """Source reference, containing detailed information about how a + referenced source relates to it""" + + def __init__(self,source=None): + """creates a new SourceRef, copying from the source if present""" + if source: + self.confidence = source.confidence + self.ref = source.ref + self.page = source.page + self.date = Date(source.date) + self.comments = Note(source.comments.get()) + self.text = source.text + else: + self.confidence = CONF_NORMAL + self.ref = None + self.page = "" + self.date = Date() + self.comments = Note() + self.text = "" + + def setConfidence(self,val): + """Sets the confidence level""" + self.confidence = val + + def getConfidence(self): + """Returns the confidence level""" + return self.confidence + + def setBase(self,ref): + """sets the Source instance to which the SourceRef refers""" + self.ref = ref + + def getBase(self): + """returns the Source instance to which the SourceRef refers""" + return self.ref + + def setDate(self,date): + """sets the Date instance of the SourceRef""" + self.date = date + + def getDate(self): + """returns the Date instance of the SourceRef""" + return self.date + + def setPage(self,page): + """sets the page indicator of the SourceRef""" + self.page = page + + def getPage(self): + """gets the page indicator of the SourceRef""" + return self.page + + def setText(self,text): + """sets the text related to the SourceRef""" + self.text = text + + def getText(self): + """returns the text related to the SourceRef""" + return self.text + + def setNoteObj(self,note): + """Change the Note instance to obj""" + self.comments = note + + def setComments(self,comments): + """sets the comments about the SourceRef""" + self.comments.set(comments) + + def getComments(self): + """returns the comments about the SourceRef""" + return self.comments.get() + + def are_equal(self,other): + """returns 1 if the passed SourceRef is equal to the current""" + if self.ref and other.ref: + if self.page != other.page: + return 0 + if compare_dates(self.date,other.date) != 0: + return 0 + if self.getText() != other.getText(): + return 0 + if self.getComments() != other.getComments(): + return 0 + if self.confidence != other.confidence: + return 0 + return 1 + elif not self.ref and not other.ref: + return 1 + else: + return 0 + + def unique_note(self): + """Creates a unique instance of the current note""" + self.comments = Note(self.comments.get()) + +class GrampsDB(Persistent): + """GRAMPS database object. This object is a base class for other + objects.""" + + def __init__(self): + """creates a new GrampsDB""" + self.surnames = [] + self.personTable = {} + self.placeTable = {} + self.sourceTable = {} + self.iprefix = "I%d" + self.sprefix = "S%d" + self.oprefix = "O%d" + self.pprefix = "P%d" + self.fprefix = "F%d" + self.familyMap = {} + self.personMap = {} + self.sourceMap = {} + self.placeMap = {} + self.new() + + def get_type(self): + return 'GrampsDB' + + def close(self): + pass + + def get_base(self): + return "" + + def need_autosave(self): + return 1 + + def getPersonKeys(self): + return self.personTable.keys() + + def getPersonDisplay(self,key): + return self.personTable[key] + + def buildPersonDisplay(self,nkey,okey=None): + if nkey != okey and okey != None: + del self.personTable[okey] + person = self.personMap[nkey] + self.personTable[nkey] = person.getDisplayInfo() + self.addSurname(person.getPrimaryName().getSurname()) + + def buildPlaceDisplay(self,nkey,okey=None): + if nkey != okey and okey != None: + del self.placeTable[okey] + self.placeTable[nkey] = self.placeMap[nkey].getDisplayInfo() + + def set_iprefix(self,val): + if _id_reg.search(val): + self.iprefix = val + else: + self.iprefix = val + "%d" + + def set_sprefix(self,val): + if _id_reg.search(val): + self.sprefix = val + else: + self.sprefix = val + "%d" + + def set_oprefix(self,val): + if _id_reg.search(val): + self.oprefix = val + else: + self.oprefix = val + "%d" + + def set_pprefix(self,val): + if _id_reg.search(val): + self.pprefix = val + else: + self.pprefix = val + "%d" + + def set_fprefix(self,val): + if _id_reg.search(val): + self.fprefix = val + else: + self.fprefix = val + "%d" + + def new(self): + """initializes the GrampsDB to empty values""" + + # eliminate memory reference cycles for 1.5.2 garbage collection + for f in self.familyMap.values(): + f.Father = None + f.Mother = None + f.Children = [] + self.familyMap = {} + + for p in self.personMap.values(): + p.clearAltFamilyList() + p.clearFamilyList() + + self.surnames = [] + self.personMap = {} + self.sourceMap = {} + self.placeMap = {} + self.objectMap = {} + self.personTable = {} + self.placeTable = {} + self.sourceTable = {} + self.smapIndex = 0 + self.pmapIndex = 0 + self.fmapIndex = 0 + self.lmapIndex = 0 + self.omapIndex = 0 + self.default = None + self.owner = Researcher() + self.bookmarks = [] + self.path = "" + self.place2title = {} + + def getSurnames(self): + return self.surnames + + def addSurname(self,name): + if name and name not in self.surnames: + self.surnames.append(name) + self.surnames.sort() + + def getBookmarks(self): + """returns the list of Person instances in the bookmarks""" + return extlist(self.bookmarks) + + def clean_bookmarks(self): + """cleans up the bookmark list, removing empty slots""" + new_bookmarks = [] + for person in self.bookmarks: + new_bookmarks.append(person) + self.bookmarks = new_bookmarks + + def setResearcher(self,owner): + """sets the information about the owner of the database""" + self.owner.set(owner.getName(),owner.getAddress(),owner.getCity(),\ + owner.getState(),owner.getCountry(),\ + owner.getPostalCode(),owner.getPhone(),owner.getEmail()) + + def getResearcher(self): + """returns the Researcher instance, providing information about + the owner of the database""" + return self.owner + + def setDefaultPerson(self,person): + """sets the default Person to the passed instance""" + if (self.default): + self.default.setAncestor(0) + self.default = person + self.default.setAncestor(1) + + def getDefaultPerson(self): + """returns the default Person of the database""" + return self.default + + def getPerson(self,id): + """returns a map of gramps's IDs to Person instances""" + return self.personMap[id] + + def getPersonMap(self): + """returns a map of gramps's IDs to Person instances""" + return extmap(self.personMap) + + def setPersonMap(self,map): + """sets the map of gramps's IDs to Person instances""" + self.personMap = map + + def getPlaceMap(self): + """returns a map of gramps's IDs to Place instances""" + return extmap(self.placeMap) + + def setPlaceMap(self,map): + """sets the map of gramps's IDs to Place instances""" + self.placeMap = map + + def getFamilyMap(self): + """returns a map of gramps's IDs to Family instances""" + return extmap(self.familyMap) + + def getFamily(self,id): + """returns a map of gramps's IDs to Family instances""" + return self.familyMap[id] + + def setFamilyMap(self,map): + """sets the map of gramps's IDs to Family instances""" + self.familyMap = map + + def getSourceMap(self): + """returns a map of gramps's IDs to Source instances""" + return extmap(self.sourceMap) + + + def getObjectMap(self): + """returns a map of gramps's IDs to Object instances""" + return self.objectMap + + def getSavePath(self): + """returns the save path of the file, or "" if one does not exist""" + return self.path + + def setSavePath(self,path): + """sets the save path for the database""" + self.path = path + + def getPersonEventTypes(self): + """returns a list of all Event types assocated with Person + instances in the database""" + map = {} + for person in self.personMap.values(): + for event in person.getEventList(): + map[event.getName()] = 1 + return map.keys() + + def getPersonAttributeTypes(self): + """returns a list of all Attribute types assocated with Person + instances in the database""" + map = {} + for key in self.personTable.keys(): + person = self.personMap[key] + for attr in person.getAttributeList(): + map[attr.getType()] = 1 + return map.keys() + + def getFamilyAttributeTypes(self): + """returns a list of all Attribute types assocated with Family + instances in the database""" + map = {} + for family in self.familyMap.values(): + for attr in family.getAttributeList(): + map[attr.getType()] = 1 + return map.keys() + + def getFamilyEventTypes(self): + """returns a list of all Event types assocated with Family + instances in the database""" + map = {} + for family in self.familyMap.values(): + for attr in family.getEventList(): + map[attr.getName()] = 1 + return map.keys() + + def getPlaces(self): + """returns a list of Place instances""" + return self.placeMap.values() + + def getFamilyRelationTypes(self): + """returns a list of all relationship types assocated with Family + instances in the database""" + map = {} + for family in self.familyMap.values(): + map[family.getRelationship()] = 1 + return map.keys() + + def removePerson(self,id): + del self.personMap[id] + del self.personTable[id] + + def removeSource(self,id): + del self.sourceMap[id] + del self.sourceTable[id] + + def addPersonAs(self,person): + self.personMap[person.getId()] = person + self.personTable[person.getId()] = person.getDisplayInfo() + + def addPerson(self,person): + """adds a Person to the database, assigning a gramps' ID""" + index = self.iprefix % self.pmapIndex + while self.personMap.has_key(index): + self.pmapIndex = self.pmapIndex + 1 + index = self.iprefix % self.pmapIndex + person.setId(index) + self.personMap[index] = person + self.personTable[index] = person.getDisplayInfo() + self.pmapIndex = self.pmapIndex + 1 + return index + + def findPerson(self,idVal,map): + """finds a Person in the database using the idVal and map + variables to translate between the external ID and gramps' + internal ID. If no such Person exists, a new Person instance + is created. + + idVal - external ID number + map - map build by findPerson of external to gramp's IDs""" + + idVal = str(idVal) + if map.has_key(idVal): + person = self.personMap[map[idVal]] + else: + person = Person() + map[idVal] = self.addPerson(person) + self.personTable[map[idVal]] = person.getDisplayInfo() + return person + + def addPersonNoMap(self,person,id): + """adds a Person to the database if the gramps' ID is known""" + + id = str(id) + person.setId(id) + self.personMap[id] = person + self.pmapIndex = self.pmapIndex+1 + self.personTable[id] = person.getDisplayInfo() + return id + + def findPersonNoMap(self,val): + """finds a Person in the database from the passed gramps' ID. + If no such Person exists, a new Person is added to the database.""" + + person = self.personMap.get(val) + if not person: + person = Person() + person.id = val + self.personMap[val] = person + self.pmapIndex = self.pmapIndex+1 + self.personTable[val] = person.getDisplayInfo() + return person + + def addSource(self,source): + """adds a Source instance to the database, assigning it a gramps' + ID number""" + + index = self.sprefix % self.smapIndex + while self.sourceMap.has_key(index): + self.smapIndex = self.smapIndex + 1 + index = self.sprefix % self.smapIndex + source.setId(index) + self.sourceMap[index] = source + self.sourceTable[index] = source.getDisplayInfo() + self.smapIndex = self.smapIndex + 1 + return index + + def findSource(self,idVal,map): + """finds a Source in the database using the idVal and map + variables to translate between the external ID and gramps' + internal ID. If no such Source exists, a new Source instance + is created. + + idVal - external ID number + map - map build by findSource of external to gramp's IDs""" + + if map.has_key(idVal): + source = self.sourceMap[map[idVal]] + else: + source = Source() + map[idVal] = self.addSource(source) + self.sourceTable[map[idVal]] = source.getDisplayInfo() + return source + + def addSourceNoMap(self,source,index): + """adds a Source to the database if the gramps' ID is known""" + source.setId(index) + self.sourceMap[index] = source + self.smapIndex = self.smapIndex + 1 + self.sourceTable[index] = source.getDisplayInfo() + return index + + def findSourceNoMap(self,val): + """finds a Source in the database from the passed gramps' ID. + If no such Source exists, a new Source is added to the database.""" + + if self.sourceMap.has_key(val): + source = self.sourceMap[val] + else: + source = Source() + self.addSourceNoMap(source,val) + self.sourceTable[val] = source.getDisplayInfo() + return source + + def addObject(self,object): + """adds an Object instance to the database, assigning it a gramps' + ID number""" + + index = self.oprefix % self.omapIndex + while self.objectMap.has_key(index): + self.omapIndex = self.omapIndex + 1 + index = self.oprefix % self.omapIndex + object.setId(index) + self.objectMap[index] = object + self.omapIndex = self.omapIndex + 1 + return index + + def findObject(self,idVal,map): + """finds an Object in the database using the idVal and map + variables to translate between the external ID and gramps' + internal ID. If no such Object exists, a new Object instance + is created. + + idVal - external ID number + map - map build by findObject of external to gramp's IDs""" + + idVal = str(idVal) + if map.has_key(idVal): + object = self.objectMap[map[idVal]] + else: + object = Photo() + map[idVal] = self.addObject(object) + return object + + def addObjectNoMap(self,object,index): + """adds an Object to the database if the gramps' ID is known""" + index = str(index) + object.setId(index) + self.objectMap[index] = object + self.omapIndex = self.omapIndex + 1 + return index + + def findObjectNoMap(self,idVal): + """finds an Object in the database from the passed gramps' ID. + If no such Source exists, a new Source is added to the database.""" + + val = str(idVal) + if self.objectMap.has_key(val): + object = self.objectMap[val] + else: + object = Photo() + self.addObjectNoMap(object,val) + return object + + def addPlace(self,place): + """adds a Place instance to the database, assigning it a gramps' + ID number""" + + index = self.pprefix % self.lmapIndex + while self.placeMap.has_key(index): + self.lmapIndex = self.lmapIndex + 1 + index = self.pprefix % self.lmapIndex + place.setId(index) + self.placeMap[index] = place + self.lmapIndex = self.lmapIndex + 1 + self.placeTable[index] = place.getDisplayInfo() + return index + + def removePlace(self,id): + del self.placeMap[id] + del self.placeTable[id] + + def addPlaceAs(self,place): + self.placeMap[place.getId()] = place + self.placeTable[place.getId()] = place.getDisplayInfo() + + def findPlace(self,idVal,map): + """finds a Place in the database using the idVal and map + variables to translate between the external ID and gramps' + internal ID. If no such Place exists, a new Place instance + is created. + + idVal - external ID number + map - map build by findPlace of external to gramp's IDs""" + + idVal = str(idVal) + if map.has_key(idVal): + place = self.placeMap[map[idVal]] + else: + place = Place() + map[idVal] = self.addPlace(place) + return place + + def addPlaceNoMap(self,place,index): + """adds a Place to the database if the gramps' ID is known""" + + index = str(index) + place.setId(index) + self.placeMap[index] = place + self.lmapIndex = self.lmapIndex + 1 + self.placeTable[index] = place.getDisplayInfo() + return index + + def findPlaceNoMap(self,val): + """finds a Place in the database from the passed gramps' ID. + If no such Place exists, a new Place is added to the database.""" + + place = self.placeMap.get(val) + if not place: + place = Place() + place.id = val + self.placeMap[val] = place + self.lmapIndex = self.lmapIndex + 1 + self.placeTable[val] = place.getDisplayInfo() + return place + + def getPlaceKeys(self): + return self.placeTable.keys() + + def getPlace(self,key): + return self.placeMap[key] + + def getPlaceDisplay(self,key): + return self.placeTable[key] + + def getSourceKeys(self): + return self.sourceTable.keys() + + def getSourceDisplay(self,key): + return self.sourceTable[key] + + def getSource(self,key): + return self.sourceMap[key] + + def buildSourceDisplay(self,nkey,okey=None): + if nkey != okey and okey != None: + del self.sourceTable[okey] + if self.sourceTable.has_key(nkey): + del self.sourceTable[nkey] + self.sourceTable[nkey] = self.sourceMap[nkey].getDisplayInfo() + + def newFamily(self): + """adds a Family to the database, assigning a gramps' ID""" + index = self.fprefix % self.fmapIndex + while self.familyMap.has_key(index): + self.fmapIndex = self.fmapIndex + 1 + index = self.fprefix % self.fmapIndex + self.fmapIndex = self.fmapIndex + 1 + family = Family() + family.setId(index) + self.familyMap[index] = family + return family + + def newFamilyNoMap(self,id): + """finds a Family in the database from the passed gramps' ID. + If no such Family exists, a new Family is added to the database.""" + + family = Family() + id = str(id) + family.setId(id) + self.familyMap[id] = family + self.fmapIndex = self.fmapIndex + 1 + return family + + def findFamily(self,idVal,map): + """finds a Family in the database using the idVal and map + variables to translate between the external ID and gramps' + internal ID. If no such Family exists, a new Family instance + is created. + + idVal - external ID number + map - map build by findFamily of external to gramp's IDs""" + + if map.has_key(idVal): + family = self.familyMap[map[idVal]] + else: + family = self.newFamily() + map[idVal] = family.getId() + return family + + def findFamilyNoMap(self,val): + """finds a Family in the database from the passed gramps' ID. + If no such Family exists, a new Family is added to the database.""" + + family = self.familyMap.get(val) + if not family: + family = Family() + family.id = val + self.familyMap[val] = family + self.fmapIndex = self.fmapIndex + 1 + return family + + def deleteFamily(self,family): + """deletes the Family instance from the database""" + if self.familyMap.has_key(family.getId()): + del self.familyMap[family.getId()] + + + diff --git a/gramps2/src/Report.py b/gramps2/src/Report.py new file mode 100644 index 000000000..ffc713277 --- /dev/null +++ b/gramps2/src/Report.py @@ -0,0 +1,1092 @@ +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2001 David R. Hampton +# +# 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 +# + +"Report Generation Framework" + +__author__ = "David R. Hampton, Donald N. Allingham" +__version__ = "$Revision$" + +#------------------------------------------------------------------------- +# +# standard python modules +# +#------------------------------------------------------------------------- +import os +import string + +#------------------------------------------------------------------------- +# +# GNOME/GTK modules +# +#------------------------------------------------------------------------- +import gtk +import gnome.ui + +#------------------------------------------------------------------------- +# +# GRAMPS modules +# +#------------------------------------------------------------------------- +import const +import Utils +import Plugins +import GenericFilter +import TextDoc +import StyleEditor +import GrampsCfg +import PaperMenu +import intl +import latin_utf8 + +u2l = latin_utf8.utf8_to_latin +_ = intl.gettext + +#------------------------------------------------------------------------- +# +# Import XML libraries +# +#------------------------------------------------------------------------- +try: + from xml.sax import make_parser,handler,SAXParseException +except: + from _xmlplus.sax import make_parser,handler,SAXParseException + +#------------------------------------------------------------------------- +# +# +# +#------------------------------------------------------------------------- +_default_template = _("Default Template") +_user_template = _("User Defined Template") + +_template_map = { + _user_template : None + } + +class Report: + """ + The Report base class. This is a base class for generating + customized reports. It cannot be used as is, but it can be easily + sub-classed to create a functional report generator. + """ + + # Ordinal generation names. Used by multiple reports. + 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: _("Eighteenth"), + 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 get_progressbar_data(self): + """The window title for this dialog, and the header line to + put at the top of the contents of the dialog box.""" + return (_("Progress Report - GRAMPS"), _("Working")) + + def progress_bar_setup(self,total): + """Create a progress dialog. This routine calls a + customization function to find out how to fill out the dialog. + The argument to this function is the maximum number of items + that the report will progress; i.e. what's considered 100%, + i.e. the maximum number of times this routine will be + called.""" + + # Customize the dialog for this report + (title, header) = self.get_progressbar_data() + self.ptop = gtk.Dialog() + self.ptop.set_title(title) + self.ptop.vbox.add(gtk.Label(header)) + self.ptop.vbox.add(gtk.HSeparator()) + self.ptop.vbox.set_spacing(10) + self.pbar = gtk.ProgressBar() + self.pbar.set_format_string(_("%v of %u (%P%%)")) + self.pbar.configure(0.0,0.0,total) + self.pbar.set_show_text(1) + self.pbar.set_usize(350,20) + self.pbar_max = total + self.pbar_index = 0.0 + + self.ptop.vbox.add(self.pbar) + self.ptop.show_all() + + def progress_bar_step(self): + """Click the progress bar over to the next value. Be paranoid + and insure that it doesn't go over 100%.""" + self.pbar_index = self.pbar_index + 1.0 + if (self.pbar_index > self.pbar_max): + self.pbar_index = self.pbar_max + self.pbar.set_value(self.pbar_index) + + def progress_bar_done(self): + """Done with the progress bar. It can be destroyed now.""" + Utils.destroy_passed_object(self.ptop) + + +class ReportDialog: + """ + The ReportDialog base class. This is a base class for generating + customized dialogs to solicit options for a report. It cannot be + used as is, but it can be easily sub-classed to create a functional + dialog. + """ + + frame_pad = 5 + border_pad = 2 + + def __init__(self,database,person): + """Initialize a dialog to request that the user select options + for a basic report.""" + + # Save info about who the report is about. + self.db = database + self.person = person + self.output_notebook = None + self.notebook_page = 1 + self.pagecount_menu = None + self.filter_combo = None + self.extra_menu = None + self.extra_textbox = None + self.pagebreak_checkbox = None + self.generations_spinbox = None + self.widgets = [] + self.frame_names = [] + self.frames = {} + + self.window = gtk.Dialog('GRAMPS') + # self.window.set_default(0) + self.window.add_button(gtk.STOCK_OK,0) + self.window.set_response_sensitive(0,gtk.TRUE) + self.window.add_button(gtk.STOCK_CANCEL,1) + self.window.set_response_sensitive(1,gtk.TRUE) +# self.window.button_connect(1,self.on_cancel) + self.window.set_resize_mode(0) + + # Build the list of widgets that are used to extend the Options + # frame and to create other frames + + self.add_user_options() + + # Set up and run the dialog. These calls are not in top down + # order when looking at the dialog box as there is some + # interaction between the various frames. + self.setup_title() + self.setup_header() + self.setup_target_frame() + self.setup_format_frame() + self.setup_style_frame() + self.setup_output_notebook() + self.setup_paper_frame() + self.setup_html_frame() + self.setup_report_options_frame() + self.setup_other_frames() + self.window.show_all() + self.setup_post_process() + + result = self.window.run() + self.on_ok_clicked(result) + + # Allow for post processing of the format frame, since the + # show_all task calls events that may reset values + + def setup_post_process(self): + pass + + #------------------------------------------------------------------------ + # + # Customization hooks for subclasses + # + #------------------------------------------------------------------------ + def get_title(self): + """The window title for this dialog.""" + return(_("Base Report - GRAMPS")) + + def get_header(self, name): + """The header line to put at the top of the contents of the + dialog box. By default this will just be the name of the + selected person. Most subclasses will customize this to give + some indication of what the report will be, i.e. 'Descendant + Report for %s'.""" + return(name) + + def get_target_browser_title(self): + """The title of the window that will be created when the user + clicks the 'Browse' button in the 'Save As' File Entry + widget.""" + return(_("Save Report As - GRAMPS")) + + def get_target_is_directory(self): + """Is the user being asked to input the name of a file or a + directory in the 'Save As' File Entry widget. This item + currently only selects the Filename/Directory prompt, and + whether or not the browser accepts filenames. In the future it + may also control checking of the selected filename.""" + return None + + def get_stylesheet_savefile(self): + """Where should new styles for this report be saved? This is + the name of an XML file that will be located in the ~/.gramps + directory. This file does not have to exist; it will be + created when needed. All subclasses should probably override + this function.""" + return "basic_report.xml" + + def get_print_pagecount_map(self): + """Return the data used to fill out the 'pagecount' option + menu in the print options box. The first value is a mapping + of string:value pairs. The strings will be used to label + individual menu items, and the values are what will be + returned if a given menu item is selected. The second value + is the name of menu item to pre-select.""" + return (None, None) + + def get_report_filters(self): + """Return the data used to fill out the 'filter' combo box in + the report options box. The return value is the list of + strings to be inserted into the pulldown.""" + return [] + + def get_report_generations(self): + """Return the default number of generations to start the + spinbox (zero to disable) and whether or not to include the + 'page break between generations' check box""" + return (10, 1) + + def get_report_extra_menu_info(self): + """Return the data used to fill out the 'extra' option menu in + the report options box. The first value is the string to be + used as the label to the left of the menu. The second value + is a mapping of string:value pairs. The strings will be used + to label individual menu items, and the values are what will + be returned if a given menu item is selected. The third value + is the name of menu item to pre-select, and the final value is + a string to use as the tooltip for the textbox.""" + return (None, None, None, None) + + def get_report_extra_textbox_info(self): + """Return the data used to fill out the 'extra' textbox in the + report options dialog. The first value is the string to be + used as the label to the left of the textbox. The second + value is the string to use as the default contents of the + textbox. If None, then the text box will be hidden. The + final value is a string to use as the tooltip for the + textbox.""" + return (None, None, None) + + #------------------------------------------------------------------------ + # + # Functions related getting/setting the default directory for a dialog. + # + #------------------------------------------------------------------------ + def get_default_directory(self): + """Get the name of the directory to which the target dialog + box should default. This value can be set in the preferences + panel.""" + return GrampsCfg.report_dir + + def set_default_directory(self, value): + """Save the name of the current directory, so that any future + reports will default to the most recently used directory. + This also changes the directory name that will appear in the + preferences panel, but does not change the preference in disk. + This means that the last directory used will only be + remembered for this session of gramps unless the user saves + his/her preferences.""" + GrampsCfg.report_dir = value + + #------------------------------------------------------------------------ + # + # Functions related to extending the options + # + #------------------------------------------------------------------------ + def add_user_options(self): + """Called to allow subclasses add widgets to the dialog form. + It is called immediately before the window is displayed. All + calls to add_option or add_frame_option should be called in + this task.""" + pass + + def add_option(self,label_text,widget,tooltip=None): + """Takes a text string and a Gtk Widget, and stores them to be + appended to the Options section of the dialog. The text string + is used to create a label for the passed widget. This allows the + subclass to extend the Options section with its own widgets. The + subclass is reponsible for all managing of the widgets, including + extracting the final value before the report executes. This task + should only be called in the add_user_options task.""" + self.widgets.append((label_text,widget)) + if tooltip: + self.add_tooltip(widget,tooltip) + + def add_frame_option(self,frame_name,label_text,widget,tooltip=None): + """Similar to add_option this method takes a frame_name, a + text string and a Gtk Widget. When the interface is built, + all widgets with the same frame_name are grouped into a + GtkFrame. This allows the subclass to create its own sections, + filling them with its own widgets. The subclass is reponsible for + all managing of the widgets, including extracting the final value + before the report executes. This task should only be called in + the add_user_options task.""" + + if self.frames.has_key(frame_name): + self.frames[frame_name].append((label_text,widget)) + else: + self.frames[frame_name] = [(label_text,widget)] + self.frame_names.append(frame_name) + if tooltip: + self.add_tooltip(widget,tooltip) + + #------------------------------------------------------------------------ + # + # Functions to create a default output style. + # + #------------------------------------------------------------------------ + def make_default_style(self): + """Create the default style to be used by the associated report. This + routine is a default implementation and should be overridden.""" + font = TextDoc.FontStyle() + font.set(face=TextDoc.FONT_SANS_SERIF,size=16,bold=1) + para = TextDoc.ParagraphStyle() + para.set_font(font) + para.set_header_level(1) + para.set(pad=0.5) + self.default_style.add_style("Title",para) + + def build_style_menu(self): + """Build a menu of style sets that are available for use in + this report. This menu will always have a default style + available, and will have any other style set name that the + user has previously created for this report. This menu is + created here instead of inline with the rest of the style + frame, because it must be recreated to reflect any changes + whenever the user closes the style editor dialog.""" + style_sheet_map = self.style_sheet_list.get_style_sheet_map() + myMenu = Utils.build_string_optmenu(style_sheet_map, "default") + self.style_menu.set_menu(myMenu) + + #------------------------------------------------------------------------ + # + # Functions related to selecting/changing the current file format. + # + #------------------------------------------------------------------------ + def make_doc_menu(self): + """Build a menu of document types that are appropriate for + this report. This menu will be generated based upon the type + of document (text, draw, graph, etc. - a subclass), whether or + not the document requires table support, etc.""" + pass + + def make_document(self): + """Create a document of the type selected by the user.""" + pass + + def doc_type_changed(self, obj): + """This routine is called when the user selects a new file + formats for the report. It adjust the various dialog sections + to reflect the appropriate values for the currently selected + file format. For example, a HTML document doesn't need any + paper size/orientation options, but it does need a template + file. Those chances are made here.""" + + # Is this to be a printed report or an electronic report + # (i.e. a set of web pages) + + if obj.get_data("paper") == 1: + self.notebook_page = 0 + else: + self.notebook_page = 1 + + if self.output_notebook == None: + return + + self.output_notebook.set_current_page(self.notebook_page) + + # Does this report format use styles? + self.style_frame.set_sensitive(obj.get_data("styles")) + + #------------------------------------------------------------------------ + # + # Functions related to setting up the dialog window. + # + #------------------------------------------------------------------------ + def setup_title(self): + """Set up the title bar of the dialog. This function relies + on the get_title() customization function for what the title + should be.""" + self.name = self.person.getPrimaryName().getRegularName() + self.window.set_title(self.get_title()) + + def setup_header(self): + """Set up the header line bar of the dialog. This function + relies on the get_header() customization function for what the + header line should read. If no customization function is + supplied by the subclass, the default is to use the full name + of the currently selected person.""" + + title = self.get_header(self.name) + label = gtk.Label(title) + label.set_size_request(450,10) + self.window.vbox.pack_start(label,gtk.TRUE,gtk.TRUE,ReportDialog.border_pad) + self.window.vbox.add(gtk.HSeparator()) + + def setup_target_frame(self): + """Set up the target frame of the dialog. This function + relies on several target_xxx() customization functions to + determine whether the target is a directory or file, what the + title of any browser window should be, and what default + directory should be used.""" + + # Save Frame + frame = gtk.Frame(_("Save As")) + frame.set_border_width(ReportDialog.frame_pad) + hid = self.get_stylesheet_savefile() + if hid[-4:]==".xml": + hid = hid[0:-4] + self.target_fileentry = gnome.ui.FileEntry(hid,_("Save As")) + + hbox = gtk.HBox() + hbox.set_border_width(ReportDialog.border_pad) + if self.get_target_is_directory(): + self.target_fileentry.set_directory_entry(1) + label = gtk.Label(_("Directory")) + else: + label = gtk.Label(_("Filename")) + hbox.pack_start(label,0,0,5) + + hbox.add(self.target_fileentry) + frame.add(hbox) + self.window.vbox.add(frame) + + self.target_fileentry.set_default_path(self.get_default_directory()) + if (self.get_target_is_directory()): + self.target_fileentry.set_directory_entry(1) + + self.target_fileentry.set_filename(self.get_default_directory()) + + # Faugh! The following line of code would allow the 'Enter' + # key in the file name box to close the dialog. However there + # is a bug (or is it?) in the closing of the Gnome FileEntry + # browser that sends the same signal that is sent when the + # 'Enter' key is pressed. This causes the report to be run + # when the browser window is closed instead of waiting for the + # dialog window OK button to be clicked. The user does not + # have a chance to set any other options. + # + # self.window.editable_enters(self.target_filename) + + def setup_format_frame(self): + """Set up the format frame of the dialog. This function + relies on the make_doc_menu() function to do all the hard + work.""" + + self.format_menu = gtk.OptionMenu() + self.make_doc_menu() + frame = gtk.Frame(_("Output Format")) + frame.add(self.format_menu) + frame.set_border_width(ReportDialog.frame_pad) + self.window.vbox.add(frame) + + def setup_style_frame(self): + """Set up the style frame of the dialog. This function relies + on other routines create the default style for this report, + and to read in any user defined styles for this report. It + the builds a menu of all the available styles for the user to + choose from.""" + + # Styles Frame + self.style_frame = gtk.Frame(_("Styles")) + hbox = gtk.HBox() + hbox.set_border_width(ReportDialog.border_pad) + self.style_menu = gtk.OptionMenu() + hbox.pack_start(self.style_menu,gtk.TRUE,gtk.TRUE,2) + style_button = gtk.Button(_("Style Editor")) + style_button.connect('clicked',self.on_style_edit_clicked) + hbox.pack_end(style_button,0,0,2) + self.style_frame.add(hbox) + self.style_frame.set_border_width(ReportDialog.frame_pad) + self.window.vbox.add(self.style_frame) + + # Build the default style set for this report. + self.default_style = TextDoc.StyleSheet() + self.make_default_style() + + # Build the initial list of available styles sets. This + # includes the default style set and any style sets saved from + # previous invocations of gramps. + self.style_sheet_list = TextDoc.StyleSheetList(self.get_stylesheet_savefile(), + self.default_style) + + # Now build the actual menu. + self.build_style_menu() + + def setup_output_notebook(self): + """Set up the output notebook of the dialog. This sole + purpose of this function is to grab a pointer for later use in + the callback from when the file format is changed.""" + + self.output_notebook = gtk.Notebook() + self.paper_frame = gtk.Frame(_("Paper Options")) + self.paper_frame.set_border_width(ReportDialog.frame_pad) + self.output_notebook.append_page(self.paper_frame,gtk.Label(_("Paper Options"))) + self.html_frame = gtk.Frame(_("HTML Options")) + self.html_frame.set_border_width(ReportDialog.frame_pad) + self.output_notebook.append_page(self.html_frame,gtk.Label(_("HTML Options"))) + self.output_notebook.set_show_tabs(0) + self.output_notebook.set_show_border(0) + self.output_notebook.set_current_page(self.notebook_page) + self.window.vbox.add(self.output_notebook) + + def setup_paper_frame(self): + """Set up the paper selection frame of the dialog. This + function relies on a paper_xxx() customization functions to + determine whether the pagecount menu should appear and what + its strings should be.""" + + (pagecount_map, start_text) = self.get_print_pagecount_map() + table = gtk.Table(2,4) + self.paper_frame.add(table) + self.papersize_menu = gtk.OptionMenu() + self.orientation_menu = gtk.OptionMenu() + l = gtk.Label(_("Size")) + pad = ReportDialog.border_pad + l.set_alignment(1.0,0.5) + table.attach(l,0,1,0,1,gtk.FILL,gtk.FILL,pad,pad) + table.attach(self.papersize_menu,1,2,0,1,xpadding=pad,ypadding=pad) + l = gtk.Label(_("Orientation")) + l.set_alignment(1.0,0.5) + table.attach(l,2,3,0,1,gtk.FILL,gtk.FILL,pad,pad) + table.attach(self.orientation_menu,3,4,0,1,xpadding=pad,ypadding=pad) + PaperMenu.make_paper_menu(self.papersize_menu) + PaperMenu.make_orientation_menu(self.orientation_menu) + + # The optional pagecount stuff. + if pagecount_map: + self.pagecount_menu = gtk.OptionMenu() + myMenu = Utils.build_string_optmenu(pagecount_map, start_text) + self.pagecount_menu.set_menu(myMenu) + table.attach(gtk.Label(_("Page Count")),0,1,1,2,gtk.FILL,gtk.FILL,pad,pad) + table.attach(self.pagecount_menu,1,2,1,2,xpadding=pad,ypadding=pad) + + def html_file_enable(self,obj): + text = obj.get_text() + if _template_map.has_key(text): + if _template_map[text]: + self.html_fileentry.set_sensitive(0) + else: + self.html_fileentry.set_sensitive(1) + else: + self.html_fileentry.set_sensitive(0) + + def setup_html_frame(self): + """Set up the html frame of the dialog. This sole purpose of + this function is to grab a pointer for later use in the parse + html frame function.""" + + table = gtk.Table(2,2) + self.html_frame.add(table) + l = gtk.Label(_("Template")) + pad = ReportDialog.border_pad + l.set_alignment(1.0,0.5) + table.attach(l,0,1,0,1,gtk.FILL,gtk.FILL,pad,pad) + self.template_combo = gtk.Combo() + + template_list = [ _default_template ] + tlist = _template_map.keys() + tlist.sort() + + for template in tlist: + if template != _user_template: + template_list.append(template) + template_list.append(_user_template) + + self.template_combo.set_popdown_strings(template_list) + self.template_combo.entry.set_editable(0) + self.template_combo.entry.connect('changed',self.html_file_enable) + + table.attach(self.template_combo,1,2,0,1, + gtk.FILL|gtk.EXPAND,gtk.FILL|gtk.EXPAND,pad,pad) + table.attach(gtk.Label(_("User Template")),0,1,1,2, + gtk.FILL,gtk.FILL,pad,pad) + self.html_fileentry = gnome.ui.FileEntry(_("HTML_Template"), + _("Choose File")) + self.html_fileentry.set_sensitive(0) + table.attach(self.html_fileentry,1,2,1,2, + gtk.FILL|gtk.EXPAND,gtk.FILL|gtk.EXPAND,pad,pad) + + def setup_report_options_frame(self): + """Set up the report options frame of the dialog. This + function relies on several report_xxx() customization + functions to determine which of the items should be present in + this box. *All* of these items are optional, although the + generations fields and the filter combo box are used in most + (but not all) dialog boxes.""" + + (use_gen, use_break) = self.get_report_generations() + local_filters = self.get_report_filters() + (em_label, extra_map, preset, em_tip) = self.get_report_extra_menu_info() + (et_label, string, et_tip) = self.get_report_extra_textbox_info() + + row = 0 + max_rows = 0 + if use_gen: + max_rows = max_rows + 1 + if use_break: + max_rows = max_rows + 1 + if len(local_filters): + max_rows = max_rows + 1 + if extra_map: + max_rows = max_rows + 1 + if string: + max_rows = max_rows + 1 + + max_rows = max_rows + len(self.widgets) + + if max_rows == 0: + return + + table = gtk.Table(2,max_rows) + + if len(self.frame_names) == 0: + frame = gtk.Frame(_("Report Options")) + frame.set_border_width(ReportDialog.frame_pad) + self.window.vbox.add(frame) + frame.add(table) + else: + self.notebook = gtk.Notebook() + self.window.vbox.pack_start(self.notebook,padding=ReportDialog.frame_pad) + self.notebook.append_page(table,gtk.Label(_("Report Options"))) + self.notebook.set_border_width(ReportDialog.frame_pad) + + pad = ReportDialog.border_pad + if len(local_filters): + self.filter_combo = gtk.OptionMenu() + l = gtk.Label(_("Filter")) + l.set_alignment(1.0,0.5) + table.attach(l,0,1,row,row+1,xoptions=gtk.FILL,yoptions=0, + xpadding=pad,ypadding=pad) + table.attach(self.filter_combo,1,2,row,row+1,yoptions=0, + xpadding=pad,ypadding=pad) + + menu = GenericFilter.build_filter_menu(local_filters) + + self.filter_combo.set_menu(menu) + self.filter_menu = menu + row = row + 1 + + # Set up the generations spin and page break checkbox + if use_gen: + self.generations_spinbox = gtk.SpinButton(digits=0) + self.generations_spinbox.set_numeric(1) + adjustment = gtk.Adjustment(use_gen,1,31,1,0) + self.generations_spinbox.set_adjustment(adjustment) + adjustment.value_changed() + l = gtk.Label(_("Generations")) + l.set_alignment(1.0,0.5) + table.attach(l,0,1,row,row+1,xoptions=gtk.FILL,yoptions=0, + xpadding=pad,ypadding=pad) + table.attach(self.generations_spinbox,1,2,row,row+1, + yoptions=0, xpadding=pad,ypadding=pad) + row = row + 1 + + if use_break: + msg = _("Page break between generations") + self.pagebreak_checkbox = gtk.CheckButton(msg) + table.attach(self.pagebreak_checkbox,1,2,row,row+1, + xpadding=pad,ypadding=pad) + row = row + 1 + + # Now the "extra" option menu + if extra_map: + self.extra_menu_label = gtk.Label(em_label) + self.extra_menu_label.set_alignment(1.0,0.5) + self.extra_menu = gtk.OptionMenu() + myMenu = Utils.build_string_optmenu(extra_map, preset) + self.extra_menu.set_menu(myMenu) + self.extra_menu.set_sensitive(len(extra_map) > 1) + self.add_tooltip(self.extra_menu,em_tip) + table.attach(self.extra_menu_label,0,1,row,row+1, + xoptions=gtk.FILL,yoptions=0,xpadding=pad,ypadding=pad) + table.attach(self.extra_menu,1,2,row,row+1,yoptions=0, + xpadding=pad,ypadding=pad) + row = row + 1 + + # Now the "extra" text box + if string: + self.extra_textbox_label = gtk.Label(et_label) + self.extra_textbox_label.set_alignment(1.0,0) + self.extra_textbox = gtk.TextView() + self.extra_textbox.get_buffer().set_text(string,len(string)) + self.extra_textbox.set_editable(1) + self.add_tooltip(self.extra_textbox,et_tip) + table.attach(self.extra_textbox_label,0,1,row,row+1,xoptions=gtk.FILL, + yoptions=0,xpadding=pad,ypadding=pad) + table.attach(self.extra_textbox,1,2,row,row+1, + yoptions=0,xpadding=pad,ypadding=pad) + row = row + 1 + + # Setup requested widgets + for (text,widget) in self.widgets: + if text == None: + table.attach(widget,0,2,row,row+1,yoptions=0,xpadding=pad,ypadding=pad) + else: + text_widget = gtk.Label(text) + text_widget.set_alignment(1.0,0) + table.attach(text_widget,0,1,row,row+1,yoptions=0,xpadding=pad,ypadding=pad) + table.attach(widget,1,2,row,row+1,yoptions=0,xpadding=pad,ypadding=pad) + row = row + 1 + + + def setup_other_frames(self): + pad = ReportDialog.border_pad + for key in self.frame_names: + list = self.frames[key] + table = gtk.Table(2,len(list)) + self.notebook.append_page(table,gtk.Label(_(key))) + + row = 0 + for (text,widget) in list: + if text == None: + table.attach(widget,0,2,row,row+1, + xpadding=pad,ypadding=pad) + else: + text_widget = gtk.Label(text) + text_widget.set_alignment(1.0,0) + table.attach(text_widget,0,1,row,row+1,gtk.FILL,gtk.FILL,pad,pad) + table.attach(widget,1,2,row,row+1,yoptions=0, + xpadding=pad,ypadding=pad) + row = row + 1 + + #------------------------------------------------------------------------ + # + # Functions related to retrieving data from the dialog window + # + #------------------------------------------------------------------------ + def parse_target_frame(self): + """Parse the target frame of the dialog. If the target + filename is empty this routine returns a special value of None + to tell the calling routine to give up. This function also + saves the current directory so that any future reports will + default to the most recently used directory.""" + self.target_path = self.target_fileentry.get_full_path(0) + if not self.target_path: + return None + + if not self.get_target_is_directory() and os.path.isdir(self.target_path): + gnome.ui.GnomeErrorDialog(_("The filename that you gave is a directory.\n" + "You need to provide a valid filename.")) + return None + + self.set_default_directory(os.path.dirname(self.target_path) + os.sep) + return 1 + + def parse_format_frame(self): + """Parse the format frame of the dialog. Save the user + selected output format for later use.""" + self.format = self.format_menu.get_menu().get_active().get_data("name") + + def parse_style_frame(self): + """Parse the style frame of the dialog. Save the user + selected output style for later use. Note that this routine + retrieves a value whether or not the menu is displayed on the + screen. The subclass will know whether this menu was enabled. + This is for simplicity of programming.""" + self.selected_style = self.style_menu.get_menu().get_active().get_data("d") + + def parse_paper_frame(self): + """Parse the paper frame of the dialog. Save the user + selected choices for later use. Note that this routine + retrieves a value from the pagecount menu, whether or not it + is displayed on the screen. The subclass will know which ones + it has enabled. This is for simplicity of programming.""" + self.paper = self.papersize_menu.get_menu().get_active().get_data("i") + self.orien = self.orientation_menu.get_menu().get_active().get_data("i") + if self.pagecount_menu == None: + self.pagecount = 0 + else: + self.pagecount = self.pagecount_menu.get_menu().get_active().get_data("d") + + def parse_html_frame(self): + """Parse the html frame of the dialog. Save the user selected + html template name for later use. Note that this routine + retrieves a value whether or not the file entry box is + displayed on the screen. The subclass will know whether this + entry was enabled. This is for simplicity of programming.""" + + text = self.template_combo.entry.get_text() + if _template_map.has_key(text): + if text == _user_template: + self.template_name = self.html_fileentry.get_full_path(0) + else: + self.template_name = "%s/%s" % (const.template_dir,_template_map[text]) + else: + self.template_name = None + + def parse_report_options_frame(self): + """Parse the report options frame of the dialog. Save the + user selected choices for later use. Note that this routine + retrieves a value from all fields in the frame, regardless of + whether or not they are displayed on the screen. The subclass + will know which ones it has enabled. This is for simplicity + of programming.""" + + if self.generations_spinbox: + self.max_gen = self.generations_spinbox.get_value_as_int() + else: + self.max_gen = 0 + + if self.pagebreak_checkbox: + self.pg_brk = self.pagebreak_checkbox.get_active() + else: + self.pg_brk = 0 + + if self.filter_combo: + self.filter = self.filter_menu.get_active().get_data("filter") + else: + self.filter = None + + if self.extra_menu: + self.report_menu = self.extra_menu.get_menu().get_active().get_data("d") + else: + self.report_menu = None + + if self.extra_textbox: + self.report_text = string.split(self.extra_textbox.get_chars(0,-1),'\n') + else: + self.report_text = "" + + def parse_other_frames(self): + """Do nothing. This sole purpose of this function is to give + subclass a place to hang a routine to parser any other frames + that are unique to that specific report.""" + pass + + #------------------------------------------------------------------------ + # + # Callback functions from the dialog + # + #------------------------------------------------------------------------ + def on_style_edit_clicked(self, obj): + """The user has clicked on the 'Edit Styles' button. Create a + style sheet editor object and let them play. When they are + done, the previous routine will be called to update the dialog + menu for selecting a style.""" + StyleEditor.StyleListDisplay(self.style_sheet_list,self.build_style_menu) + + + def on_ok_clicked(self, val): + """The user is satisfied with the dialog choices. Validate + the output file name before doing anything else. If there is + a file name, gather the options and create the report.""" + + if val == 1: + self.window.destroy() + else: + + # Is there a filename? This should also test file permissions, etc. + if not self.parse_target_frame(): + return + + # Preparation + self.parse_format_frame() + self.parse_style_frame() + self.parse_paper_frame() + self.parse_html_frame() + self.parse_report_options_frame() + self.parse_other_frames() + + # Create the output document. + self.make_document() + + # Create the report object and product the report. + try: + self.make_report() + except (IOError,OSError),msg: + gnome.ui.GnomeErrorDialog(str(msg)) + + # Clean up the dialog object + self.window.destroy() + + #------------------------------------------------------------------------ + # + # Functions related to creating the actual report document. + # + #------------------------------------------------------------------------ + def make_report(self): + """Create the contents of the report. This is the meat and + potatoes of reports. The whole purpose of the dialog is to + get to this routine so that data is written to a file. This + routine should either write the data directly to the file, or + better yet, should create a subclass of a Report that will + write the data to a file.""" + pass + + #------------------------------------------------------------------------ + # + # Miscellaneous functions. + # + #------------------------------------------------------------------------ + def add_tooltip(self,widget,string): + """Adds a tooltip to the specified widget""" + if not widget or not string: + return + tip = gtk.Tooltips() + tip.set_tip(widget,string) + + +class TextReportDialog(ReportDialog): + """A class of ReportDialog customized for text based reports.""" + + def __init__(self,database,person): + """Initialize a dialog to request that the user select options + for a basic text report. See the ReportDialog class for more + information.""" + ReportDialog.__init__(self,database,person) + + #------------------------------------------------------------------------ + # + # Customization hooks for subclasses + # + #------------------------------------------------------------------------ + def doc_uses_tables(self): + """Does this report require the ability to generate tables in + the file format. Override this for documents that do need + table support.""" + return 0 + + #------------------------------------------------------------------------ + # + # Functions related to selecting/changing the current file format. + # + #------------------------------------------------------------------------ + def make_doc_menu(self): + """Build a menu of document types that are appropriate for + this text report. This menu will be generated based upon + whether the document requires table support, etc.""" + Plugins.get_text_doc_menu(self.format_menu, self.doc_uses_tables(), + self.doc_type_changed) + + def make_document(self): + """Create a document of the type requested by the user.""" + self.doc = self.format(self.selected_style,self.paper, + self.template_name,self.orien) + + #------------------------------------------------------------------------ + # + # Functions related to creating the actual report document. + # + #------------------------------------------------------------------------ + def make_report(self): + """Create the contents of the report. This is a simple + default implementation suitable for testing. Is should be + overridden to produce a real report.""" + self.doc.start_paragraph("Title") + title = "Basic Report for %s" % self.name + self.doc.write_text(title) + self.doc.end_paragraph() + +class DrawReportDialog(ReportDialog): + """A class of ReportDialog customized for drawing based reports.""" + def __init__(self,database,person): + """Initialize a dialog to request that the user select options + for a basic drawing report. See the ReportDialog class for + more information.""" + ReportDialog.__init__(self,database,person) + + #------------------------------------------------------------------------ + # + # Functions related to selecting/changing the current file format. + # + #------------------------------------------------------------------------ + def make_doc_menu(self): + """Build a menu of document types that are appropriate for + this drawing report.""" + Plugins.get_draw_doc_menu(self.format_menu) + + def make_document(self): + """Create a document of the type requested by the user.""" + self.doc = self.format(self.selected_style,self.paper,self.orien) + + +class TemplateParser(handler.ContentHandler): + """ + Interface to the document template file + """ + def __init__(self,data,fpath): + """ + Creates a template parser. The parser loads map of tempate names + to the file containing the tempate. + + data - dictionary that holds the name to path mappings + fpath - filename of the XML file + """ + handler.ContentHandler.__init__(self) + self.data = data + self.path = fpath + + def setDocumentLocator(self,locator): + """Sets the XML document locator""" + self.locator = locator + + def startElement(self,tag,attrs): + """ + Loads the dictionary when an XML tag of 'template' is found. The format + XML tag is