Merge branch 'gramps50'

This commit is contained in:
Nick Hall 2018-03-03 17:29:32 +00:00
commit 59bd9f040d
54 changed files with 6236 additions and 4946 deletions

View File

@ -16,14 +16,15 @@ The following packages **MUST** be installed in order for Gramps to work:
The following three packages with GObject Introspection bindings (the gi packages)
* **cairo** - a 2D graphics library with support for multiple output devices. http://cairographics.org/
* **cairo** 1.13.1 or greater - a 2D graphics library with support for multiple output devices. http://cairographics.org/
* **Pycairo** 1.13.3 or greater - GObject Introspection bindings for cairo. https://github.com/pygobject/pycairo
* **pango** - a library for laying out and rendering of text, with an emphasis on internationalization. http://www.pango.org/
* **pangocairo** - Allows you to use Pango with Cairo http://www.pango.org/
* **librsvg2** - (SVG icon view) a library to render SVG files using cairo. http://live.gnome.org/LibRsvg
* **xdg-utils** - Desktop integration utilities from freedesktop.org
* **bsddb3** - Python bindings for Oracle Berkeley DB https://pypi.python.org/pypi/bsddb3/
* **sqlite3** - Python bindings for SQLite Database library
The following package is needed for full translation of the interface
to your language:
@ -44,7 +45,7 @@ The following packages are **STRONGLY RECOMMENDED** to be installed:
It may be osmgpsmap, osm-gps-map, or python-osmgpsmap,
but the Python bindings for this must also be present, so gir1.2-osmgpsmap-1.0.
Without this the GeoView will not be active, see
https://gramps-project.org/wiki/index.php?title=Gramps_4.2_Wiki_Manual_-_Categories#Geography_Category
https://gramps-project.org/wiki/index.php?title=Gramps_5.0_Wiki_Manual_-_Categories#Geography_Category
* **Graphviz**
@ -65,6 +66,10 @@ The following packages are **STRONGLY RECOMMENDED** to be installed:
(These are Python bindings for the ICU package.
https://pypi.python.org/pypi/PyICU/)
* **Ghostscript**
Used by Graphviz reports to help create PDF's
The following packages are optional:
------------------------------------
* **gtkspell**
@ -77,12 +82,12 @@ The following packages are optional:
The GNU Revision Control System (RCS) can be used to manage
multiple revisions of your family trees. See info at
https://gramps-project.org/wiki/index.php?title=Gramps_4.2_Wiki_Manual_-_Manage_Family_Trees#Archiving_a_Family_Tree
https://gramps-project.org/wiki/index.php?title=Gramps_5.0_Wiki_Manual_-_Manage_Family_Trees#Archiving_a_Family_Tree
Only rcs is needed, NO python bindings are required
* **PIL**
Python Image Library is needed to crop
Python Image Library (PILLOW) is needed to crop
images and also to convert non-JPG images to
JPG so as to include them in LaTeX output.
(For Python3 a different source may be needed,
@ -124,6 +129,9 @@ Prerequistes required for the following Addons to work:
* **Graph View** - Requires: PyGoocanvas and Goocanvas (python-pygoocanvas, gir1.2-goocanvas-2.0).
( https://gramps-project.org/wiki/index.php?title=Graph_View )
* **Network Chart** - Requires: networkx and pygraphviz
( https://gramps-project.org/wiki/index.php?title=NetworkChart )
* **PedigreeChart** - Can optionally use - numpy if installed
( https://gramps-project.org/wiki/index.php?title=PedigreeChart )

View File

@ -201,12 +201,12 @@
<date name="Pääsiäispäivä" type="religious" value="> easter(y)" />
<date name="2. Pääsiäispäivä" type="religious" value="> easter(y)" offset="1" />
<date name="Helatorstai" type="religious" value="> easter(y)" offset="39" if="not(y>=1973)" />
<date name="Kristuksen taivaaseenastumisen päivä." type="religious" value="> easter(y)" offset="34" if="(y>=1973) and not(y>=1992)" />
<date name="Kristuksen taivaaseenastumisen päivä" type="religious" value="> easter(y)" offset="34" if="(y>=1973) and not(y>=1992)" />
<date name="Helatorstai" type="religious" value="> easter(y)" offset="39" if="(y>=1992)" />
<date name="Helluntaipäivä" value="easter(y)" offset="49" type="religious" />
<date name="Pyhän Kolminaisuuden päivä" value="easter(y)" offset="56" type="religious" />
<date name="Apostolienpäivä" value="easter(y)" offset="91" type="religious" />
<date name="Kirkastussunnuntai." value="easter(y)" offset="105" type="religious" />
<date name="Kirkastussunnuntai" value="easter(y)" offset="105" type="religious" />
<date name="Juhannusaatto" value="*/jun/19" offset="fri" type="religious" if="(y>=1955)" />
<date name="Juhannusaatto" value="*/jun/23" type="religious" if="not(y>=1955)" />
<date name="Juhannuspäivä" value="*/jun/20" offset="sat" type="religious" if="(y>=1955)" />
@ -224,12 +224,12 @@
<date name="Joulupäivä" value="*/12/25" type="religious" />
<date name="Tapaninpäivä" value="*/12/26" type="religious" />
<date name="Johannes Evankelistan päivä" value="*/dec/27" type="religious" if="not(y>=1774)" />
<date name="Apostoli Johanneksen päivä." value="*/dec/27" type="religious" if="dow(y, m, d) == 7 and (y>=2000)" />
<date name="Apostoli Johanneksen päivä" value="*/dec/27" type="religious" if="dow(y, m, d) == 7 and (y>=2000)" />
<date name="Viattomien lasten päivä" value="*/12/28" type="religious" />
<date name="Uudenvuodenpäivä" value="*/1/1" type="national" />
<date name="Vainojen uhrien muistopäivä" value="*/1/27" type="national" if="(y>=2002)" />
<date name="J.L. Runebergin päivä" value="*/2/5" type="national" if="(y>=1854)" />
<date name="Saamelaisten kansallis päivä" value="*/2/6" type="religious" if="(y>=2004)" />
<date name="Saamelaisten kansallispäivä" value="*/2/6" type="religious" if="(y>=2004)" />
<date name="Ystävänpäivä" value="*/2/14" type="national" if="(y>=1987)" />
<date name="Kalevalan päivä" value="*/2/28" type="national" if="(y>=1978)" />
<date name="Naistenpäivä" value="*/3/8" type="national" if="(y>=1975)" />

24
debian/README.Debian vendored
View File

@ -1,18 +1,18 @@
Gramps for Debian
----------------------
-----------------
This is the Debian package of the 4.0 series of GRAMPS.
Version 5.0 of gramps adds the option of using a new database backend called
DB_API, as an alternative to the default BSDDB (Berkeley).
It is a major update of Gramps to upgrade to GTK 3. A switch was also made to distutils from autotools.
Two DB-API SQL engines have been developed, sqlite3 and postgresql. Compared
to BSDDB, the alternative backends have beend designed allow some flexibility
with respect to using the database with multiple users, or in multiple
locations (different computers).
The 4.0 series of Gramps is being packaged for the experimental distribution until all dependencies are available
and it proves stable.
For more details, please read the Gramps wiki:
https://gramps-project.org/wiki/index.php?title=DB-API_Database_Backend
Webkit - gir1.2-webkit-3.0 crashes. Gramps has been patched disable the hidden
HTML view instead until a solution is found.
Please note, this particular version is a pre-release version for testing.
Please do not use it on your only copy of important genealogical data.
Goocanvas2 - The latest Goocanvas is not available in Debian yet. If you miss
the Graphview plugin, you could try installing the gir1.2-goocanvas-2.0-9 which
is available in Ubuntu.
-- Ross Gammon <rossgammon@mail.dk> Sat, 25 Jan 2014 18:00:00 +0100
-- Ross Gammon <rossgammon@debian.org> Mon, 19 Feb 2018 00:04:00 +0100

157
debian/README.test vendored Normal file
View File

@ -0,0 +1,157 @@
Run gramps -v from the commandline and check dependencies:
- From the commandline type $ gramps -v
- The gramps version and versions of library dependencies are output
- Check that all dependencies have been installed, show their versions, and that there are no error messages
- If required, install the dependencies that have not been found (typically icu, osmgpsmap & gexiv)
- Type $ gramps -v again
- Check that all dependencies have been installed, show their versions, and that there are no error messages
Open Gramps, create an empty Family Tree, and check the Gramps version, credits & license:
- Run gramps
- Family Trees window opens
- Click "New" to create an empty Family Tree
- Type a name for your family tree (e.g. Sample), and press "Enter"
- Click "Load Family Tree"
- Gramps displays the "Welcome to Gramps!" start screen
- Choose Help > About from the menu
- The "About gramps" window is displayed with Version information
- Click on "Credits"
- A list of Authors and Contributors to Gramps is displayed
- Click on "License"
- The GNU General Public License is displayed
- Click on the "X" to close the "About gramps" window
- Gramps closes the "About gramps" window and returns to the "Welcome to Gramps!" start screen
Import a GEDCOM file into Gramps
If you do not have one to hand, the provided example can be extracted to your home directory and imported from there.
/usr/share/doc/gramps/example/gedcom/sample.ged.gz
- From your open and empty Family Tree, choose Family Trees > Import from the menu
- The Gramps: Import Family Tree window opens
- Locate your GEDCOM file, select it and click on "Import"
- The Import Statistics window displays "Results: done"
- Click on "Close"
- The GEDCOM import report window displays "No errors detected"
- CLick on "Close"
- The Top Surnames gramplet displays the surnames of the people imported into the Tree
Test aspects of the People View
- Click on the People View
- A list of people in "Group View" mode are shown
- Click on the arrow for a surname (e.g. Hansdotter)
- The people with this surname are revealed
- Select a person and click in the "Edit selcted person" icon (or just double click on the person)
- The "Person" window opens showing the details of this person
- Click on Cancel
- The "Person" window closes
- Choose the person list view (not grouped) by clicking on the "People" icon
- The people are now listed without any grouping by surname
- Click on the "+" icon to create a new person
- An empty "Person" window opens
- Enter some details about the person (e.g. given name, surname, and gender)
- Click on the "+" button to create a new event for this person
- The "Event Reference Editor" window opens
- Create an event (e.g. birth) by entering a date
- Click on the "+" button to add a new place
- The "New Place" window opens
- Type in some details about the place (Name, Type, Latitude & Longitude)
- Click on OK
- The "New Place" window closes
- In the "Event Reference Editor" click OK
- In the "Person" window click OK
- The "Person" window closes and you can find the person just created in the list of people
Test aspects of the Relationships View
- Click on Anna Hansdotter to select her
- Click on the Relationships View
- Details of Anna and her family are displayed
- Click on one of her children, Hjalmar Smith
- Details of Hjalmar and his family are displayed
- Click on the "Add existing Child to family" icon just above Halmar's children
- The "Select Child" window opens
- Find the person you entered previously and select it
- Click OK
- The "Select Child" window closes and you can see the new person listed as a child in Hjalmar's family
Test aspects of the Charts View
- Click on the Charts View
- The Pedigree View is shown
- Click somewhere in the Pedigree View and drag the chart around
- The mouse pointer changes to a hand and the chart can be move around
- Click on the left and right arrows (when going left you need to choose the child to move to)
- The chart will move to reveal the next generation in the family
- Make sure there are several families in view, then Click on the "Fan Chart" icon
- A fan chart showing the ancesters of the main person is shown
- Click on the Descendant Fan icon
- A fan chart showing the descendants of the same person is shown
Test aspects of the Geography View
- Click on the Geography View
- The map may take some time to load, then a pin for the person you entered early should be shown on the map at the coordinates you entered
- Click on the pin
- A choice of the place, or the person will be offered
- Hover over the place name, and choose "Edit Place"
- The "Place Selection in a region" opens
- Double click on the place
- The "Place:" editor opens
- Click on Cancel
- Click on the pin
- A choice of the place, or the person will be offered
- Hover over the persons name, and choose "Edit Event"
- The "Event:" window opens
- Click on Cancel
Import a Gramps Xml file (*.gramps) into Gramps
An existing Gramps *.gramps file with links to media will be needed for this and the next test. If you do not have one to hand, the provided example can be extracted to your home directory and imported from there.
/usr/share/doc/gramps/example/gramps/example.gramps.gz
- From the "Family Trees" menu, choose "Manage Family Trees"
- The Family Trees window opens
- Click "New" to create an empty Family Tree
- Type a name for your family tree (e.g. Example), and press "Enter"
- Click "Load Family Tree"
- Gramps opens an empty database
- From your open and empty Family Tree, choose Family Trees > Import from the menu
- The Gramps: Import Family Tree window opens
- Locate your *.gramps file, select it and click on "Import"
- The import may take some minutes, then the Import Statistics window displays the number of objects imported.
- Click on "Close"
- The Import Statistics window closes.
View Media for a person, and add new media
The media for the example file you may have used in the previous test can be found in /usr/share/doc/gramps/example/gramps/. Create a folder in your home directory to store Gramps media, and then copy the media there.
You will also need a photo to add to Gramps. Any photo will do (e.g. *.jpg file - but you can use the ones provided with Gramps).
You also need to set the base media patch for Gramps.
- In the "Edit" menu, choose "Preferences".
- The Preferences window opens on the "General" tab.
- Click the "Folder" icon to set the "Base path for relative media paths".
- The "Select media directory" window opens
- Choose the directory where your media is stored and then click "Apply"
- The "Select media directory" window closes
- Click Close
- The "Preferences" window closes
- In the "People" View, find a person with media associated (e.g. Eugene Stanley Garner, Jr. in the example database) and select him/her.
- Below the Detials tab, a thumbnail image of the person should appear (in the case of Eugene Stanley Garner, Jr. you should see him yawning). It may be necessary to restart Gramps to see the Thumbnail.
- Double click on the person's name in the People View.
- The "Person:" window opens, and the image is dispayed for the person in the Image square in the top left corner of the "Person:" window.
- Double click on the image.
- The Media Reference Editor opens showing details about the image.
- Double click in the bottom image Preview.
- An external viewer opens giving details of the image metadata and allowing some basic manipulation of the image.
- Click on the "X" to close the external viewer
- Click "Cancel" on the Media Reference Editor
- Click "Cancel" on the "Person:" window.
- All three windows close.
- Click on the "Media View".
- A list of available media is shown.
- Click on the "+" icon.
- The "Select a media object" window opens.
- Move to the folder where the media is and select the new photo (if you are using the examples provided with Gramps, I can recommend choosing O3.jpg).
- Click on "OK".
- The "New Media" window opens.
- Click on "OK".
- The media is added to the list of media.
- Select the new media.
- A preview (thumbnail) image is shown.
- Close Gramps by choosing "Quit" from the "Family Trees" menu.
- Gramps closes.
TODO: Tagging & Filtering

101
debian/changelog vendored
View File

@ -1,4 +1,101 @@
Old Changelog:
gramps (5.0.0~beta1-1) unstable; urgency=medium
* First beta release of gramps 5.0
* Sync debian directory with Debian experimental branch on salsa
* Point Vcs URLs at the Gramps Project on Github
* Correct spelling in debian/rules, node > nose
* Delete gbp.conf, not required as gbp not used to build package
* Delete NEWS file, only really applicable in Debian
* Fix syntax errors in d/changelog and remove trailing whitespace
* Patch person_rules_test.py to remove hard coded build path from
import. Fixes FTBFS due to test failure.
* Enable extra tests that were failing for alpha3
-- Ross Gammon <rossgammon@debian.org> Mon, 19 Feb 2018 19:25:25 +0100
gramps (4.2.8) unstable; urgency=medium
* Quick bug fix release
-- Ross Gammon <rossgammon@debian.org> Sat, 10 Feb 2018 08:30:33 +0100
gramps (5.0.0-alpha3) experimental; urgency=medium
* New alpha release for Gramps 5.0.0
-- Ross Gammon <rossgammon@debian.org> Mon, 04 Sep 2017 16:55:41 +0200
gramps (4.2.6) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.6
-- Jérôme Rapinat <romjerome@yahoo.fr> Tue, 01 Aug 2017 14:10:19 +0200
gramps (5.0.0-alpha2) experimental; urgency=medium
* 2nd Alpha release for testing
-- Ross Gammon <rosco2@ubuntu.com> Mon, 12 Jun 2017 19:42:39 +0200
gramps (4.2.5) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.5
-- Jérôme Rapinat <romjerome@yahoo.fr> Thu, 15 Dec 2016 18:52:08 +0100
gramps (4.2.4) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.4
-- Jérôme Rapinat <romjerome@yahoo.fr> Sun, 04 Sep 2016 18:34:49 +0200
gramps (5.0.0-alpha1) UNRELEASED; urgency=medium
* Alpha stream for Gramps 5.0.0
-- système <romjerome@yahoo.fr> Sat, 04 Jun 2016 20:07:14 +0200
gramps (4.2.3) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.3
-- Jérôme Rapinat <romjerome@yahoo.fr> Sun, 10 Apr 2016 21:09:19 +0200
gramps (4.2.2) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.2
-- Jérôme Rapinat <romjerome@yahoo.fr> Wed, 06 Jan 2016 19:38:25 +0100
gramps (4.2.1) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.1
-- Jérôme Rapinat <romjerome@yahoo.fr> Tue, 13 Oct 2015 05:08:30 +0200
gramps (4.2.0) UNRELEASED; urgency=medium
* New upstream for Gramps 4.2.0
-- Jérôme Rapinat <romjerome@yahoo.fr> Sun, 02 Aug 2015 17:03:37 +0200
gramps (4.1.3) precise; urgency=low
* New upstream for Gramps 4.1 branch (4.1.3)
-- Jérôme Rapinat <romjerome@yahoo.fr> Thu, 30 Apr 2015 18:42:34 +0200
gramps (3.4.9-1) precise; urgency=low
* New upstream release for 3.4.x branch
-- Jérôme Rapinat <romjerome@yahoo.fr> Thu, 30 Apr 2015 16:02:44 +0200
gramps (4.0.4) precise; urgency=low
* New upsteam for Gramps 4.0.4
-- Jérôme Rapinat <romjerome@yahoo.fr> Fri, 23 May 2014 17:07:41 +0200
gramps (4.0.3) precise; urgency=low
@ -10,7 +107,7 @@ gramps (4.0.2) precise; urgency=low
* experimental .deb for gramps 4.0.2
-- Jérôme Rapinat <romjerome@yahoo.fr> Wed, 04 Dec 2013 10:23:36 +0100
-- Jérôme Rapinat <romjerome@yahoo.fr> Wed, 04 Dec 2013 10:23:36 +0100
gramps (4.0.1-2) precise; urgency=low

2
debian/compat vendored
View File

@ -1 +1 @@
9
11

51
debian/control vendored
View File

@ -1,29 +1,38 @@
Source: gramps
Section: python
Section: gnome
Priority: optional
Maintainer: Ross Gammon <rossgammon@mail.dk>
Maintainer: Ross Gammon <rossgammon@debian.org>
Build-Depends-Indep:
dh-linktree,
dh-python,
gettext,
intltool,
libxml-parser-perl,
python3-all,
python3-setuptools
python3-setuptools,
python3-nose,
gir1.2-gtk-3.0 (>= 3.10.0),
python3-gi (>= 3.12.0),
python3-gi-cairo,
python3-bsddb3,
python3-lxml,
python3-jsonschema,
python3-mock,
python3-icu,
python3-nose-exclude
Build-Depends:
dh-python,
debhelper (>= 9.0.0)
Standards-Version: 3.9.5
Vcs-Git: git://anonscm.debian.org/collab-maint/gramps.git
Vcs-browser: http://anonscm.debian.org/gitweb/?p=collab-maint/gramps.git
Homepage: http://www.gramps-project.org/
X-Python-Version: >= 3.2
debhelper (>= 11)
Standards-Version: 4.1.3
Vcs-Git: https://github.com/gramps-project/gramps.git
Vcs-browser: https://github.com/gramps-project/gramps/tree/maintenance/gramps50
Homepage: https://www.gramps-project.org/
X-Python3-Version: >= 3.2
Package: python3-gramps
Package: gramps
Architecture: all
Depends:
gir1.2-gtk-3.0 (>= 3.10.0),
librsvg2-2,
python3-gi,
python3-gi (>= 3.12.0),
python3-gi-cairo,
python3-bsddb3,
xdg-utils,
@ -31,16 +40,22 @@ Depends:
${python3:Depends}
Recommends:
graphviz,
gir1.2-goocanvas-2.0,
libosmgpsmap-1.0-0,
gir1.2-gexiv2-0.10,
gir1.2-osmgpsmap-1.0,
python3-pyicu
python3-icu
Suggests:
fonts-freefont-ttf,
gir1.2-gexiv2-0.10,
gir1.2-goocanvas-2.0,
gir1.2-gtkspell3-3.0,
python3-pil,
rcs
rcs,
python3-numpy
Conflicts:
python-gramps,
python3-gramps
Replaces:
python-gramps,
python3-gramps
Description: Genealogical research program
Gramps is an Open Source genealogy program written in Python, using
the GTK/GNOME interface. It is an extremely flexible program fitting

276
debian/copyright vendored
View File

@ -1,37 +1,37 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Gramps
Source: http://gramps-project.org
Source: https://gramps-project.org
Files: *
Copyright: 2000-2007, Alex Roitman
2000-2002, Bruce J. DeGrasse
2000-2008, Donald N. Allingham
2000-2007, Martin Hawlisch
2001, Andrés Sepúlveda
2001, Andrés Sepúlveda
2001, David R. Hampton
2001-2013, Free Software Foundation, Inc.
2001-2017, Free Software Foundation, Inc.
2001, Graham J. Williams
2001, Jesper Zedlitz
2001-2013, The Gramps Project
2001-2017, The Gramps Project
2002, Gary Shao
2003-2006, Josiah Carlson
2004-2006, Eero Tamminen
2004-2013, Julio Sánchez
2004, Toshio Kuratomi
2005-2011, Serge Noiraud
2006-2011, Brian G. Matherly
2004-2013, Julio Sánchez
2005-2017, Serge Noiraud
2006-2012, Brian G. Matherly
2006, 2008-2011, Kees Bakker
2006-2008, Steve Hall
2007-2012, Benny Malengier
2007-2012, Douglas S. Blank
2007-2013, Benny Malengier
2007-2013, 2015-2016, Douglas S. Blank
2007-2012, Gary Burton
2007-2011, Jerome Rapinat
2007, Johan Gronqvist
2007, Robert Cawley
2007-2009, Stephane Charette
2007-2016, The Gramps Developers
2007, Thom Sturgill
2007-2008, Zsolt Foldvari
2008-2010, 2012, Craig J. Anderson
2008-2010, 2012-2015, Craig J. Anderson
2008-2009, James Friedmann
2008-2009, Jason Simanek
2008, Lukasz Rymarczyk
@ -43,133 +43,58 @@ Copyright: 2000-2007, Alex Roitman
2008, Stefan Siegel
2008-2010, Stephen George
2009-2010, Andrew I Baznikin
2009, 2011, The Dojo Foundation
2009, Florian Heinle
2009, Gerald W. Britton
2009, Igal Shapira
2009, 2011, John Resig
2009-2013, Nick Hall
2009-2018, Nick Hall
2009, Pander Musubi
2009, Robert Ham
2009, Swoon on bug tracker
2009, Yevgeny Zegzda
2010, Gramps
2010, 2015 Gramps
2010, Jakim Friant
2010, Josip
2010, lcc & Robert Jerome
2010-2012, Michiel D. Nauta
2010-2013, Tim G L Lyons
2010-2011, Vlada Perić
2010-2016, Tim G L Lyons
2010-2011, 2014, Vlada Perić
2011, Adam Stein
2011-2012, Harald Rosemann
2011, 2013, Heinz Brinker
2011, Helge Herz
2011, 2013 John Ralls
2011, Matt Keenan
2011-2013, Paul Franklin
2012, Mathieu MD
2011, 2016 Matt Keenan
2011-2017, Paul Franklin
2012, lcc
2012, 2014, Mathieu MD
2012, Nicolas Adenis-Lamarre
2013, Fedir Zinchuk
2013, Oleh Petrivk
2013, Vassilii Khachaturov
2013, Artem Glebov
2011-2016, Fedir Zinchuk
2013-2017, Alois Poettker
2013-2014, Vassilii Khachaturov
2013, Zissis Papadopoulos
2015, Icelandic translators of Gramps
2014, Bastien Jacquet
2014, Gerald Kunzmann
2015, Fabrice
2015, Lajos Nemeséri
2015, Detlef Wolz
2016, Allen Crider
2016, DaAwesomeP
2016-2017, Paul Culley
2016, QuLogic
2016, Tom Samstag
2017, Mindaugas Baranauskas
2017, Robert Carnell
License: GPL-2+
Files: data/javascript/jquery-1.3.2.min.js
Copyright: 2009, John Resig
License: MIT and GPL
Files: data/javascript/jquery-1.7.1.js
Copyright: 2011, John Resig
2011, The Dojo Foundation
License: BSD and MIT and GPL-2
Files: data/javascript/jquery-ui-1.7.2.custom.min.js
Copyright: 2009, jQuery UI Team (http://jqueryui.com/about/)
License: MIT and GPL-2
Files: data/javascript/jquery.flexbox*
Copyright: 2008-2010, Noah Heldman and Fairway Technologies
License: Ms-PL
Files: data/jhtmlarea/Readme.txt
Copyright: 2009, Chris Pietschmann
License: Ms-RL
Files: data/jhtmlarea/scripts/jHtmlArea*
Copyright: 2009, Chris Pietschmann
License: Ms-RL
Files: data/jhtmlarea/scripts/jquery-1.3.2*
Copyright: 2009, John Resig
2009, The Dojo Foundation
License: MIT
Files: data/jhtmlarea/scripts/jquery-ui-*
Copyright: 2009, jQuery UI Team (http://jqueryui.com/about)
License: MIT and GPL
Files: debian/*
Copyright: 2001-2002, Brandon L. Griffith
2002, Alex Roitman
2002-2012, James A. Treacy
2013, Ross Gammon
2013-2018, Ross Gammon
License: GPL-2+
Files: gramps/webapp/grampsdb/view/png.py
Copyright: 2006, Johann C. Rocholl
2009, David Jones
2006, Nicko van Someren
License: MIT
License: BSD
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY John Resig ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: GPL
This package 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; version 1 only of the License.
.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL'.
License: GPL-2
This package 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; version 2 only of the License.
.
This package 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 package; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL-2'.
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -187,128 +112,3 @@ License: GPL-2+
.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL-2'.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
License: Ms-PL
This license governs use of the accompanying software. If you use the
software, you accept this license. If you do not accept the license, do not
use the software.
.
1. Definitions
.
The terms "reproduce," "reproduction," "derivative works," and "distribution"
have the same meaning here as under U.S. copyright law.
.
A "contribution" is the original software, or any additions or changes to the
software.
.
A "contributor" is any person that distributes its contribution under this
license.
.
"Licensed patents" are a contributor's patent claims that read directly on its
contribution.
.
2. Grant of Rights
.
(A) Copyright Grant- Subject to the terms of this license, including the
license conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free copyright license to reproduce its
contribution, prepare derivative works of its contribution, and distribute its
contribution or any derivative works that you create.
.
(B) Patent Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free license under its licensed patents to
make, have made, use, sell, offer for sale, import, and/or otherwise dispose of
its contribution in the software or derivative works of the contribution in the
software.
.
3. Conditions and Limitations
.
(A) No Trademark License- This license does not grant you rights to use any
contributors' name, logo, or trademarks.
.
(B) If you bring a patent claim against any contributor over patents that you
claim are infringed by the software, your patent license from such contributor
to the software ends automatically.
.
(C) If you distribute any portion of the software, you must retain all copyright,
patent, trademark, and attribution notices that are present in the software.
.
(D) If you distribute any portion of the software in source code form, you may do
so only under this license by including a complete copy of this license with your
distribution. If you distribute any portion of the software in compiled or object
code form, you may only do so under a license that complies with this license.
.
(E) The software is licensed "as-is." You bear the risk of using it. The
contributors give no express warranties, guarantees or conditions. You may have
additional consumer rights under your local laws which this license cannot change.
To the extent permitted under your local laws, the contributors exclude the
implied warranties of merchantability, fitness for a particular purpose and
non-infringement.
License: Ms-RL
This license governs use of the accompanying software. If you use the software,
you accept this license. If you do not accept the license, do not use the software.
.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have
the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the
software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its
contribution.
.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free copyright license to reproduce its
contribution, prepare derivative works of its contribution, and distribute its
contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license
conditions and limitations in section 3, each contributor grants you a
non-exclusive, worldwide, royalty-free license under its licensed patents to make,
have made, use, sell, offer for sale, import, and/or otherwise dispose of its
contribution in the software or derivative works of the contribution in the software.
.
3. Conditions and Limitations
(A) Reciprocal Grants- For any file you distribute that contains code from the
software (in source code or binary format), you must provide recipients the source
code to that file along with a copy of this license, which license will govern that
file. You may license other files that are entirely your own work and do not contain
code from the software under any terms you choose.
(B) No Trademark License- This license does not grant you rights to use any
contributors' name, logo, or trademarks.
(C) If you bring a patent claim against any contributor over patents that you claim
are infringed by the software, your patent license from such contributor to the
software ends automatically.
(D) If you distribute any portion of the software, you must retain all copyright,
patent, trademark, and attribution notices that are present in the software.
(E) If you distribute any portion of the software in source code form, you may do so
only under this license by including a complete copy of this license with your
distribution. If you distribute any portion of the software in compiled or object code
form, you may only do so under a license that complies with this license.
(F) The software is licensed "as-is." You bear the risk of using it. The contributors
give no express warranties, guarantees or conditions. You may have additional consumer
rights under your local laws which this license cannot change. To the extent permitted
under your local laws, the contributors exclude the implied warranties of
merchantability, fitness for a particular purpose and non-infringement.

1
debian/gramps.docs vendored Normal file
View File

@ -0,0 +1 @@
RELEASE_NOTES

View File

@ -0,0 +1,24 @@
Description: Remove hard coded build path from import
gramps/gen/filters/rules/test/person_rules_test.py contains an import
that hard codes the normal build path when working in the source tree.
This causes the test to fail when building the Debian package, which
happens out of the source tree.
This patch imports using .... instead of build/lib for the path for the
MatchIdOf function (the same as the other imports in the file).
Author: Ross Gammon <rossgammon@debian.org>
Forwarded: not-yet
Applied-Upstream: not-yet
Last-Update: 2018-02-19
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- gramps.orig/gramps/gen/filters/rules/test/person_rules_test.py
+++ gramps/gramps/gen/filters/rules/test/person_rules_test.py
@@ -17,7 +17,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
-from build.lib.gramps.gen.filters.rules.person._matchidof import MatchIdOf
+from ....filters.rules.person._matchidof import MatchIdOf
"""
Unittest that tests person-specific filter rules

1
debian/patches/series vendored Normal file
View File

@ -0,0 +1 @@
hardcoded_path_person_rules_test.patch

47
debian/rules vendored
View File

@ -1,35 +1,38 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
export DH_OPTIONS=-v
#export DH_VERBOSE=1
#export DH_OPTIONS=-v
export PYBUILD_NAME=gramps
export PYBUILD_INSTALL_ARGS_python3=--resourcepath=/usr/share --force
%:
dh $@ --with python3 --buildsystem=pybuild
# Override auto test because upstream do not use the standard unittest discover
# Override auto test to enable nose tests
override_dh_auto_test:
# Override of auto_build
override_dh_auto_build:
python3 setup.py build
HOME=$(CURDIR)/build \
nosetests3 -vv \
--exclude=TestcaseGenerator \
--exclude=test4_arbitrary_uncode_path \
--exclude-dir=gramps/plugins/test/ \
gramps
# Override of auto_install to remove information from package
override_dh_auto_install:
#dh_auto_install
python3 setup.py install --resourcepath=/usr/share --root=debian/python3-gramps --install-layout=deb
# Remove duplicate license/copyright information
rm $(CURDIR)/debian/python3-gramps/usr/share/doc/gramps/COPYING
dh_installchangelogs NEWS
dh_auto_install
# Remove install file as it is not needed by package users
rm $(CURDIR)/debian/python3-gramps/usr/share/doc/gramps/INSTALL
# Link license/copyright information to debians
ln -s /usr/share/common-licenses/GPL-2 $(CURDIR)/debian/python3-gramps/usr/share/doc/gramps/COPYING
rm $(CURDIR)/debian/gramps/usr/share/doc/gramps/INSTALL
# Remove NEWS file as it is now installed as the changelog
rm $(CURDIR)/debian/gramps/usr/share/doc/gramps/NEWS
#Remove license information in COPYING file & link to system license
rm $(CURDIR)/debian/gramps/usr/share/doc/gramps/COPYING
ln -s /usr/share/common-licenses/GPL-2 $(CURDIR)/debian/gramps/usr/share/doc/gramps/COPYING
# Make css style sheets and png icons non-executable
override_dh_fixperms:
dh_fixperms
chmod a-x $(CURDIR)/debian/python3-gramps/usr/share/gramps/css/Web_*.css
# Avoid compressing COPYING file so that it can appear in the "About" dialog
override_dh_compress:
dh_compress -X COPYING
# Fix clean target
override_dh_clean:
rm -rf data/tips.xml
rm -rf gramps/plugins/lib/holidays.xml
rm -rf po/.intltool-merge-cache
dh_clean

View File

@ -1 +1 @@
1.8
3.0 (quilt)

1
debian/source/local-options vendored Normal file
View File

@ -0,0 +1 @@
unapply-patches

3
debian/tests/control vendored Normal file
View File

@ -0,0 +1,3 @@
Tests: gramps-import-export
Depends: gramps, gzip
Restrictions: allow-stderr

38
debian/tests/gramps-import-export vendored Executable file
View File

@ -0,0 +1,38 @@
#!/bin/sh
# Author: Ross Gammon <rossgammon@mail.dk>
#
# autopkgtest check: Tests that gramps can import the sample gedcom file and
# export it in the .gpkg format, and then import the example gramps database
# and export it in gedcom format.
set -e
echo "--------------------------------"
echo "GEDCOM to Gramps conversion test"
echo "--------------------------------"
echo "Retrieving sample gedcom"
cp /usr/share/doc/gramps/example/gedcom/sample.ged.gz .
echo "Unzipping sample gedcom"
gunzip sample.ged.gz
echo "Importing gedcom into gramps and exporting a gramps .gpkg file"
gramps -i sample.ged -e sample.gpkg
echo "-----------------------------------"
echo "GEDCOM to Gramps conversion SUCCESS"
echo "-----------------------------------"
echo
echo "--------------------------------"
echo "Gramps to GEDCOM conversion test"
echo "--------------------------------"
echo "Retrieving example gramps file"
cp /usr/share/doc/gramps/example/gramps/example.gramps.gz .
echo "Unzipping example gramps file"
gunzip example.gramps.gz
echo "Importing gramps file into gramps and exporting a gedcom"
gramps -i example.gramps -e example.ged
echo "-----------------------------------"
echo "Gramps to GEDCOM conversion SUCCESS"
echo "-----------------------------------"
echo
echo "gramps-import-export: TEST PASSED"

7
debian/upstream/metadata vendored Normal file
View File

@ -0,0 +1,7 @@
Bug-Database: https://gramps-project.org/bugs/my_view_page.php
Contact: https://lists.sourceforge.net/lists/listinfo/gramps-users
Donation: https://sourceforge.net/project/project_donations.php?group_id=25770
Name: Gramps
Homepage: https://gramps-project.org/
Repository: https://github.com/gramps-project/gramps.git
Repository-Browse: https://github.com/gramps-project/gramps

8
debian/watch vendored Normal file
View File

@ -0,0 +1,8 @@
version=3
opts=\
dversionmangle=s/(\~|\+)(debian|dfsg|ds|deb)(\.\d+)?$//,\
filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/$1\.tar\.gz/,\
repacksuffix=~dfsg \
https://github.com/gramps-project/gramps/tags \
.*/archive/v?([\d\.]+).tar.gz

View File

@ -57,7 +57,7 @@ master_doc = 'index'
# General information about the project.
project = 'Gramps'
copyright = '2017, The Gramps Project'
copyright = '2001-2018, The Gramps Project'
author = 'Donald N. Allingham'
# The version info for the project you're documenting, acts as replacement for

View File

@ -46,7 +46,7 @@ Generic
DummyDb
====================================
.. automodule:: gramps.plugins.db.dummydb
.. automodule:: gramps.gen.db.dummydb
:members:
:undoc-members:
:show-inheritance:

View File

@ -249,11 +249,8 @@ register('preferences.hide-ep-msg', False)
register('preferences.invalid-date-format', "<b>%s</b>")
register('preferences.iprefix', 'I%04d')
register('preferences.name-format', 1)
register('preferences.place-format', 0)
register('preferences.place-auto', True)
register('preferences.place-number', False)
register('preferences.place-reverse', False)
register('preferences.place-restrict', 0)
register('preferences.place-lang', '')
register('preferences.patronimic-surname', False)
register('preferences.no-given-text', "[%s]" % _("Missing Given Name"))
register('preferences.no-record-text', "[%s]" % _("Missing Record"))

View File

@ -112,6 +112,7 @@ VERSION_DIR = os.path.join(
CUSTOM_FILTERS = os.path.join(VERSION_DIR, "custom_filters.xml")
REPORT_OPTIONS = os.path.join(HOME_DIR, "report_options.xml")
TOOL_OPTIONS = os.path.join(HOME_DIR, "tool_options.xml")
PLACE_FORMATS = os.path.join(HOME_DIR, "place_formats.xml")
ENV_DIR = os.path.join(HOME_DIR, "env")
TEMP_DIR = os.path.join(HOME_DIR, "temp")
@ -217,7 +218,7 @@ GTK_GETTEXT_DOMAIN = 'gtk30'
#
#-------------------------------------------------------------------------
COPYRIGHT_MSG = "© 2001-2006 Donald N. Allingham\n" \
"© 2007-2017 The Gramps Developers"
"© 2007-2018 The Gramps Developers"
COMMENTS = _("Gramps\n (Genealogical Research and Analysis "
"Management Programming System)\n"
"is a personal genealogy program.")

View File

@ -1,7 +1,7 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2014-2015 Nick Hall
# Copyright (C) 2014-2017 Nick Hall
#
# 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
@ -22,15 +22,43 @@
Class handling displaying of places.
"""
#---------------------------------------------------------------
#
# Python imports
#
#---------------------------------------------------------------
import os
import xml.dom.minidom
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from ..const import PLACE_FORMATS
from ..config import config
from ..utils.location import get_location_list
from ..lib import PlaceType
#-------------------------------------------------------------------------
#
# PlaceFormat class
#
#-------------------------------------------------------------------------
class PlaceFormat:
def __init__(self, name, levels, language, street, reverse):
self.name = name
self.levels = levels
self.language = language
self.street = street
self.reverse = reverse
def to_xml(self):
return (' <format name="%s" levels="%s" language="%s" '
'street="%s" reverse="%s"/>\n' %
(self.name, self.levels, self.language,
self.street, self.reverse))
#-------------------------------------------------------------------------
#
# PlaceDisplay class
@ -38,51 +66,121 @@ from ..lib import PlaceType
#-------------------------------------------------------------------------
class PlaceDisplay:
def display_event(self, db, event):
def __init__(self):
self.place_formats = []
self.default_format = config.get('preferences.place-format')
if os.path.exists(PLACE_FORMATS):
self.load_formats()
else:
pf = PlaceFormat('Full', ':', '', 0, False)
self.place_formats.append(pf)
def display_event(self, db, event, fmt=None):
if not event:
return ""
place_handle = event.get_place_handle()
if place_handle:
place = db.get_place_from_handle(place_handle)
return self.display(db, place, event.get_date_object())
return self.display(db, place, event.get_date_object(), fmt)
else:
return ""
def display(self, db, place, date=None):
def display(self, db, place, date=None, fmt=None):
if not place:
return ""
if not config.get('preferences.place-auto'):
return place.title
else:
lang = config.get('preferences.place-lang')
places = get_location_list(db, place, date, lang)
if fmt is None:
fmt = config.get('preferences.place-format')
pf = self.place_formats[fmt]
lang = pf.language
all_places = get_location_list(db, place, date, lang)
if config.get('preferences.place-restrict') > 0:
index = _find_populated_place(places)
if index is not None:
if config.get('preferences.place-restrict') == 1:
places = places[:index+1]
# Apply format string to place list
index = _find_populated_place(all_places)
places = []
for slice in pf.levels.split(','):
parts = slice.split(':')
if len(parts) == 1:
offset = _get_offset(parts[0], index)
if offset is not None:
places.append(all_places[offset])
elif len(parts) == 2:
start = _get_offset(parts[0], index)
end = _get_offset(parts[1], index)
if start is None:
places.extend(all_places[:end])
elif end is None:
places.extend(all_places[start:])
else:
places = places[index:]
places.extend(all_places[start:end])
if config.get('preferences.place-number'):
if pf.street:
types = [item[1] for item in places]
try:
idx = types.index(PlaceType.NUMBER)
except ValueError:
idx = None
if idx is not None and len(places) > idx+1:
if pf.street == 1:
combined = (places[idx][0] + ' ' + places[idx+1][0],
places[idx+1][1])
else:
combined = (places[idx+1][0] + ' ' + places[idx][0],
places[idx+1][1])
places = places[:idx] + [combined] + places[idx+2:]
names = [item[0] for item in places]
if config.get('preferences.place-reverse'):
if pf.reverse:
names.reverse()
# TODO for Arabic, should the next line's comma be translated?
return ", ".join(names)
def get_formats(self):
return self.place_formats
def set_formats(self, formats):
self.place_formats = formats
def load_formats(self):
dom = xml.dom.minidom.parse(PLACE_FORMATS)
top = dom.getElementsByTagName('place_formats')
for fmt in top[0].getElementsByTagName('format'):
name = fmt.attributes['name'].value
levels = fmt.attributes['levels'].value
language = fmt.attributes['language'].value
street = int(fmt.attributes['street'].value)
reverse = fmt.attributes['reverse'].value == 'True'
pf = PlaceFormat(name, levels, language, street, reverse)
self.place_formats.append(pf)
dom.unlink()
def save_formats(self):
with open(PLACE_FORMATS, 'w') as fd:
fd.write('<?xml version="1.0" encoding="utf-8"?>\n')
fd.write('<place_formats>\n')
for fmt in self.place_formats:
fd.write(fmt.to_xml())
fd.write('</place_formats>\n')
def _get_offset(value, index):
if index is not None and value.startswith('p'):
try:
offset = int(value[1:])
except ValueError:
offset = 0
offset += index
else:
try:
offset = int(value)
except ValueError:
offset = None
return offset
def _find_populated_place(places):
populated_place = None
for index, item in enumerate(places):

View File

@ -17,7 +17,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
from build.lib.gramps.gen.filters.rules.person._matchidof import MatchIdOf
from ....filters.rules.person._matchidof import MatchIdOf
"""
Unittest that tests person-specific filter rules

View File

@ -1002,7 +1002,7 @@ class GVPdfGsDoc(GVDocBase):
os.system(command)
# Merge pieces to single multipage PDF ;
command = '%s -q -dBATCH -dNOPAUSE '\
'-sOUTPUTFILE=%s -r72 -sDEVICE=pdfwrite %s '\
'-sOUTPUTFILE="%s" -r72 -sDEVICE=pdfwrite %s '\
% (_GS_CMD, self._filename, ' '.join(list_of_pieces))
os.system(command)

View File

@ -26,6 +26,8 @@
from abc import ABCMeta, abstractmethod
import os
import shutil
import re
from subprocess import Popen, PIPE
from io import StringIO
import tempfile
import logging
@ -97,9 +99,25 @@ _NOTESIZE = [{'name': _("Tiny"), 'value': "tiny"},
if win():
_LATEX_FOUND = search_for("lualatex.exe")
DETACHED_PROCESS = 8
else:
_LATEX_FOUND = search_for("lualatex")
def escape(text):
lookup = {
'&': '\\&',
'%': '\\%',
'$': '\\$',
'#': '\\#',
'_': '\\_',
'{': '\\{',
'}': '\\}',
'~': '\\~{}',
'^': '\\^{}',
'\\': '\\textbackslash{}'
}
pattern = re.compile('|'.join([re.escape(key) for key in lookup.keys()]))
return pattern.sub(lambda match: lookup[match.group(0)], text)
#------------------------------------------------------------------------------
#
@ -415,8 +433,8 @@ class TreeDocBase(BaseDoc, TreeDoc):
nick = name.get_nick_name()
surn = name.get_surname()
name_parts = [self.format_given_names(name),
'\\nick{{{}}}'.format(nick) if nick else '',
'\\surn{{{}}}'.format(surn) if surn else '']
'\\nick{{{}}}'.format(escape(nick)) if nick else '',
'\\surn{{{}}}'.format(escape(surn)) if surn else '']
self.write(level+1, 'name = {{{}}},\n'.format(
' '.join([e for e in name_parts if e])))
for eventref in person.get_event_ref_list():
@ -432,13 +450,17 @@ class TreeDocBase(BaseDoc, TreeDoc):
self.write_event(db, level+1, event)
for attr in person.get_attribute_list():
if str(attr.get_type()) == 'Occupation':
self.write(level+1, 'profession = {%s},\n' % attr.get_value())
self.write(level+1, 'profession = {%s},\n' %
escape(attr.get_value()))
if str(attr.get_type()) == 'Comment':
self.write(level+1, 'comment = {%s},\n' % attr.get_value())
self.write(level+1, 'comment = {%s},\n' %
escape(attr.get_value()))
for mediaref in person.get_media_list():
media = db.get_media_from_handle(mediaref.ref)
path = media_path_full(db, media.get_path())
if os.path.isfile(path):
if win():
path = path.replace('\\', '/')
self.write(level+1, 'image = {%s},\n' % path)
break # first image only
self.write(level, '}\n')
@ -496,7 +518,7 @@ class TreeDocBase(BaseDoc, TreeDoc):
stop_date = self.format_iso(date.get_stop_ymd(), calendar)
date_str = date_str + '/' + stop_date
place = _pd.display_event(db, event)
place = escape(_pd.display_event(db, event))
if modifier:
event_type += '+'
@ -519,14 +541,14 @@ class TreeDocBase(BaseDoc, TreeDoc):
if call in first:
where = first.index(call)
return '{before}\\pref{{{call}}}{after}'.format(
before=first[:where],
call=call,
after=first[where+len(call):])
before=escape(first[:where]),
call=escape(call),
after=escape(first[where+len(call):]))
else:
# ignore erroneous call name
return first
return escape(first)
else:
return first
return escape(first)
def format_iso(self, date_tuple, calendar):
"""
@ -582,7 +604,7 @@ class TreeTexDoc(TreeDocBase):
if self._filename[-4:] != ".tex":
self._filename += ".tex"
with open(self._filename, "w") as texfile:
with open(self._filename, 'w', encoding='utf-8') as texfile:
texfile.write(self._tex.getvalue())
@ -605,11 +627,16 @@ class TreePdfDoc(TreeDocBase):
self._filename += ".pdf"
with tempfile.TemporaryDirectory() as tmpdir:
with open(os.path.join(tmpdir, 'temp.tex'), "w") as texfile:
texfile.write(self._tex.getvalue())
os.system('lualatex -output-directory %s temp.tex >/dev/null'
% tmpdir)
shutil.copy(os.path.join(tmpdir, 'temp.pdf'), self._filename)
basename = os.path.basename(self._filename)
args = ['lualatex', '-output-directory', tmpdir,
'-jobname', basename[:-4]]
if win():
proc = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE,
creationflags=DETACHED_PROCESS)
else:
proc = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
proc.communicate(input=self._tex.getvalue().encode('utf-8'))
shutil.copy(os.path.join(tmpdir, basename), self._filename)
#------------------------------------------------------------------------------

View File

@ -32,6 +32,7 @@ from ...config import config
from ...datehandler import get_date_formats, LANG_TO_DISPLAY, main_locale
from ...display.name import displayer as global_name_display
from ...lib.date import Today
from ...display.place import displayer as _pd
from ..menu import EnumeratedListOption, BooleanOption, NumberOption
from ...proxy import PrivateProxyDb, LivingProxyDb
from ...utils.grampslocale import GrampsLocale
@ -327,3 +328,16 @@ def add_gramps_id_option(menu, category, ownline=False):
include_id.add_item(1, _('Include'))
include_id.set_help(_("Whether to include Gramps IDs"))
menu.add_option(category, 'inc_id', include_id)
def add_place_format_option(menu, category):
"""
Insert an option for changing the report's place format to a
report-specific format instead of the user's Edit=>Preferences choice
"""
place_format = EnumeratedListOption(_("Place format"), None)
place_format.add_item(None, _("Default"))
for number, fmt in enumerate(_pd.get_formats()):
place_format.add_item(number, fmt.name)
place_format.set_help(_("Select the format to display places"))
menu.add_option(category, "place_format", place_format)
return place_format

View File

@ -1540,6 +1540,8 @@ class MultiTreeView(Gtk.TreeView):
if is_right_click(event):
selection = widget.get_selection()
store, paths = selection.get_selected_rows()
if not paths:
return
tpath = paths[0] if len(paths) > 0 else None
node = store.get_iter(tpath) if tpath else None
o = None

View File

@ -53,6 +53,7 @@ from gramps.gen.const import HOME_DIR, URL_WIKISTRING
from gramps.gen.datehandler import get_date_formats
from gramps.gen.display.name import displayer as _nd
from gramps.gen.display.name import NameDisplayError
from gramps.gen.display.place import displayer as _pd
from gramps.gen.utils.alive import update_constants
from gramps.gen.utils.file import media_path
from gramps.gen.utils.keyword import (get_keywords, get_translation_from_keyword,
@ -62,6 +63,7 @@ from gramps.gen.lib import Name, Surname, NameOriginType
from .managedwindow import ManagedWindow
from .widgets import MarkupLabel, BasicLabel
from .dialog import ErrorDialog, QuestionDialog2, OkDialog
from .editors.editplaceformat import EditPlaceFormat
from .glade import Glade
from gramps.gen.plug.utils import available_updates
from .plug import PluginWindows
@ -511,7 +513,6 @@ class GrampsPreferences(ConfigureDialog):
self.add_behavior_panel,
self.add_famtree_panel,
self.add_formats_panel,
self.add_places_panel,
self.add_text_panel,
self.add_prefix_panel,
self.add_date_panel,
@ -931,6 +932,13 @@ class GrampsPreferences(ConfigureDialog):
_nd.set_default_format(new_idx)
self.uistate.emit('nameformat-changed')
def cb_place_fmt_changed(self, obj):
"""
Called when the place format is changed.
"""
config.set('preferences.place-format', obj.get_active())
self.uistate.emit('placeformat-changed')
def cb_pa_sur_changed(self,*args):
"""
checkbox patronymic as surname changed, propagate to namedisplayer
@ -1052,6 +1060,34 @@ class GrampsPreferences(ConfigureDialog):
grid.attach(obox, 1, row, 2, 1)
row += 1
# Place format:
self.pformat = Gtk.ComboBox()
renderer = Gtk.CellRendererText()
self.pformat.pack_start(renderer, True)
self.pformat.add_attribute(renderer, "text", 0)
self.cb_place_fmt_rebuild()
active = config.get('preferences.place-format')
self.pformat.set_active(active)
self.pformat.connect('changed', self.cb_place_fmt_changed)
lwidget = BasicLabel(_("%s: ") % _('Place format'))
lwidget.set_use_underline(True)
lwidget.set_mnemonic_widget(obox)
hbox = Gtk.Box()
self.fmt_btn = Gtk.Button(label=("%s..." % _('Edit')))
self.fmt_btn.connect('clicked', self.cb_place_fmt_dialog)
hbox.pack_start(self.pformat, True, True, 0)
hbox.pack_start(self.fmt_btn, False, False, 0)
grid.attach(lwidget, 0, row, 1, 1)
grid.attach(hbox, 1, row, 2, 1)
row += 1
auto = self.add_checkbox(grid,
_("Enable automatic place title generation"),
row, 'preferences.place-auto',
extra_callback=self.auto_title_changed)
self.auto_title_changed(auto)
row += 1
# Age precision:
# precision=1 for "year", 2: "year, month" or 3: "year, month, days"
obox = Gtk.ComboBoxText()
@ -1151,66 +1187,13 @@ class GrampsPreferences(ConfigureDialog):
row += 1
return _('Display'), grid
def add_places_panel(self, configdialog):
grid = Gtk.Grid()
grid.set_border_width(12)
grid.set_column_spacing(6)
grid.set_row_spacing(6)
auto = self.add_checkbox(grid,
_("Enable automatic place title generation"),
0, 'preferences.place-auto',
extra_callback=self.auto_title_changed)
row = 0
grid2 = Gtk.Grid()
grid2.set_border_width(12)
grid2.set_column_spacing(6)
grid2.set_row_spacing(6)
grid.attach(grid2, 1, 1, 1, 1)
self.place_widgets = []
cbox = self.add_checkbox(grid2, _("Suppress comma after house number"),
row, 'preferences.place-number', start=0)
self.place_widgets.append(cbox)
row += 1
cbox = self.add_checkbox(grid2, _("Reverse display order"),
row, 'preferences.place-reverse', start=0)
self.place_widgets.append(cbox)
row += 1
# Place restriction
obox = Gtk.ComboBoxText()
formats = [_("Full place name"),
_("-> Hamlet/Village/Town/City"),
_("Hamlet/Village/Town/City ->")]
list(map(obox.append_text, formats))
active = config.get('preferences.place-restrict')
obox.set_active(active)
obox.connect('changed', self.place_restrict_changed)
lwidget = BasicLabel(_("%s: ") % _('Restrict'))
grid2.attach(lwidget, 0, row, 1, 1)
grid2.attach(obox, 1, row, 2, 1)
self.place_widgets.append(obox)
row += 1
entry = self.add_entry(grid2, _("Language"),
row, 'preferences.place-lang')
self.place_widgets.append(entry)
row += 1
self.auto_title_changed(auto)
return _('Places'), grid
def auto_title_changed(self, obj):
"""
Update sensitivity of place configuration widgets.
Update sensitivity of place format widget.
"""
active = obj.get_active()
for widget in self.place_widgets:
widget.set_sensitive(active)
active = config.get('preferences.place-auto')
self.pformat.set_sensitive(active)
self.fmt_btn.set_sensitive(active)
def add_text_panel(self, configdialog):
row = 0
@ -1258,6 +1241,23 @@ class GrampsPreferences(ConfigureDialog):
Gdk.RGBA.parse(color, hexval)
widget.set_rgba(color)
def cb_place_fmt_dialog(self, button):
"""
Called to invoke the place format editor.
"""
EditPlaceFormat(self.uistate, self.dbstate, self.track,
self.cb_place_fmt_rebuild)
def cb_place_fmt_rebuild(self):
"""
Called to rebuild the place format list.
"""
model = Gtk.ListStore(str)
for fmt in _pd.get_formats():
model.append([fmt.name])
self.pformat.set_model(model)
self.pformat.set_active(0)
def check_for_type_changed(self, obj):
active = obj.get_active()
if active == 0: # update
@ -1281,10 +1281,6 @@ class GrampsPreferences(ConfigureDialog):
active = obj.get_active()
config.set('behavior.check-for-addon-updates', active)
def place_restrict_changed(self, obj):
active = obj.get_active()
config.set('preferences.place-restrict', active)
def date_format_changed(self, obj):
config.set('preferences.date-format', obj.get_active())
OkDialog(_('Change is not immediate'),

View File

@ -372,6 +372,7 @@ class DisplayState(Callback):
'filters-changed' : (str, ),
'filter-name-changed' : (str, str, str),
'nameformat-changed' : None,
'placeformat-changed' : None,
'grampletbar-close-changed' : None,
'update-available' : (list, ),
'autobackup' : None,

View File

@ -0,0 +1,157 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2017 Nick Hall
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from ..managedwindow import ManagedWindow
from ..glade import Glade
from ..listmodel import ListModel
from gramps.gen.errors import ValidationError
from gramps.gen.display.place import displayer as _pd
from gramps.gen.display.place import PlaceFormat
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# EditPlaceFormat
#
#-------------------------------------------------------------------------
class EditPlaceFormat(ManagedWindow):
def __init__(self, uistate, dbstate, track, callback):
self.title = _('Place Format Editor')
ManagedWindow.__init__(self, uistate, track, EditPlaceFormat)
self.callback = callback
self.top = Glade()
self.set_window(self.top.toplevel, None, self.title, None)
self.setup_configs('interface.editplaceformat', 600, 400)
self.top.get_object('add').connect('clicked', self.__add)
self.top.get_object('remove').connect('clicked', self.__remove)
self.top.get_object('name').connect('changed', self.__name_changed)
self.top.get_object('levels').connect('validate', self._validate)
self.window.connect('response', self.__close)
self.model = None
self.formats = _pd.get_formats()
self.current_format = None
self.__populate_format_list()
self.show()
def build_menu_names(self, obj):
return (self.title, None)
def __populate_format_list(self):
flist = self.top.get_object('format_list')
self.model = ListModel(flist,
[(_('Format'), -1, 100)],
select_func=self.__format_changed)
for fmt in self.formats:
self.model.add([fmt.name])
self.model.select_row(0)
def __format_changed(self, selection):
if self.current_format is not None:
fmt = self.formats[self.current_format]
self.__save_format(fmt)
row = self.model.get_selected_row()
if row != -1:
fmt = self.formats[row]
self.__load_format(fmt)
self.current_format = row
if row == 0:
self.top.get_object('remove').set_sensitive(False)
self.top.get_object('name').set_sensitive(False)
self.top.get_object('levels').set_sensitive(False)
self.top.get_object('street').set_sensitive(False)
self.top.get_object('language').set_sensitive(False)
self.top.get_object('reverse').set_sensitive(False)
else:
self.top.get_object('remove').set_sensitive(True)
self.top.get_object('name').set_sensitive(True)
self.top.get_object('levels').set_sensitive(True)
self.top.get_object('street').set_sensitive(True)
self.top.get_object('language').set_sensitive(True)
self.top.get_object('reverse').set_sensitive(True)
self.top.get_object('levels').validate(force=True)
def __name_changed(self, entry):
store, iter_ = self.model.get_selected()
self.model.set(iter_, [entry.get_text()])
def _validate(self, widget, text):
for level in text.split(','):
parts = level.split(':')
if len(parts) < 1:
return ValidationError('Empty level')
if len(parts) > 2:
return ValidationError('Invalid slice')
for part in parts:
integer_str = part.replace('p', '')
if integer_str != '':
try:
integer = int(integer_str)
except ValueError:
return ValidationError('Invalid format string')
def __load_format(self, fmt):
self.top.get_object('name').set_text(fmt.name)
self.top.get_object('levels').set_text(fmt.levels)
self.top.get_object('street').set_active(fmt.street)
self.top.get_object('language').set_text(fmt.language)
self.top.get_object('reverse').set_active(fmt.reverse)
def __save_format(self, fmt):
fmt.name = self.top.get_object('name').get_text()
fmt.levels = self.top.get_object('levels').get_text()
fmt.street = self.top.get_object('street').get_active()
fmt.language = self.top.get_object('language').get_text()
fmt.reverse = self.top.get_object('reverse').get_active()
def __add(self, button):
name = _('New')
self.formats.append(PlaceFormat(name, ':', '', 0, False))
self.model.add([name])
self.model.select_row(len(self.formats)-1)
def __remove(self, button):
store, iter_ = self.model.get_selected()
if iter_:
self.current_format = None
del self.formats[self.model.get_selected_row()]
self.model.remove(iter_)
if self.model.get_selected_row() == -1:
self.model.select_row(len(self.formats)-1)
def __close(self, *obj):
row = self.model.get_selected_row()
fmt = self.formats[self.current_format]
self.__save_format(fmt)
_pd.save_formats()
self.callback()
self.close()

View File

@ -121,7 +121,7 @@ class PlaceSidebarFilter(SidebarFilter):
self.filter_code.set_text('')
self.filter_enclosed.set_text('')
self.filter_note.set_text('')
self.filter_within.set_value(0, 0)
self.filter_within.set_value('', 0)
self.ptype.get_child().set_text('')
self.tag.set_active(0)
self.generic.set_active(0)
@ -133,7 +133,7 @@ class PlaceSidebarFilter(SidebarFilter):
code = str(self.filter_code.get_text()).strip()
enclosed = str(self.filter_enclosed.get_text()).strip()
note = str(self.filter_note.get_text()).strip()
within = self.filter_within.get_value()
within = self.filter_within.get_value()[0]
regex = self.filter_regex.get_active()
tag = self.tag.get_active() > 0
gen = self.generic.get_active() > 0

View File

@ -0,0 +1,254 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<requires lib="grampswidgets" version="0.0"/>
<object class="GtkDialog" id="editplaceformat">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">_Close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkPaned" id="paned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkTreeView" id="format_list">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="add">
<property name="label" translatable="yes">Add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="remove">
<property name="label" translatable="yes">Remove</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">6</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Levels:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Street format:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Language:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="language">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="reverse">
<property name="label" translatable="yes">Reverse display order</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="hexpand">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="street">
<property name="visible">True</property>
<property name="can_focus">False</property>
<items>
<item translatable="yes">None</item>
<item translatable="yes">Number Street</item>
<item translatable="yes">Street Number</item>
</items>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Name:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="name">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="ValidatableMaskedEntry" id="levels">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-7">button1</action-widget>
</action-widgets>
<child>
<placeholder/>
</child>
</object>
</interface>

View File

@ -55,6 +55,7 @@ from .. import widgets
from ..managedwindow import ManagedWindow
from ..dialog import OptionDialog
from ..selectors import SelectorFactory
from gramps.gen.errors import HandleError
from gramps.gen.display.name import displayer as _nd
from gramps.gen.display.place import displayer as _pd
from gramps.gen.filters import GenericFilterFactory, GenericFilter, rules
@ -653,6 +654,7 @@ class GuiPersonOption(Gtk.Box):
gid = self.__option.get_value()
# Pick up the active person
try:
person_handle = self.__uistate.get_active('Person')
person = self.__dbstate.db.get_person_from_handle(person_handle)
@ -666,6 +668,8 @@ class GuiPersonOption(Gtk.Box):
if not person:
person = self.__db.find_initial_person()
except HandleError:
person = None
self.__update_person(person)

View File

@ -50,6 +50,7 @@ class PersonDetails(Gramplet):
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add(self.gui.WIDGET)
self.uistate.connect('nameformat-changed', self.update)
self.uistate.connect('placeformat-changed', self.update)
def build_gui(self):
"""

View File

@ -157,6 +157,7 @@ class BasePersonView(ListView):
})
uistate.connect('nameformat-changed', self.build_tree)
uistate.connect('placeformat-changed', self.build_tree)
self.additional_uis.append(self.additional_ui())

View File

@ -130,6 +130,9 @@ class PlaceBaseView(ListView):
'<PRIMARY>BackSpace' : self.key_delete,
})
self.maptoolbtn = None
uistate.connect('placeformat-changed', self.build_tree)
self.additional_uis.append(self.additional_ui())
def navigation_type(self):

View File

@ -226,7 +226,7 @@ class Printinfo:
This class must first be initialized with set_class_vars
"""
def __init__(self, doc, database, numbering, showmarriage, showdivorce,
name_display, rlocale, want_ids):
name_display, rlocale, want_ids, pformat):
#classes
self._name_display = name_display
self.doc = doc
@ -238,6 +238,7 @@ class Printinfo:
self.want_ids = want_ids
self._ = rlocale.translation.sgettext # needed for English
self._get_date = rlocale.get_date
self.pformat = pformat
def __date_place(self, event):
""" return the date and/or place an event happened """
@ -245,7 +246,7 @@ class Printinfo:
date = self._get_date(event.get_date_object())
place_handle = event.get_place_handle()
if place_handle:
place = _pd.display_event(self.database, event)
place = _pd.display_event(self.database, event, self.pformat)
return("%(event_abbrev)s %(date)s - %(place)s" % {
'event_abbrev': event.type.get_abbreviation(self._),
'date' : date,
@ -474,9 +475,11 @@ class DescendantReport(Report):
stdoptions.run_name_format_option(self, menu)
pformat = menu.get_option_by_name("place_format").get_value()
self.obj_print = Printinfo(self.doc, self.database, obj, marrs, divs,
self._name_display, self._locale,
self.want_ids)
self.want_ids, pformat)
def write_report(self):
self.doc.start_paragraph("DR-Title")
@ -555,6 +558,8 @@ class DescendantOptions(MenuReportOptions):
stdoptions.add_name_format_option(menu, category_name)
stdoptions.add_place_format_option(menu, category_name)
stdoptions.add_private_data_option(menu, category_name)
stdoptions.add_living_people_option(menu, category_name)

View File

@ -168,6 +168,8 @@ class DetAncestorReport(Report):
stdoptions.run_name_format_option(self, menu)
self._nd = self._name_display
self.place_format = menu.get_option_by_name("place_format").get_value()
self.gen_handles = {}
self.prev_gen_handles = {}
@ -440,7 +442,7 @@ class DetAncestorReport(Report):
else:
date = event.get_date_object().get_year()
place = _pd.display_event(self._db, event)
place = _pd.display_event(self._db, event, self.place_format)
self.doc.start_paragraph('DAR-MoreDetails')
if date and place:
@ -848,6 +850,8 @@ class DetAncestorOptions(MenuReportOptions):
stdoptions.add_name_format_option(menu, category)
stdoptions.add_place_format_option(menu, category)
stdoptions.add_private_data_option(menu, category)
stdoptions.add_living_people_option(menu, category)

View File

@ -201,6 +201,8 @@ class DetDescendantReport(Report):
stdoptions.run_name_format_option(self, menu)
self.place_format = menu.get_option_by_name("place_format").get_value()
self.__narrator = Narrator(self._db, self.verbose,
use_call, use_fulldate,
empty_date, empty_place,
@ -474,7 +476,7 @@ class DetDescendantReport(Report):
else:
date = event.get_date_object().get_year()
place = _pd.display_event(self._db, event)
place = _pd.display_event(self._db, event, self.place_format)
self.doc.start_paragraph('DDR-MoreDetails')
event_name = self._get_type(event.get_type())
@ -1039,6 +1041,8 @@ class DetDescendantOptions(MenuReportOptions):
stdoptions.add_name_format_option(menu, category)
stdoptions.add_place_format_option(menu, category)
stdoptions.add_private_data_option(menu, category)
stdoptions.add_living_people_option(menu, category)

View File

@ -117,13 +117,15 @@ class FamilyGroup(Report):
stdoptions.run_name_format_option(self, menu)
self.place_format = menu.get_option_by_name("place_format").get_value()
def dump_parent_event(self, name, event):
place = ""
date = ""
descr = ""
if event:
date = self._get_date(event.get_date_object())
place = _pd.display_event(self.db, event)
place = _pd.display_event(self.db, event, self.place_format)
if place is None:
place = ''
descr = event.get_description()
@ -438,7 +440,7 @@ class FamilyGroup(Report):
date = self._get_date(event.get_date_object())
place_handle = event.get_place_handle()
if place_handle:
place = _pd.display_event(self.db, event)
place = _pd.display_event(self.db, event, self.place_format)
if place is None:
place = ''
@ -736,6 +738,8 @@ class FamilyGroupOptions(MenuReportOptions):
self.__update_filters()
stdoptions.add_place_format_option(menu, category_name)
stdoptions.add_private_data_option(menu, category_name)
stdoptions.add_living_people_option(menu, category_name)

View File

@ -157,6 +157,8 @@ class IndivCompleteReport(Report):
stdoptions.run_name_format_option(self, menu)
self.place_format = menu.get_option_by_name("place_format").get_value()
self.home_person = self._db.get_default_person() # might be None
self.increlname = menu.get_option_by_name('incl_relname').get_value()
if self.increlname and self.home_person:
@ -183,7 +185,7 @@ class IndivCompleteReport(Report):
place_handle = event.get_place_handle()
if place_handle:
place = self._db.get_place_from_handle(place_handle)
place_name = _pd.display_event(self._db, event)
place_name = _pd.display_event(self._db, event, self.place_format)
place_endnote = self._cite_endnote(place)
# make sure it's translated, so it can be used below, in "combine"
ignore = _('%(str1)s in %(str2)s. ') % {'str1' : '', 'str2' : ''}
@ -518,7 +520,8 @@ class IndivCompleteReport(Report):
place_handle = lds_ord.get_place_handle()
if place_handle:
place = self._db.get_place_from_handle(place_handle)
place_name = _pd.display_event(self._db, lds_ord)
place_name = _pd.display_event(self._db, lds_ord,
self.place_format)
place_endnote = self._cite_endnote(place)
endnotes = self._cite_endnote(lds_ord, prior=place_endnote)
self.doc.start_row()
@ -716,7 +719,8 @@ class IndivCompleteReport(Report):
place_handle = lds_ord.get_place_handle()
if place_handle:
place = self._db.get_place_from_handle(place_handle)
place_name = _pd.display_event(self._db, lds_ord)
place_name = _pd.display_event(self._db, lds_ord,
self.place_format)
place_endnote = self._cite_endnote(place)
endnotes = self._cite_endnote(lds_ord, prior=place_endnote)
self.doc.start_row()
@ -1083,6 +1087,8 @@ class IndivCompleteOptions(MenuReportOptions):
self.__update_filters()
stdoptions.add_place_format_option(menu, category_name)
stdoptions.add_private_data_option(menu, category_name)
stdoptions.add_living_people_option(menu, category_name)

View File

@ -105,6 +105,8 @@ class PlaceReport(Report):
stdoptions.run_name_format_option(self, menu)
self._nd = self._name_display
self.place_format = menu.get_option_by_name("place_format").get_value()
filter_option = menu.get_option_by_name('filter')
self.filter = filter_option.get_filter()
@ -196,7 +198,7 @@ class PlaceReport(Report):
place_names += ' (%s)' % place_name.get_language()
place_details += [self._("places|All Names: %s") % place_names,]
self.doc.start_paragraph("PLC-PlaceTitle")
place_title = _pd.display(self._db, place)
place_title = _pd.display(self._db, place, self.place_format)
self.doc.write_text(("%(nbr)s. %(place)s") % {'nbr' : place_nbr,
'place' : place_title})
self.doc.end_paragraph()
@ -425,7 +427,7 @@ class PlaceOptions(MenuReportOptions):
if subject:
subject += " + "
place = self.__db.get_place_from_gramps_id(place_id)
subject += _pd.display(self.__db, place)
subject += _pd.display(self.__db, place, self.place_format)
return subject
def add_menu_options(self, menu):

View File

@ -108,6 +108,8 @@ class TagReport(Report):
stdoptions.run_name_format_option(self, menu)
self.place_format = menu.get_option_by_name("place_format").get_value()
def write_report(self):
self.doc.start_paragraph("TR-Title")
# feature request 2356: avoid genitive form
@ -439,7 +441,7 @@ class TagReport(Report):
for place_handle in place_list:
place = self.database.get_place_from_handle(place_handle)
place_title = _pd.display(self.database, place)
place_title = _pd.display(self.database, place, self.place_format)
self.doc.start_row()
@ -916,6 +918,8 @@ class TagOptions(MenuReportOptions):
stdoptions.add_name_format_option(menu, category_name)
stdoptions.add_place_format_option(menu, category_name)
stdoptions.add_private_data_option(menu, category_name)
stdoptions.add_living_people_option(menu, category_name)

View File

@ -125,6 +125,7 @@ class EventView(ListView):
})
uistate.connect('nameformat-changed', self.build_tree)
uistate.connect('placeformat-changed', self.build_tree)
self.additional_uis.append(self.additional_ui())

View File

@ -536,6 +536,7 @@ class PedigreeView(NavigationView):
self.dbstate = dbstate
self.dbstate.connect('database-changed', self.change_db)
uistate.connect('nameformat-changed', self.person_rebuild)
uistate.connect('placeformat-changed', self.person_rebuild)
self.format_helper = FormattingHelper(self.dbstate)

View File

@ -144,6 +144,7 @@ class RelationshipView(NavigationView):
dbstate.connect('database-changed', self.change_db)
uistate.connect('nameformat-changed', self.build_tree)
uistate.connect('placeformat-changed', self.build_tree)
self.redrawing = False
self.child = None

View File

@ -1312,9 +1312,8 @@ class BasePage: # pylint: disable=C1001
msg += self._('Last change was the %(date)s') % {'date' :
last_modif}
else:
dat_txt = ' on %(date)s' % {'date' :
self.rlocale.get_date(Today())}
msg += self._(dat_txt)
dat_txt = self._(' on %(date)s')
msg += dat_txt % {'date' : self.rlocale.get_date(Today())}
origin1 = self.report.filter.get_name(self.rlocale)
filt_number = self.report.options['filter']
@ -2578,6 +2577,44 @@ class BasePage: # pylint: disable=C1001
)
tbody += trow
# display all related locations
for placeref in place.get_placeref_list():
place_date = self.rlocale.get_date(placeref.get_date_object())
if place_date != "":
parent_place = self.r_db.get_place_from_handle(placeref.ref)
parent_name = parent_place.get_name().get_value()
trow = Html('tr') + (
Html("td", self._("Locations"), class_="ColumnAttribute",
inline=True),
Html("td", parent_name, class_="ColumnValue", inline=True),
Html("td", place_date, class_="ColumnValue", inline=True)
)
tbody += trow
altloc = place.get_alternative_names()
if altloc:
tbody += Html("tr") + Html("td", "&nbsp;", colspan=2)
trow = Html("tr") + (
Html("th", self._("Alternate Names"), colspan=1,
class_="ColumnAttribute", inline=True),
Html("th", self._("Language"), colspan=1,
class_="ColumnAttribute", inline=True),
Html("th", self._("Date range in which the name is valid."), colspan=1,
class_="ColumnAttribute", inline=True),
)
tbody += trow
for loc in altloc:
place_date = self.rlocale.get_date(loc.date)
trow = Html("tr") + (
Html("td", loc.get_value(), class_="ColumnValue",
inline=True),
Html("td", loc.get_language(), class_="ColumnValue",
inline=True),
Html("td", place_date, class_="ColumnValue",
inline=True),
)
tbody += trow
altloc = place.get_alternate_locations()
if altloc:
tbody += Html("tr") + Html("td", "&nbsp;", colspan=2)
@ -2605,20 +2642,6 @@ class BasePage: # pylint: disable=C1001
tbody += trow
tbody += Html("tr") + Html("td", "&nbsp;", colspan=2)
# display all related locations
for placeref in place.get_placeref_list():
place_date = self.rlocale.get_date(placeref.get_date_object())
if place_date != "":
parent_place = self.r_db.get_place_from_handle(placeref.ref)
parent_name = parent_place.get_name().get_value()
trow = Html('tr') + (
Html("td", self._("Locations"), class_="ColumnAttribute",
inline=True),
Html("td", parent_name, class_="ColumnValue", inline=True),
Html("td", place_date, class_="ColumnValue", inline=True)
)
tbody += trow
# return place table to its callers
return table

View File

@ -158,7 +158,8 @@ class MediaPages(BasePage):
total = len(self.unused_media_handles)
idx = 1
prev = sorted_media_handles[len(sorted_media_handles)-1]
total_m = len(sorted_media_handles)
prev = sorted_media_handles[total_m-1] if total_m > 0 else 0
if total > 0:
for media_handle in self.unused_media_handles:
media = self.r_db.get_media_from_handle(media_handle)

View File

@ -1679,6 +1679,8 @@ class PersonPages(BasePage):
self.report.options['pid'])
if center_person is None:
return
if probably_alive(center_person, self.r_db, Today()):
return
relationship = self.rel_class.get_one_relationship(self.r_db,
self.person,
center_person)

View File

@ -529,6 +529,7 @@ class WebCalReport(Report):
# each year will link to current month.
# this will always need an extension added
month = int(self.today.get_month())
month = month.lower()
full_month_name = self.rlocale.date_displayer.long_months[month]
# Note. We use '/' here because it is a URL, not a OS dependent
@ -589,6 +590,7 @@ class WebCalReport(Report):
# Note. We use '/' here because it is a URL, not a OS
# dependent pathname need to leave home link alone,
# so look for it ...
url_fname = url_fname.lower()
url = url_fname
add_subdirs = False
if not (url.startswith('http:') or url.startswith('/')):
@ -718,20 +720,20 @@ class WebCalReport(Report):
self.end_year = self.start_year
if month > 1:
full_month_name = date_displayer.long_months[month-1]
url = full_month_name + self.ext
url = full_month_name.lower() + self.ext
prevm = Date(int(year), int(month-1), 0)
my_title = Html("a", _escape("<"), href=url,
title=date_displayer.display(prevm))
elif self.multiyear and year > self.start_year:
full_month_name = date_displayer.long_months[12]
url = full_month_name + self.ext
url = full_month_name.lower() + self.ext
dest = os.path.join("../", str(year-1), url)
prevm = Date(int(year-1), 12, 0)
my_title = Html("a", _escape("<"), href=dest,
title=date_displayer.display(prevm))
else:
full_month_name = date_displayer.long_months[12]
url = full_month_name + self.ext
url = full_month_name.lower() + self.ext
dest = os.path.join("../", str(self.end_year), url)
prevy = Date(self.end_year, 12, 0)
my_title = Html("a", _escape("<"), href=dest,
@ -739,20 +741,20 @@ class WebCalReport(Report):
my_title += Html("</a>&nbsp;")
if month < 12:
full_month_name = date_displayer.long_months[month+1]
url = full_month_name + self.ext
url = full_month_name.lower() + self.ext
nextd = Date(int(year), int(month+1), 0)
my_title += Html("a", _escape(">"), href=url,
title=date_displayer.display(nextd))
elif self.multiyear and year < self.end_year:
full_month_name = date_displayer.long_months[1]
url = full_month_name + self.ext
url = full_month_name.lower() + self.ext
dest = os.path.join("../", str(year+1), url)
nextd = Date(int(year+1), 1, 0)
my_title += Html("a", _escape(">"), href=dest,
title=date_displayer.display(nextd))
else:
full_month_name = date_displayer.long_months[1]
url = full_month_name + self.ext
url = full_month_name.lower() + self.ext
dest = os.path.join("../", str(self.start_year), url)
nexty = Date(self.start_year, 1, 0)
my_title += Html("a", _escape(">"), href=dest,
@ -967,6 +969,7 @@ class WebCalReport(Report):
for month in range(1, 13):
cal_fname = self.rlocale.date_displayer.long_months[int(month)]
cal_fname = cal_fname.lower()
open_file = self.create_file(cal_fname, str(year))
# Add xml, doctype, meta and stylesheets
@ -2008,8 +2011,9 @@ def get_day_list(event_date, holiday_list, bday_anniv_list, rlocale=glocale):
if age_at_death is not None:
death_symbol = "&#10014;" # latin cross for html code
mess = trans_text("Died %(death_date)s.") % {
'death_date' : dead_event_date}
trans_date = trans_text("Died %(death_date)s.")
translated_date = rlocale.get_date(dead_event_date)
mess = trans_date % {'death_date' : translated_date}
age = ", <font size='+1' ><b>%s</b></font> <em>%s (%s)" % (
death_symbol, mess, age_at_death)
else:
@ -2017,9 +2021,12 @@ def get_day_list(event_date, holiday_list, bday_anniv_list, rlocale=glocale):
# where "12 years" is already localized to your language
age = ', <em>'
date_y = date.get_year()
age += trans_text('%s old') % str(age_str) if date_y != 0 else \
trans_text("Born %(birth_date)s.") % {
'birth_date' : dead_event_date}
trans_date = trans_text("Born %(birth_date)s.")
old_date = trans_text('%s old')
tranlated_date = rlocale.get_date(dead_event_date)
age += old_date % str(age_str) if date_y != 0 else \
trans_date % {
'birth_date' : translated_date}
txt_str = (text + age + '</em>')
# an anniversary
@ -2035,7 +2042,7 @@ def get_day_list(event_date, holiday_list, bday_anniv_list, rlocale=glocale):
if isinstance(dead_event_date,
Date) and dead_event_date.get_year() > 0:
txt_str += " (" + trans_text("Until") + " "
txt_str += str(dead_event_date)
txt_str += rlocale.get_date(dead_event_date)
txt_str += ")</em>"
else:
txt_str += "</em>"

4
po/POTFILES.in Normal file → Executable file
View File

@ -423,6 +423,7 @@ gramps/gui/editors/editnote.py
gramps/gui/editors/editperson.py
gramps/gui/editors/editpersonref.py
gramps/gui/editors/editplace.py
gramps/gui/editors/editplaceformat.py
gramps/gui/editors/editplacename.py
gramps/gui/editors/editplaceref.py
gramps/gui/editors/editprimary.py
@ -472,6 +473,7 @@ gramps/gui/glade/editnote.glade
gramps/gui/glade/editperson.glade
gramps/gui/glade/editpersonref.glade
gramps/gui/glade/editplace.glade
gramps/gui/glade/editplaceformat.glade
gramps/gui/glade/editplacename.glade
gramps/gui/glade/editplaceref.glade
gramps/gui/glade/editreporef.glade
@ -520,6 +522,7 @@ gramps/gui/plug/quick/_textbufdoc.py
gramps/gui/plug/report/_bookdialog.py
gramps/gui/plug/report/_docreportdialog.py
gramps/gui/plug/report/_fileentry.py
gramps/gui/plug/report/_graphreportdialog.py
gramps/gui/plug/report/_graphvizreportdialog.py
gramps/gui/plug/report/_papermenu.py
gramps/gui/plug/report/_reportdialog.py
@ -591,6 +594,7 @@ gramps/plugins/drawreport/statisticschart.py
gramps/plugins/drawreport/timeline.py
gramps/plugins/export/export.gpr.py
gramps/plugins/export/exportcsv.py
gramps/plugins/export/exportftree.py
gramps/plugins/export/exportgedcom.py
gramps/plugins/export/exportgeneweb.py
gramps/plugins/export/exportpkg.py

View File

@ -493,7 +493,6 @@ gramps/plugins/drawreport/__init__.py
# plugins/export directory
#
gramps/plugins/export/__init__.py
gramps/plugins/export/exportftree.py
#
# plugins/export/test directory
#

9461
po/ca.po

File diff suppressed because it is too large Load Diff