Compare commits

..

91 Commits

Author SHA1 Message Date
romjerome 96e715df2b fix trailing whitespace
https://github.com/gramps-project/gramps/pull/966#issuecomment-569182132
thanks!
2019-12-29 14:59:57 +01:00
romjerome 0120572a7a Wrong continued indentation 2019-12-14 18:48:56 +01:00
romjerome ea58544530 Trailing whitespace 2019-12-14 18:47:46 +01:00
romjerome c36b6c20c1 options for including occupation data 2019-12-10 16:18:01 +01:00
Paulo Henrique Moraes fc9e5c2a4a Updated translation. (#952) 2019-11-27 11:51:50 -06:00
prculley e3eedb2219 Merge branch 'gramps51' 2019-11-08 11:46:40 -06:00
Paul Culley b7487330a7 Fix up Event Editors Place display for bidi text with Gramps ID (#924)
Fixes #10124

Fix up Event Editors Place display for bidi text with Gramps ID (PR 924)

Some versions of Gtk/Pango have trouble with text containing both LTR and RTL characters. The bug notes this shows up in our Event Editor on the 'Place" field, where we have the place displayer title and the Gramps ID concatenated into the same string.

In older versions of Gtk (3.18.9 tested) the bracket around the Gramps ID would get mangled to the beginning of the string:
<images>

In newer versions of Gtk (3.24.3 tested) it was better to start with:
<images>

The older version of Gtk/Pango doesn't seem to properly interpret all of the potential Unicode bidi control characters, so the fix shown is the best I can do. The fixed version of the newer Gtk version is what is desired.

I note that the Place displayer should be fixed up to use more appropriate separators than just commas for RTL text, but that is another issue.
2019-11-05 13:00:48 +11:00
Paul Culley 1025a38caa Fix issues with RTL languages and LAT/LONG (#922)
* Fix display of GPS coordinates in Places view for RTL languages

Issue #11335

* Fix place editor lat/long entry for RTL languages

Fixes #11335
2019-11-05 12:42:09 +11:00
Paul Culley 2054c467db Fix GEDCOM export to avoid translated GrampsType strings (#947)
Fixes #11410

The bug submitter noticed that the GEDCOM export contained translated strings in the MEDI lines of his export. GEDCOM should contain English values for most such cases where 'types' are exported.

I scanned the export code for other potential cases, and found:

* Certain unexpected event types on individuals (Marriage)
* Certain unexpected event types on families (Immigration, Residence, etc.)
* Pedigree types that were not standardized on PEDI,_FREL,_MREL (Sponsored, Unknown)
* Family Attributes other than Number if children (Caste, Description, National etc.)
* Personal Attributes other than Caste, Description, ID, National, number of children, SSN (Occupation etc.)
* The MEDI types of this bug report...
2019-11-05 12:22:26 +11:00
Serge Noiraud 789b72289c Narrativeweb: Referenced regions problems (#946)
When image width > 800, the referenced regions are incorrectly placed

Fixes #11414
2019-11-05 12:06:06 +11:00
Paul Culley 2e1132bec0 Allow Tools with Notbook tabs to expand to fill the window (#944)
Fixes #10762

User "petpil" (Gramps Bugtracker) noted that the Calculate Estimated Dates addon would not expand the size of its window content when the window was stretched. That addon used the ToolManagedWindowBatch which uses a Gtk Notebook to support several tabs. He also submitted a patch which fixes the problem.

The Gtk.Container.add method originally used apparently did not have expand/fill settings to allow the expansion. The Gtk.Box.pack_start used instead does.

I tested this with all the users of ToolManagedWindowBatch and ToolManagedWindow which inherit from ToolManagedWindowBase, and did not see any bad/unexpected side effects. The Calculate Estimated Dates addon was the only one that really could use this, as it was the only one which I spotted using a potentially large widget in the notebook tab.
2019-11-05 11:44:23 +11:00
Fedik 8ccfa43e56 Ukrainian translation update 2019-11-02 16:51:02 +02:00
Fedik 40140859af Ukrainian translation update 2019-11-02 16:05:15 +02:00
Nick Hall e69e6ca338 Limit Age Stats gramplet settings to appropriate values (#936)
* Max ages should be divisible by 5 to avoid out of range
  errors.
* The chart width should be greater than 45 to look right and
  avoid division by zero errors.
2019-10-30 09:35:32 +11:00
Paul Culley fb29a77f83 Fix the Preferences 'Age display precision' value getting lost (#940)
Fixes #11384

It turns out the changes was actually changing the wrong config setting...

I had to look this one up. Using a lambda like this is called a 'closure' by some; what is happening is that the value 'constant' is being evaluated at the time the lambda is called, not when it is assigned. So in this particular bit of code the preference setting was actually changing 'preferences.family-relation-type' (the value of the variable 'constant' set a bit after the lambda definition.

I reverted this particular bit of code, as I think this kind of Python knowledge is pretty obscure (I could have just used a different unique name for the 'constant' variable).
2019-10-30 09:17:06 +11:00
Paul Culley 06cca96ad0 Fix Spanish translation for dates (#943)
Fixes #10836
2019-10-26 10:14:15 +11:00
avma 2c49461529 Hebrew translation-current version 5.12 (#939)
...I've completed all strings (using the recent .POT)...
2019-10-24 10:41:40 +11:00
Paul Culley 73d19851ef Fix Window family tree title for non-ASCII chars on Windows (#932)
Fixes #11390

As it says, if Family Tree name contained non-ASCII characters, the titlebar on Windows would display it wrong. Turned out to be reading of a utf8 file without the 'encoding' set. On Windows this results in using the default encoding which is one of the code pages, NOT utf8.
2019-10-24 10:24:04 +11:00
Paul Culley 16c8e61944 Fix Preferences/Genealogical Symbols when only one font is present (#930)
that passes

If user has only a single font available that passes check for the Genealogical Symbols being all present, the original code crashed. Apparently never tested... #598 

Fixes #11395
2019-10-24 10:07:52 +11:00
niememat 2fbf945309 Fix translation in Finnish 2019-10-21 18:13:08 +03:00
Milo Ivir cf184e72e8 Update Croatian translation 2019-10-20 16:13:08 +01:00
Leonhaeuser 1c27b785f4 update German translation 2019-10-19 16:52:40 +02:00
Zdeněk Hataš da7e4cc763 Update Czech translation 2019-10-18 09:49:43 +02:00
niememat 5d2fd8cbda Fix translation in Finnish 2019-10-18 05:49:49 +03:00
pehlm 005beac33f Update Swedish translation 2019-10-17 12:10:17 +02:00
niememat ae53b401ce Update finnish translation 2019-10-17 13:00:21 +03:00
Paul Culley 79c54aaedc Fix various Entry fields so Undo/Redo works (#920)
Fixes #11380, #11339

In prior versions of Gramps you could use the undo/redo keys to edit items in the text entries. This no longer works.

This is related to the changes to suppress odd characters and leading/trailing spaces. The Gtk.Entry.set_text() call is effectively clearing the undo/redo list at every keystroke or when you leave the field.

In this PR I move the odd characters cleanup into UndoableEntry.do_insert_text instead of MonitoredEntry.

I scanned the users of MonitoredEntry and they all appeared to use Glade files, I scanned the glade files for anyone using just plain Entry (none found), they all appeared to use UndoableEntry or ValidatableMaskedEntry, so this should cover everyone.
2019-10-17 13:15:39 +11:00
Sam Manzi 4360976d73 Update translation template due to pr #918 (#933) 2019-10-17 12:06:38 +11:00
romjerome 5e9d79ac6f Update POTFILES.in/skip for missing translations (#918)
* Update POTFILES.in

* Update POTFILES.skip

* Update POTFILES.in

add missing 'removespaces.glade' reference
2019-10-17 11:42:22 +11:00
Serge Noiraud ee1d9be898 Narrative web: Ancestor's tree Fix display looks weird (#929)
* Narrative web: Ancestor's tree display looks weird

Solves the following:
- Person boxes overlap
- Some person boxes partially visible or hidden

Fixes #11382

* Narrative web: some cleanup in ancestortree.css

* Narrative web : ancestor tree and long names.

* Adapt ancestor tree css file for all themes
2019-10-17 11:17:31 +11:00
romjerome 75b0b66269 Fix tag colors on PedigreeView (#915)
Fixes #11363

* Handle long and short hex format black color

* Fix hex_to_rgb_float utility function
2019-10-17 10:57:36 +11:00
Paul Culley c54f381737 Fix Gramps -v error when Gtk is not present (#923)
Via email a user noted a bug when "Gramps -v" was used with Gtk not installed (and gi was).
When the "gi.require_version('Gtk', '3.0')" was added during Gramps 5.0.0 timeframe, a corresponding exception was not.
2019-10-17 10:23:21 +11:00
Serge Noiraud 2aa6b54de4 NarrativeWeb: dates not localised in place pages (#916)
* NarrativeWeb: dates not localised in place pages

Fixes #11357

* WEBCAL: home link translated to lowercase

Fixes #11358
2019-10-17 10:07:59 +11:00
Baizley 49bad564ae Patch for PedigreeView not reflecting changes to birthday or death (#921)
Fixes #11366

* Make PedigreeView listen on event update signals.

The PedigreeView was not listening for updates on events, so changes to a birthday or death would not be reflected in the view.

* Remove comment about signal side-effects.
2019-10-17 09:23:02 +11:00
Paul Culley 03ab64c4d5 Fix improper escaping in odt output for TOC/Bookmark etc. (#928)
Fixes #11378

For the index, toc, bookmark etc. normal XML escape is correct, the original code also added sub-tags for line break and tab which was NOT correct.
2019-10-17 09:03:29 +11:00
Paul Culley f7bd062bdb Fix CLI parser to accept negative integers as valid (#927)
Fixes #11381
2019-10-17 08:47:55 +11:00
Paul Culley c312c96987 Fix Descendant Tree report for HandleError when no parents on family (#925)
Fixes #11365
2019-10-17 08:33:39 +11:00
niememat 6b2066c797 Fix translation in Finnish 2019-10-10 07:26:04 +03:00
Nick Hall 5d15ccb2a2 Merge pull request #910 from prculley:reorder 2019-10-08 18:44:43 +01:00
prculley 0095a07f12 Fix Reorder ID tool to avoid scrambling the order IDs are assigned
Fixes #10641
2019-10-08 18:43:42 +01:00
prculley bb5b03dd78 Fix Reorder ID tool so subsequent db additions used next possible ID
Fixes #11346
2019-10-08 18:43:42 +01:00
niememat 26351c18c9 Fix translation in Finnish 2019-10-08 12:43:03 +03:00
Nick Hall f5861169fe Merge pull request #908 from SNoiraud:FR11336
New narrative web and web calendar features:

* Allow urls in the user's css files
* Allow alternate stylesheets in pages for narrative web and webcal
* Webcal: incorrect results when divorce event.
* Some pylint improvements

Resolves #11336.
2019-10-05 18:10:45 +01:00
SNoiraud 4e2f98da02 Better score for pylint 2019-10-05 18:05:21 +01:00
SNoiraud 95a0216287 Duplicate marriage 2019-10-05 18:05:21 +01:00
SNoiraud 03fb2ff1c2 Incorrect results when divorce event 2019-10-05 18:05:15 +01:00
SNoiraud 17141a0536 Add alternate stylesheets 2019-10-05 18:03:03 +01:00
SNoiraud 528852b9b3 Allow alternate stylesheets in pages
Useful when you create a site web, you don't need to create a new
web when you are testing the stylesheets. The final user can change
the stylesheet for the current page.

i.e. on Firefox: View -> Page style -> The stylesheet
2019-10-05 18:02:51 +01:00
SNoiraud 0de286e7a8 Allow urls for images in user css files 2019-10-05 17:59:17 +01:00
SNoiraud 7979bf79fd Better code quality for within area rule 2019-10-05 17:28:21 +01:00
Nick Hall 7100c51a31 Merge pull request #903 from prculley:deprecations 2019-10-05 17:22:19 +01:00
prculley 57f7502105 Fix deprecation of Gtk positional arguments 2019-10-05 17:17:54 +01:00
prculley 0f925a86f5 Fix Gtk deprecation Menu.set_title 2019-10-05 17:17:54 +01:00
prculley 17f4d93363 Fix Gtk deprecatioon ScrolledWindow.add_with_viewport 2019-10-05 17:17:54 +01:00
prculley cea48b618f Fix GObject.PARAM_READWRITE deprecation 2019-10-05 17:17:54 +01:00
prculley 290d6f7287 Fix deprecation GObject.GError -> GLib.GError 2019-10-05 17:17:54 +01:00
prculley 4d0e86a2e8 Fix Gtk deprecation Widget.reparent 2019-10-05 17:17:54 +01:00
prculley 831c7f9c66 Fix Gtk deprecation Widget.set_padding 2019-10-05 17:17:54 +01:00
prculley 702e51dd47 Fix deprecation on Gtk.Widget.override_font and modify_font 2019-10-05 17:17:54 +01:00
Jonas Hahnfeld f3555d0168 Add new graph output format to the tree document generator
The "graph" is the data part for genealogytree without the boilerplate
code around it that makes up a full LaTeX file. This format is useful
for people who have their own (more sophisticated) LaTeX file with
custom styles and so on.
The implementation is pretty straight-forward: Just don't output the
LaTeX code.
2019-10-05 17:05:38 +01:00
niememat ecd6da40dd Fix translation in Finnish 2019-10-05 12:30:46 +03:00
Matthias Kemmer bedc4b8e74 Add a new person filter rule 'HasAddressText' 2019-10-04 21:07:52 +01:00
Matthias Kemmer 8a8a21f85d Add date format option for 'numeric date with leading zeros' 2019-10-04 19:59:54 +01:00
Nick Hall c7350c53e2 Remove irrelevant comment 2019-10-04 19:54:00 +01:00
Fredrik Lindseth 52e76b506a Add descriptions to decendant tree report styles 2019-10-04 19:18:16 +01:00
Matthias Kemmer ab52d0988e Remove tag from selected rows 2019-10-03 21:28:33 +01:00
Matthias Kemmer 5935a315b2 Add 'HasAttribute' filter rule to repositories, sources and citations
Fixes #9845
2019-10-03 21:05:14 +01:00
SNoiraud 793b13be67 Narrativeweb: Mainz problem with short text in one note
Issue occurs on the homepage and introduction page.

Fixes #11349
2019-10-03 20:33:17 +01:00
Nick Hall 48dfca57e2 Merge pull request #913 from prculley:bug11316 2019-10-03 19:58:49 +01:00
prculley a07aae2e30 Fix export tests to actually test most files, and run for both dbs 2019-10-03 19:56:27 +01:00
prculley 8f5daac4a7 Fix exports to have consistent results 2019-10-03 19:56:27 +01:00
prculley 0cd6394b72 Upgrade export VCalendar to v2.0, so can export utf8
Fixes #11316
2019-10-03 19:56:27 +01:00
SNoiraud 57d8dcd574 WEBCAL: Wrong web calendar title on home page
Fixes #11354

This PR solves the possibility to have ">", "<" in the title
2019-10-03 19:50:04 +01:00
prculley d5bb4da5a1 Fix Preferences so <ctrl>PageUp/PageDn doesn't stick on Dates tab
Fixes #11351
2019-10-03 19:41:05 +01:00
ailintom 5c44d925e1 Escape for name, dates and places in graph reports
Currently dates and places contain XML special characters (example: birth date
= "1867 <?>"), the item is rendered incorrectly in the report, when images are
included. Escaping special characters with html.escape solves the problem.

Also fixes the & sign in the name, which earlier caused the report to fail.
2019-10-03 19:08:57 +01:00
Paul Culley c7e2e09b42 Fix 'Go' menu direct object selection, goes to wrong place (#907)
Fixes #11341

Fixes up the scrambled 'Go' menu, got messed up in the UIManager upgrade.
2019-09-25 11:39:58 +10:00
Zdeněk Hataš 669e4af0b7 Update Czech translation 2019-09-20 13:17:28 +02:00
pehlm 88f7a701a3 Swedish translation, some changes 2019-09-18 12:37:07 +02:00
RossGammon 52c087154f [Debian ( .deb file)]Release511 updates (#909)
* Add python3-fontconfig to recommends

* Finalise Debian changelog for 5.1.1-1 release
2019-09-18 11:41:30 +10:00
prculley 1eaa609058 Get BetaWarning correct for master 2019-09-16 11:13:08 -05:00
prculley 5f0c2c1c54 Set Beta warning to True 2019-09-16 11:02:03 -05:00
prculley 6d39920e6f Merge branch 'gramps51' 2019-09-16 10:54:55 -05:00
John Ralls 2b62729f52 Release Gramps 5.1.1 on MacOS. 2019-09-14 16:58:34 -07:00
John Ralls 1c856bb93b Assorted fixes for building Gramps 5.0. 2019-09-14 16:56:23 -07:00
Nick Hall 710e40425f Bump to 5.1.2 2019-09-14 23:40:42 +01:00
prculley 4859c14aaa Fix typo in merge 2019-08-12 16:58:55 -05:00
prculley f4a8f21032 Merge from gramps51 2019-08-09 09:06:42 -05:00
prculley e894c4478f Some pylint cleanups 2019-08-09 08:55:05 -05:00
romjerome 56afb5bca9 Add missing 'get_number_of_citations' method (#859)
* Add missing 'get_number_of_citations' method

* update db test for bsddb

* fix trailing whitespace

* typo
2019-08-07 13:47:09 -05:00
SNoiraud 9da8f705f6 Narrative web: Add popup to manage markers
If you click on a marker in the family map page, you get a popup.
In this popup associated with a place, if you have several events,
for each event you see the person and the event type.
If you click on the person, you go to the related page for this person.
If you click on the event type, you go to the related page for this event.

Fixes #11150
2019-07-07 19:25:42 +02:00
SNoiraud ce4cd33139 Narrative web: Add Stamen map
Fixes #05984
2019-07-07 19:24:44 +02:00
140 changed files with 18772 additions and 29124 deletions
+1 -2
View File
@@ -473,11 +473,10 @@ table.eventlist tbody tr td.ColumnSources {
margin: 0px auto;
display: block;
border: solid 1px #999;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+1 -2
View File
@@ -838,11 +838,10 @@ div#EventDetail table.eventlist tbody tr td.ColumnDate {
}
#GalleryDisplay img {
margin: 0 auto;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+1 -2
View File
@@ -524,11 +524,10 @@ table.eventlist tbody tr td.ColumnSources {
margin: 0px auto;
display: block;
border: solid 1px #7C8F7C;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+2 -2
View File
@@ -512,15 +512,15 @@ table.eventlist tbody tr td.ColumnSources {
margin: 0px auto;
display: block;
border: solid 1px #669;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
}
#GalleryDetail h3 {
text-align: center;
}
+1 -2
View File
@@ -512,11 +512,10 @@ table.eventlist tbody tr td.ColumnSources {
margin: 0px auto;
display: block;
border: solid 1px #EA8414;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+1 -2
View File
@@ -513,11 +513,10 @@ table.eventlist tbody tr td.ColumnSources {
margin: 0px auto;
display: block;
border: solid 1px #7CA3DD;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+2 -2
View File
@@ -82,6 +82,7 @@ body > div {
}
.content {
padding: 1.5em 1.5em;
overflow: auto;
background: url(../images/Web_Mainz_Mid.png) #FFF2C6 repeat;
}
#ThumbnailPreview div.snapshot {
@@ -467,11 +468,10 @@ table.eventlist tbody tr td.ColumnSources {
margin: 0px auto;
display:block;
border: solid 1px #7D5925;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+1 -2
View File
@@ -747,11 +747,10 @@ table.eventlist tbody tr td.ColumnSources {
}
#GalleryDisplay img {
margin:0 auto;
max-width: 800px;
height: auto;
}
@media only screen and (max-width: 1080px) {
@media only screen and (max-width: 1600px) {
#GalleryDisplay img {
max-width: 100%;
}
+66 -41
View File
@@ -9,7 +9,7 @@
# 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,
# 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.
@@ -20,10 +20,10 @@
#
# $Id: $
#
**************************************************************************************************
*******************************************************************************
GRAMPS Cascading Style Sheet
Style Name: Combined Ancestor Tree Style Sheet
***************************************************************************************************
*******************************************************************************
#
===== Ancestor Graph Color Scheme =====
Males #BCEAF6
@@ -33,10 +33,8 @@ Unknown #000
===== Web Graphics =====
Males Web_Gender_Male.png
Females Web_Gender_Female.png
# ------------------------------------------------------------------------------------------------- */
/* Subsections : Ancestors Tree
----------------------------------------------------- */
# -------------------------------------------------------------------------- #
/* Subsections : Ancestors Tree -------------------------------------------- */
#tree {
page-break-before:always;
margin:0;
@@ -52,8 +50,8 @@ Females Web_Gender_Female.png
}
#treeContainer div.boxbg {
position:absolute;
margin:0;
padding:0;
margin:0px;
padding:0px;
background:none;
}
#treeContainer div.boxbg a,
@@ -61,41 +59,43 @@ Females Web_Gender_Female.png
position:relative;
z-index:10;
display:block;
font:normal .7em/1.4em sans-serif;
font:normal 1.1em/1.4em sans-serif;
text-align:center;
word-break:break-word;
word-wrap:break-word;
text-decoration:none;
color: #00029D;
width:118px;
padding:5px 20px 7px 20px;
width:280px;
min-height: 70px;
margin-left:16px;
background-color: #FFF;
border: solid 1px #000;
border: solid 2px #000;
border-radius: 10px;
}
#treeContainer div.boxbg a.noThumb,
#treeContainer div.AncCol3 a,
#treeContainer div.AncCol4 a,
#treeContainer div.AncCol3 span.unlinked,
#treeContainer div.AncCol4 a,
#treeContainer div.AncCol4 span.unlinked {
margin-top:10px;
float: right;
}
#treeContainer div.boxbg a:hover {
position:relative;
z-index:999;
font-size:1em;
font-size:1.3em;
word-break:break-word;
word-wrap:break-word;
text-decoration:none;
color: #00029D;
width:190px;
width:400px;
margin-left:-20px;
padding:10px 25px 12px 25px;
border: solid 2px #000;
padding: 0px 0px 0px 40px;
}
#treeContainer div.boxbg a:hover,
#treeContainer div.AncCol3 a:hover,
#treeContainer div.boxbg a:hover,
#treeContainer div.AncCol4 a:hover {
margin-top:-44px;
}
#treeContainer div.boxbg a.noThumb:hover {
margin-top:0;
padding-left: 10px;
}
#treeContainer div.AncCol0 a:hover {
margin-left:12px;
@@ -105,48 +105,73 @@ Females Web_Gender_Female.png
}
#treeContainer div.boxbg span.thumbnail {
display:block;
max-width:80px;
max-height:65px;
margin:0 auto;
padding:4px 0;
position: absolute;
max-width:85px;
max-height:75px;
left: 3px;
top: 3px;
}
#treeContainer div.boxbg span.thumbnail img {
max-width:80px;
max-height:65px;
margin:0 auto;
#treeContainer div.boxbg a.thumbnail table td.img {
padding-right: 5px;
}
#treeContainer div.boxbg a:hover span.thumbnail, #treeContainer div.boxbg a:hover span.thumbnail img {
height:80px;
#treeContainer div.boxbg a.thumbnail:hover table td.img {
padding-right: 9px;
}
#treeContainer div.AncCol3 span.thumbnail, #treeContainer div.AncCol4 span.thumbnail {
#treeContainer div.boxbg a.thumbnail table td.name {
padding-top:3px;
padding-left: 2px;
padding-right: 23px;
width: 90%;
}
#treeContainer div.boxbg a.thumbnail img {
margin-left:0px;
padding-left: 0px;
border-radius: 5px;
}
#treeContainer div.boxbg a.thumbnail:hover img {
max-height:90%;
margin-left:5px;
position: absolute;
left: 0px;
top: 4px;
border-radius: 5px;
}
#treeContainer div.boxbg table td:first-child, table th:first-child {
padding-left: 5px;
padding-top: 5px;
}
#IndividualDetail div.subsection table tr td:first-child {
padding-left: 5px;
padding-top: 5px;
}
#treeContainer #treeContainer div.AncCol4 span.thumbnail {
display:none;
}
#treeContainer div.boxbg a:hover span.thumbnail {
display:block;
}
#treeContainer div.boxbg span.fullname {
display: none;
}
#treeContainer div.boxbg span.shortname {
display: inline;
}
#treeContainer div.boxbg a:hover span.fullname {
display: inline;
}
#treeContainer div.boxbg a:hover span.shortname {
display: none;
}
#treeContainer div.boxbg a:hover {
float: right;
margin-top: 10px;
border: solid 4px #000;
}
#treeContainer div.male a,
#treeContainer div.male span.unlinked {
background:url(../images/Web_Gender_Male.png) #BCEAF6 no-repeat top right;
}
#treeContainer div.female a,
#treeContainer div.female a,
#treeContainer div.female span.unlinked {
background:url(../images/Web_Gender_Female.png) #FFC0CB no-repeat top right;
}
+45
View File
@@ -66,3 +66,48 @@ div#FamilyMapDetail div#references table.infolist {
div#FamilyMapDetail div#references table.infolist tbody tr td.ColumnPlace {
width: 40%;
}
/* Subsection: popup
------------------------------------------------------ */
.ol-popup {
position: absolute;
background-color: white;
-webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
padding: 15px;
border-radius: 10px;
border: 2px solid #111111;
bottom: 12px;
left: -50px;
min-width: 450px;
}
.ol-popup:after, .ol-popup:before {
top: 100%;
border: solid transparent;
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after {
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-closer {
text-decoration: none;
position: absolute;
top: 2px;
right: 8px;
}
.ol-popup-closer:after {
content: "✖";
}
+14 -3
View File
@@ -9,6 +9,12 @@ beg
- h Hans_Peter.8 17/4/1904 #bp Rønne,_Bornholm,_Denmark 29/1/1977 #dp San_Francisco,_San_Francisco_Co.,_CA
end
notes Hansdotter Anna.1
beg
******************************************************************890123456789
******************************************************************89 123456789
end notes
notes Smith Hjalmar.5
beg
BIOGRAPHY
@@ -61,7 +67,7 @@ Some Bold Unicode Characters: &#2294;&#508;&#1024;&#1580;&#12228;&#13405;&#15691
Some Italic Unicode Characters: &#2294;&#508;&#1024;&#1580;&#12228;&#13405;&#15691;&#22299;&#22665;&#24181;&#32863;&#32870;&#65865;&#128694;&#128712;
end notes
fam Smith Gus.6 +~1920 Michaels Evelyn.25 ~1897
fam Smith Gus.6 +~1920 Michaels Evelyn.25 ~1897 0
fam Smith Hjalmar.5 +31/10/1927 #mp Reno,_Washoe_Co.,_NV Ohman Marjorie.26 3/6/1903 #bp Denver,_Denver_Co.,_CO,_Denver_Co.,_Colorado,_USA 22/6/1980 #dp Reno,_Washoe_Co.,_NV
beg
@@ -98,13 +104,18 @@ beg
- h Martin.17 1794..1796 #bp Tommarp,_Kristianstad_Län,_Sweden #dp Sweden
end
fam Willard Edwin.42 ~1886 +~1910 Smith Kirsti_Marie.2
fam Willard Edwin.42 ~1886 0 +~1910 Smith Kirsti_Marie.2
fam Smith Magnes.38 +24/8/1884 #mp Rønne,_Bornholm,_Denmark Streiffert Anna.43 23/9/1860 #bp Hoya/Jona/Hoia,_Sweden 2/2/1927 #dp Rønne,_Bornholm,_Denmark
fam Tester The.14 + Tester Mrs.44 0
beg
- h Tom.45 0
- h Tom.45 Von_Tester_y_tested 0
- Fake.46 von_Person 1954 #bp Fremont,_Alameda_Co.,_CA
- f Mary.47 0
- f Martha.48 0
- h John.49 0
- h Mark.50 0
end
notes Tester Mrs.44
+315 -655
View File
File diff suppressed because it is too large Load Diff
+52 -47
View File
@@ -1,47 +1,52 @@
Anna Hansdotter;;;;;2/10/1864-29/9/1945
Keith Lloyd Smith;Lloyd Smith;Janis Green;;;11/8/1966
Hans Peter Smith;Gustaf Smith;Anna Hansdotter;;;17/4/1904-29/1/1977
Hanna Smith;Martin Smith0;Elna Jefferson;;;29/1/1821
Herman Julius Nielsen;;;;;31/8/1889-1945
Evelyn Michaels;;;;;1897
Marjorie Lee Smith;Hjalmar Smith0;Marjorie Ohman;;;4/11/1934
Gus Smith;Gustaf Smith;Anna Hansdotter;;;11/9/1897-21/10/1963
Jennifer Anderson;;;;;5/11/1907-29/5/1985
Lillie Harriet Jones;;;;;2/5/1910-26/6/1990
John Hjalmar Smith;Hjalmar Smith0;Marjorie Ohman;;;30/1/1932
Eric Lloyd Smith;Lloyd Smith;Janis Green;;;28/8/1963
Amber Marie Smith;Edwin Smith;Janice Adams;;;12/4/1998
Carl Emil Smith;Gustaf Smith;Anna Hansdotter;;;20/12/1899-28/1/1959
Hjalmar Smith;Gustaf Smith;Anna Hansdotter;;;31/1/1893-25/9/1894
Martin Smith;Martin Smith0;Elna Jefferson;;;19/11/1830-1899
Astrid Shermanna Augusta Smith;Gustaf Smith;Anna Hansdotter;;;31/1/1889-21/12/1963
Gustaf Smith, Sr.;Martin Smith;Kerstina Hansdotter;;;28/11/1862-23/7/1930
Marta Ericsdotter;;;;;1775
Kirsti Marie Smith;Gustaf Smith;Anna Hansdotter;;;15/12/1886-18/7/1966
Ingeman Smith;;;;;1770
Anna Streiffert;;;;;23/9/1860-2/2/1927
Craig Peter Smith;Lloyd Smith;Janis Green;;;1966
Magnes Smith;Martin Smith;Kerstina Hansdotter;;;6/10/1858-20/2/1910
Janice Ann Adams;;;;;26/8/1965
Marjorie Ohman;;;;;3/6/1903-22/6/1980
Darcy Horne;;;;;2/7/1966
Alice Paula Perkins;;;;;22/11/1933
Lars Peter Smith;Eric Smith;Darcy Horne;;;16/9/1991
Ingeman Smith0;Martin Smith0;Elna Jefferson;;;29/1/1826
Lloyd Smith;Hans Smith;Lillie Jones;;;13/3/1935
Elna Jefferson;;;;;14/9/1800-
Edwin Michael Smith;John Smith;Alice Perkins;;;24/5/1961
Kerstina Hansdotter;;;;;29/11/1832-1908
Martin Smith0;Ingeman Smith;Marta Ericsdotter;;;1794-
Marjorie Alice Smith0;John Smith;Alice Perkins;;;5/2/1960
Janis Elaine Green;;;;;2/12/1935
Mason Michael Smith;Edwin Smith;Janice Adams;;;26/6/1996
Edwin Willard;;;;;1886
Ingar Smith;Martin Smith0;Elna Jefferson;;;1823
Hjalmar Smith0;Gustaf Smith;Anna Hansdotter;;;7/4/1895-26/6/1975
Emil Smith;Martin Smith;Kerstina Hansdotter;;;27/9/1860
雪 Ke 柯;Herman Nielsen;Astrid Smith;;;
The Tester;Lloyd Smith;Janis Green;;;29/12/1954
Mrs Tester;;;;;
ピーター リチミシキスイミ;;;;;
Tom Tester;The Tester;Mrs Tester;;;
Anna Hansdotter;;;;;2/10/1864-29/9/1945
Keith Lloyd Smith;Lloyd Smith;Janis Green;;;11/8/1966
Hans Peter Smith;Gustaf Smith;Anna Hansdotter;;;17/4/1904-29/1/1977
Hanna Smith;Martin Smith0;Elna Jefferson;;;29/1/1821
Herman Julius Nielsen;;;;;31/8/1889-1945
Evelyn Michaels;;;;;1897
Marjorie Lee Smith;Hjalmar Smith0;Marjorie Ohman;;;4/11/1934
Gus Smith;Gustaf Smith;Anna Hansdotter;;;11/9/1897-21/10/1963
Jennifer Anderson;;;;;5/11/1907-29/5/1985
Lillie Harriet Jones;;;;;2/5/1910-26/6/1990
John Hjalmar Smith;Hjalmar Smith0;Marjorie Ohman;;;30/1/1932
Eric Lloyd Smith;Lloyd Smith;Janis Green;;;28/8/1963
Amber Marie Smith;Edwin Smith;Janice Adams;;;12/4/1998
Carl Emil Smith;Gustaf Smith;Anna Hansdotter;;;20/12/1899-28/1/1959
Hjalmar Smith;Gustaf Smith;Anna Hansdotter;;;31/1/1893-25/9/1894
Martin Smith;Martin Smith0;Elna Jefferson;;;19/11/1830-1899
Astrid Shermanna Augusta Smith;Gustaf Smith;Anna Hansdotter;;;31/1/1889-21/12/1963
Gustaf Smith, Sr.;Martin Smith;Kerstina Hansdotter;;;28/11/1862-23/7/1930
Marta Ericsdotter;;;;;1775
Kirsti Marie Smith;Gustaf Smith;Anna Hansdotter;;;15/12/1886-18/7/1966
Ingeman Smith;;;;;1770
Anna Streiffert;;;;;23/9/1860-2/2/1927
Craig Peter Smith;Lloyd Smith;Janis Green;;;1966
Magnes Smith;Martin Smith;Kerstina Hansdotter;;;6/10/1858-20/2/1910
Janice Ann Adams;;;;;26/8/1965
Marjorie Ohman;;;;;3/6/1903-22/6/1980
Darcy Horne;;;;;2/7/1966
Lloyd Smith;Hans Smith;Lillie Jones;;;13/3/1935
Alice Paula Perkins;;;;;22/11/1933
Lars Peter Smith;Eric Smith;Darcy Horne;;;16/9/1991
Elna Jefferson;;;;;14/9/1800-
Edwin Michael Smith;John Smith;Alice Perkins;;;24/5/1961
Kerstina Hansdotter;;;;;29/11/1832-1908
Martin Smith0;Ingeman Smith;Marta Ericsdotter;;;1794-
Ingeman Smith0;Martin Smith0;Elna Jefferson;;;29/1/1826
Marjorie Alice Smith0;John Smith;Alice Perkins;;;5/2/1960
Janis Elaine Green;;;;;2/12/1935
Mason Michael Smith;Edwin Smith;Janice Adams;;;26/6/1996
Edwin Willard;;;;;1886
Ingar Smith;Martin Smith0;Elna Jefferson;;;1823
Hjalmar Smith0;Gustaf Smith;Anna Hansdotter;;;7/4/1895-26/6/1975
Emil Smith;Martin Smith;Kerstina Hansdotter;;;27/9/1860
雪 Ke 柯;Herman Nielsen;Astrid Smith;;;
ピーター リチミシキスイミ;;;;;
The Tester;Lloyd Smith;Janis Green;;;29/12/1954
Mrs Tester;;;;;
Tom Von Tester y tested;The Tester;Mrs Tester;;;
Fake von Person, I;The Tester;Mrs Tester;;;1954-
Mary Tester;The Tester;Mrs Tester;;;
Martha Tester;The Tester;Mrs Tester;;;
John Tester;The Tester;Mrs Tester;;;
Mark Tester;The Tester;Mrs Tester;;;
+50 -51
View File
@@ -30,66 +30,65 @@
[P0014],"Denver, Denver Co., CO","Denver, Denver Co., CO",City,39.7392,104.9903 W,,[P0024],
Person,Surname,Given,Call,Suffix,Prefix,Title,Gender,Birth date,Birth place,Birth source,Baptism date,Baptism place,Baptism source,Death date,Death place,Death source,Burial date,Burial place,Burial source,Note
[I0030],Adams,Janice Ann,,,,,female,26 Aug 1965,"Fremont, Alameda Co., CA",,,,,,,,,,,
[I0016],Anderson,Jennifer,,,,,female,5 Nov 1907,"Rønne, Bornholm, Denmark",,,,,29 May 1985,"San Francisco, San Francisco Co., CA",,,,,
[I0025],Ericsdotter,Marta,,,,,female,about 1775,Sweden,,,,,,,,,,,
[I0041],Green,Janis Elaine,,,,,female,2 Dec 1935,,,,,,,,,,,,
[I0000],Hansdotter,Anna,,,,,female,2 Oct 1864,"Löderup, Malmöhus Län, Sweden",,,,,29 Sep 1945,"Sparks, Washoe Co., NV",,,,,
[I0038],Hansdotter,Kerstina,,,,,female,29 Nov 1832,"Smestorp, Kristianstad Län, Sweden",,,,,before 1908,Sweden,,,,,
[I0032],Horne,Darcy,,,,,female,2 Jul 1966,"Sacramento, Sacramento Co., CA",,,,,,,,,,,
[I0036],Jefferson,Elna,,,,,female,14 Sep 1800,"Gladsax, Kristianstad Län, Sweden",,,,,,Sweden,,,,,
[I0017],Jones,Lillie Harriet,,,,,female,2 May 1910,"Rønne, Bornholm, Denmark",,,,,26 Jun 1990,,,,,,
[I0030],Adams,Janice Ann,,,,,female,1965-08-26,[P0013],,,,,,,,,,,
[I0016],Anderson,Jennifer,,,,,female,1907-11-05,[P0003],,,,,1985-05-29,[P0002],,,,,
[I0025],Ericsdotter,Marta,,,,,female,about 1775,[P0008],,,,,,,,,,,
[I0041],Green,Janis Elaine,,,,,female,1935-12-02,,,,,,,,,,,,
[I0000],Hansdotter,Anna,,,,,female,1864-10-02,[P0000],,,,,1945-09-29,[P0001],,,,,
[I0038],Hansdotter,Kerstina,,,,,female,1832-11-29,[P0019],,,,,before 1908,[P0008],,,,,
[I0032],Horne,Darcy,,,,,female,1966-07-02,[P0015],,,,,,,,,,,
[I0036],Jefferson,Elna,,,,,female,1800-09-14,[P0004],,,,,,[P0008],,,,,
[I0017],Jones,Lillie Harriet,,,,,female,1910-05-02,[P0003],,,,,1990-06-26,,,,,,
[I0042],Ke 柯,,,,,,male,,,,,,,,,,,,,
[I0013],Michaels,Evelyn,,,,,female,about 1897,,,,,,,,,,,,
[I0012],Nielsen,Herman Julius,,,,,male,31 Aug 1889,"Rønne, Bornholm, Denmark",,,,,1945,,,,,,
[I0031],Ohman,Marjorie,,,,,female,3 Jun 1903,"Denver, Denver Co., CO, Denver Co., Colorado, USA",,,,,22 Jun 1980,"Reno, Washoe Co., NV",,,,,
[I0034],Perkins,Alice Paula,,,,,female,22 Nov 1933,"Sparks, Washoe Co., NV",,,,,,,,,,,
[I0002],Smith,Amber Marie,,,,,female,12 Apr 1998,"Hayward, Alameda Co., CA",,,,,,,,,,,
[I0023],Smith,Astrid Shermanna Augusta,,,,,female,31 Jan 1889,"Rønne, Bornholm, Denmark",,,,,21 Dec 1963,"San Francisco, San Francisco Co., CA",,,,,
[I0020],Smith,Carl Emil,,,,,male,20 Dec 1899,"Rønne, Bornholm, Denmark",,,,,28 Jan 1959,"Reno, Washoe Co., NV",,,,,
[I0029],Smith,Craig Peter,,,,,male,after 1966,"San Francisco, San Francisco Co., CA",,,,,,,,,,,
[I0037],Smith,Edwin Michael,,,,,male,24 May 1961,"San Jose, Santa Clara Co., CA","Birth, Death and Marriage Records",,,,,,,,,,
[I0009],Smith,Emil,,,,,male,27 Sep 1860,"Simrishamn, Kristianstad Län, Sweden",,,,,,,,,,,
[I0019],Smith,Eric Lloyd,,,,Dr.,male,28 Aug 1963,"San Francisco, San Francisco Co., CA",,,,,,,,,,,
[I0015],Smith,Gus,,,,,male,11 Sep 1897,"Rønne, Bornholm, Denmark",,,,,21 Oct 1963,"San Francisco, San Francisco Co., CA",,,,,
[I0024],Smith,Gustaf,,Sr.,,,male,28 Nov 1862,"Grostorp, Kristianstad Län, Sweden",,,,,before 23 Jul 1930,"Sparks, Washoe Co., NV",,,,,
[I0011],Smith,Hanna,,,,,female,29 Jan 1821,"Gladsax, Kristianstad Län, Sweden",,,,,,,,,,,
[I0010],Smith,Hans Peter,,,,,male,17 Apr 1904,"Rønne, Bornholm, Denmark",Birth Records,,,,29 Jan 1977,"San Francisco, San Francisco Co., CA",,5 Feb 1977,"San Francisco, San Francisco Co., CA",findagrave.com,
[I0021],Smith,Hjalmar,,,,,male,31 Jan 1893,"Rønne, Bornholm, Denmark",,,,,25 Sep 1894,"Rønne, Bornholm, Denmark",,,,,
[I0008],Smith,Hjalmar,,,,,male,7 Apr 1895,"Rønne, Bornholm, Denmark",,3 Jun 1895,"Rønne Bornholm, Denmark",,26 Jun 1975,"Reno, Washoe Co., NV",,,,,
[I0007],Smith,Ingar,,,,,female,after 1823,"Gladsax, Kristianstad Län, Sweden",,,,,,,,,,,
[I0027],Smith,Ingeman,,,,,male,about 1770,Sweden,,,,,,,,,,,
[I0004],Smith,Ingeman,,,,,male,29 Jan 1826,"Gladsax, Kristianstad Län, Sweden",,,,,,,,,,,
[I0018],Smith,John Hjalmar,,,,,male,30 Jan 1932,"San Francisco, San Francisco Co., CA",,,,,,,,,,,
[I0001],Smith,Keith Lloyd,,,,,male,11 Aug 1966,"San Francisco, San Francisco Co., CA",,,,,,,,,,,
[I0026],Smith,Kirsti Marie,,,,,female,15 Dec 1886,"Rønne, Bornholm, Denmark",,,,,18 Jul 1966,"San Francisco, San Francisco Co., CA",,,,,
[I0035],Smith,Lars Peter,,,,,male,16 Sep 1991,"Santa Rosa, Sonoma Co., CA",,,,,,,,,,,
[I0033],Smith,Lloyd,,,,,male,13 Mar 1935,"San Francisco, San Francisco Co., CA",,,,,,,,,,,
[I0003],Smith,Magnes,,,,,male,6 Oct 1858,"Simrishamn, Kristianstad Län, Sweden",,,,,20 Feb 1910,"Rønne, Bornholm, Denmark",,,,,
[I0040],Smith,Marjorie Alice,,,,,female,5 Feb 1960,"San Jose, Santa Clara Co., CA",,,,,,,,,,,
[I0014],Smith,Marjorie Lee,,,,,female,4 Nov 1934,"Reno, Washoe Co., NV",,,,,,,,,,,
[I0022],Smith,Martin,,,,,male,19 Nov 1830,"Gladsax, Kristianstad Län, Sweden",,23 Nov 1830,"Gladsax, Kristianstad Län, Sweden",,between 1899 and 1905,Sweden,,,,,
[I0039],Smith,Martin,,,,,male,between 1794 and 1796,"Tommarp, Kristianstad Län, Sweden",,,,,,Sweden,,,,,
[I0005],Smith,Mason Michael,,,,,male,26 Jun 1996,"Hayward, Alameda Co., CA",,,,,,,,,,,
[I0028],Streiffert,Anna,,,,,female,23 Sep 1860,"Hoya/Jona/Hoia, Sweden",,,,,2 Feb 1927,"Rønne, Bornholm, Denmark",,,,,
[I0012],Nielsen,Herman Julius,,,,,male,1889-08-31,[P0003],,,,,1945,,,,,,
[I0031],Ohman,Marjorie,,,,,female,1903-06-03,[P0014],,,,,1980-06-22,[P0005],,,,,
[I0034],Perkins,Alice Paula,,,,,female,1933-11-22,[P0001],,,,,,,,,,,
[I0002],Smith,Amber Marie,,,,,female,1998-04-12,[P0006],,,,,,,,,,,
[I0023],Smith,Astrid Shermanna Augusta,,,,,female,1889-01-31,[P0003],,,,,1963-12-21,[P0002],,,,,
[I0020],Smith,Carl Emil,,,,,male,1899-12-20,[P0003],,,,,1959-01-28,[P0005],,,,,
[I0029],Smith,Craig Peter,,,,,male,after 1966,[P0002],,,,,,,,,,,
[I0037],Smith,Edwin Michael,,,,,male,1961-05-24,[P0017],"Birth, Death and Marriage Records",,,,,,,,,,
[I0009],Smith,Emil,,,,,male,1860-09-27,[P0012],,,,,,,,,,,
[I0019],Smith,Eric Lloyd,,,,Dr.,male,1963-08-28,[P0002],,,,,,,,,,,
[I0015],Smith,Gus,,,,,male,1897-09-11,[P0003],,,,,1963-10-21,[P0002],,,,,
[I0024],Smith,Gustaf,,Sr.,,,male,1862-11-28,[P0009],,,,,before 1930-07-23,[P0001],,,,,
[I0011],Smith,Hanna,,,,,female,1821-01-29,[P0004],,,,,,,,,,,
[I0010],Smith,Hans Peter,,,,,male,1904-04-17,[P0003],Birth Records,,,,1977-01-29,[P0002],,1977-02-05,[P0002],findagrave.com,
[I0021],Smith,Hjalmar,,,,,male,1893-01-31,[P0003],,,,,1894-09-25,[P0003],,,,,
[I0008],Smith,Hjalmar,,,,,male,1895-04-07,[P0003],,1895-06-03,[P0021],,1975-06-26,[P0005],,,,,
[I0007],Smith,Ingar,,,,,female,after 1823,[P0004],,,,,,,,,,,
[I0027],Smith,Ingeman,,,,,male,about 1770,[P0008],,,,,,,,,,,
[I0004],Smith,Ingeman,,,,,male,1826-01-29,[P0004],,,,,,,,,,,
[I0018],Smith,John Hjalmar,,,,,male,1932-01-30,[P0002],,,,,,,,,,,
[I0001],Smith,Keith Lloyd,,,,,male,1966-08-11,[P0002],,,,,,,,,,,
[I0026],Smith,Kirsti Marie,,,,,female,1886-12-15,[P0003],,,,,1966-07-18,[P0002],,,,,
[I0035],Smith,Lars Peter,,,,,male,1991-09-16,[P0016],,,,,,,,,,,
[I0033],Smith,Lloyd,,,,,male,1935-03-13,[P0002],,,,,,,,,,,
[I0003],Smith,Magnes,,,,,male,1858-10-06,[P0012],,,,,1910-02-20,[P0003],,,,,
[I0040],Smith,Marjorie Alice,,,,,female,1960-02-05,[P0017],,,,,,,,,,,
[I0014],Smith,Marjorie Lee,,,,,female,1934-11-04,[P0005],,,,,,,,,,,
[I0022],Smith,Martin,,,,,male,1830-11-19,[P0004],,1830-11-23,[P0004],,between 1899 and 1905,[P0008],,,,,
[I0039],Smith,Martin,,,,,male,between 1794 and 1796,[P0020],,,,,,[P0008],,,,,
[I0005],Smith,Mason Michael,,,,,male,1996-06-26,[P0006],,,,,,,,,,,
[I0028],Streiffert,Anna,,,,,female,1860-09-23,[P0011],,,,,1927-02-02,[P0003],,,,,
[I0006],Willard,Edwin,,,,,male,about 1886,,,,,,,,,,,,
[I0043],リチミシキスイミ,ピーター,,,,,male,,,,,,,,,,,,,
Marriage,Husband,Wife,Date,Place,Source,Note
[F0000],[I0039],[I0036],about 1816,"Gladsax, Kristianstad Län, Sweden",,
[F0001],[I0027],[I0025],about 1790,Sweden,,
[F0000],[I0039],[I0036],about 1816,[P0004],,
[F0001],[I0027],[I0025],about 1790,[P0008],,
[F0002],[I0022],[I0038],about 1856,,,
[F0003],[I0024],[I0000],27 Nov 1885,"Rønne, Bornholm, Denmark",,
[F0003],[I0024],[I0000],1885-11-27,[P0003],,
[F0004],[I0006],[I0026],about 1910,,,
[F0005],[I0012],[I0023],30 Nov 1912,"Rønne, Bornholm, Denmark",,
[F0006],[I0008],[I0031],31 Oct 1927,"Reno, Washoe Co., NV",,
[F0005],[I0012],[I0023],1912-11-30,[P0003],,
[F0006],[I0008],[I0031],1927-10-31,[P0005],,
[F0007],[I0015],[I0013],about 1920,,,
[F0008],[I0033],[I0041],10 Aug 1958,"San Francisco, San Francisco Co., CA",,
[F0008],[I0033],[I0041],1958-08-10,[P0002],,
[F0009],[I0010],[I0017],,,,
[F0010],[I0019],[I0032],12 Jul 1986,"Woodland, Yolo Co., CA",,
[F0011],[I0003],[I0028],24 Aug 1884,"Rønne, Bornholm, Denmark",,
[F0012],[I0018],[I0034],4 Jun 1954,"Sparks, Washoe Co., NV",Marriage Certificae,
[F0013],[I0037],[I0030],27 May 1995,"San Ramon, Conta Costa Co., CA",,
[F0010],[I0019],[I0032],1986-07-12,[P0022],,
[F0011],[I0003],[I0028],1884-08-24,[P0003],,
[F0012],[I0018],[I0034],1954-06-04,[P0001],Marriage Certificae,
[F0013],[I0037],[I0030],1995-05-27,[P0023],,
[F0014],[I0010],[I0016],,,,
Family,Child
1 Place Title Name Type Latitude Longitude Code Enclosed_by Date
30 [P0014] Denver, Denver Co., CO Denver, Denver Co., CO City 39.7392 104.9903 W [P0024]
31 Person Surname Given Call Suffix Prefix Title Gender Birth date
32 [I0030] Adams Janice Ann female 26 Aug 1965 1965-08-26
33 [I0016] Anderson Jennifer female 5 Nov 1907 1907-11-05
34 [I0025] Ericsdotter Marta female about 1775
35 [I0041] Green Janis Elaine female 2 Dec 1935 1935-12-02
36 [I0000] Hansdotter Anna female 2 Oct 1864 1864-10-02
37 [I0038] Hansdotter Kerstina female 29 Nov 1832 1832-11-29
38 [I0032] Horne Darcy female 2 Jul 1966 1966-07-02
39 [I0036] Jefferson Elna female 14 Sep 1800 1800-09-14
40 [I0017] Jones Lillie Harriet female 2 May 1910 1910-05-02
41 [I0042] Ke 柯 male
42 [I0013] Michaels Evelyn female about 1897
43 [I0012] Nielsen Herman Julius male 31 Aug 1889 1889-08-31
44 [I0031] Ohman Marjorie female 3 Jun 1903 1903-06-03
45 [I0034] Perkins Alice Paula female 22 Nov 1933 1933-11-22
46 [I0002] Smith Amber Marie female 12 Apr 1998 1998-04-12
47 [I0023] Smith Astrid Shermanna Augusta female 31 Jan 1889 1889-01-31
48 [I0020] Smith Carl Emil male 20 Dec 1899 1899-12-20
49 [I0029] Smith Craig Peter male after 1966
50 [I0037] Smith Edwin Michael male 24 May 1961 1961-05-24
51 [I0009] Smith Emil male 27 Sep 1860 1860-09-27
52 [I0019] Smith Eric Lloyd Dr. male 28 Aug 1963 1963-08-28
53 [I0015] Smith Gus male 11 Sep 1897 1897-09-11
54 [I0024] Smith Gustaf Sr. male 28 Nov 1862 1862-11-28
55 [I0011] Smith Hanna female 29 Jan 1821 1821-01-29
56 [I0010] Smith Hans Peter male 17 Apr 1904 1904-04-17
57 [I0021] Smith Hjalmar male 31 Jan 1893 1893-01-31
58 [I0008] Smith Hjalmar male 7 Apr 1895 1895-04-07
59 [I0007] Smith Ingar female after 1823
60 [I0027] Smith Ingeman male about 1770
61 [I0004] Smith Ingeman male 29 Jan 1826 1826-01-29
62 [I0018] Smith John Hjalmar male 30 Jan 1932 1932-01-30
63 [I0001] Smith Keith Lloyd male 11 Aug 1966 1966-08-11
64 [I0026] Smith Kirsti Marie female 15 Dec 1886 1886-12-15
65 [I0035] Smith Lars Peter male 16 Sep 1991 1991-09-16
66 [I0033] Smith Lloyd male 13 Mar 1935 1935-03-13
67 [I0003] Smith Magnes male 6 Oct 1858 1858-10-06
68 [I0040] Smith Marjorie Alice female 5 Feb 1960 1960-02-05
69 [I0014] Smith Marjorie Lee female 4 Nov 1934 1934-11-04
70 [I0022] Smith Martin male 19 Nov 1830 1830-11-19
71 [I0039] Smith Martin male between 1794 and 1796
72 [I0005] Smith Mason Michael male 26 Jun 1996 1996-06-26
73 [I0028] Streiffert Anna female 23 Sep 1860 1860-09-23
74 [I0006] Willard Edwin male about 1886
75 [I0043] Marriage リチミシキスイミ Husband ピーター Wife Date Place Source Note
Marriage Husband Wife Date Place Source Note
76 [F0000] [I0039] [I0036] about 1816 Gladsax, Kristianstad Län, Sweden [P0004]
77 [F0001] [I0027] [I0025] about 1790 Sweden [P0008]
78 [F0002] [I0022] [I0038] about 1856
79 [F0003] [I0024] [I0000] 27 Nov 1885 1885-11-27 Rønne, Bornholm, Denmark [P0003]
80 [F0004] [I0006] [I0026] about 1910
81 [F0005] [I0012] [I0023] 30 Nov 1912 1912-11-30 Rønne, Bornholm, Denmark [P0003]
82 [F0006] [I0008] [I0031] 31 Oct 1927 1927-10-31 Reno, Washoe Co., NV [P0005]
83 [F0007] [I0015] [I0013] about 1920
84 [F0008] [I0033] [I0041] 10 Aug 1958 1958-08-10 San Francisco, San Francisco Co., CA [P0002]
85 [F0009] [I0010] [I0017]
86 [F0010] [I0019] [I0032] 12 Jul 1986 1986-07-12 Woodland, Yolo Co., CA [P0022]
87 [F0011] [I0003] [I0028] 24 Aug 1884 1884-08-24 Rønne, Bornholm, Denmark [P0003]
88 [F0012] [I0018] [I0034] 4 Jun 1954 1954-06-04 Sparks, Washoe Co., NV [P0001] Marriage Certificae
89 [F0013] [I0037] [I0030] 27 May 1995 1995-05-27 San Ramon, Conta Costa Co., CA [P0023]
90 [F0014] [I0010] [I0016]
91 Family Child
92 [F0000] [I0011]
93 [F0000] [I0007]
94 [F0000] [I0004]
+7
View File
@@ -1,3 +1,10 @@
gramps (5.1.1-1) unstable; urgency=medium
* New release
* Add python3-fontconfig to recommends
-- Ross Gammon <rossgammon@debian.org> Tue, 17 Sep 2019 15:21:43 +0200
gramps (5.1.0-1) unstable; urgency=medium
* New release
+2 -1
View File
@@ -42,7 +42,8 @@ Recommends:
gir1.2-gexiv2-0.10,
gir1.2-osmgpsmap-1.0,
python3-icu,
gir1.2-geocodeglib-1.0
gir1.2-geocodeglib-1.0,
python3-fontconfig
Suggests:
fonts-freefont-ttf,
gir1.2-goocanvas-2.0,
+1 -1
View File
@@ -280,7 +280,7 @@ class CLIManager:
# Attempt to figure out the database title
path = os.path.join(filename, "name.txt")
try:
with open(path) as ifile:
with open(path, encoding='utf8') as ifile:
title = ifile.readline().strip()
except:
title = filename
+2 -2
View File
@@ -88,9 +88,9 @@ def _convert_str_to_match_type(str_val, type_val):
return str(str_val)
elif ret_type == int:
if str_val.isdigit():
try:
return int(str_val)
else:
except ValueError:
print("'%s' is not an integer number" % str_val)
return 0
+1 -1
View File
@@ -145,7 +145,7 @@ sys.path.insert(0, ROOT_DIR)
git_revision = get_git_revision(ROOT_DIR).replace('\n', '')
if sys.platform == 'win32' and git_revision == "":
git_revision = get_git_revision(os.path.split(ROOT_DIR)[1])
#VERSION += git_revision
VERSION += git_revision
#VERSION += "-1"
#
+14 -1
View File
@@ -290,7 +290,8 @@ class DateDisplayDE(DateDisplay):
formats = (
"JJJJ-MM-DD (ISO)", "Numerisch", "Monat Tag Jahr",
"MONAT Tag Jahr", "Tag. Monat Jahr", "Tag. MONAT Jahr"
"MONAT Tag Jahr", "Tag. Monat Jahr", "Tag. MONAT Jahr",
"Numerisch mit führenden Nullen"
)
# this definition must agree with its "_display_gregorian" method
@@ -343,6 +344,18 @@ class DateDisplayDE(DateDisplay):
else:
value = "%d. %s %s" % (date_val[0],
self.long_months[date_val[1]], year)
elif self.format == 6:
# day.month_number.year with leading zeros
if date_val[3]:
return self.display_iso(date_val)
else:
if date_val[0] == date_val[1] == 0:
value = str(date_val[2])
else:
value = self.dhformat.replace('%m', str(date_val[1])
.zfill(2))
value = value.replace('%d', str(date_val[0]).zfill(2))
value = value.replace('%Y', str(date_val[2]))
else:
# day. month_abbreviation year
if date_val[0] == 0:
+9 -1
View File
@@ -32,7 +32,7 @@ database to fetch data from). Thus, dbstate.db cannot be left as 'None' because
None has no 'is_open' attribute. Therefore this database class is provided so
that it can be instantiated for dbstate.db.
FIXME: Ideally, only is_open() needs to be implemented here, bacause that is the
FIXME: Ideally, only is_open() needs to be implemented here, because that is the
only method that should really be called, but the Gramps code is not perfect,
and many other methods are called. Calls of other methods could be considered
bugs, so when these are fixed, this class could be reduced.
@@ -757,6 +757,14 @@ class DummyDb(M_A_M_B("NewBaseClass", (DbReadBase, Callback, object,), {})):
LOG.warning("database is closed")
return 0
def get_number_of_citations(self):
"""
Return the number of citations currently in the database.
"""
if not self.db_is_open:
LOG.warning("database is closed")
return 0
def get_number_of_tags(self):
"""
Return the number of tags currently in the database.
+1 -1
View File
@@ -757,7 +757,7 @@ class DbGeneric(DbWriteBase, DbReadBase, UpdateCallback, Callback):
if self._directory:
filepath = os.path.join(self._directory, "name.txt")
try:
with open(filepath, "r") as name_file:
with open(filepath, "r", encoding='utf8') as name_file:
name = name_file.readline().strip()
except (OSError, IOError) as msg:
LOG.error(str(msg))
@@ -28,6 +28,7 @@ from ._hascitation import HasCitation
from ._allcitations import AllCitations
from ._changedsince import ChangedSince
from ._citationprivate import CitationPrivate
from ._hasattribute import HasAttribute
from ._hasgallery import HasGallery
from ._hasidof import HasIdOf
from ._hasnote import HasNote
@@ -50,6 +51,7 @@ editor_rule_list = [
AllCitations,
ChangedSince,
CitationPrivate,
HasAttribute,
HasGallery,
HasIdOf,
HasNote,
@@ -0,0 +1,49 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2019 Matthias Kemmer
#
# 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.
#
# -------------------------------------------------------------------------
#
# Standard Python modules
#
# -------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
# -------------------------------------------------------------------------
#
# Gramps modules
#
# -------------------------------------------------------------------------
from .._hasattributebase import HasAttributeBase
# -------------------------------------------------------------------------
#
# HasAttribute
#
# -------------------------------------------------------------------------
class HasAttribute(HasAttributeBase):
"""Rule that checks for a citation with a particular attribute"""
labels = [_('Citation attribute:'), _('Value:')]
name = _('Citations with the attribute <attribute>')
description = _("Matches citations with the attribute "
"of a particular value")
@@ -29,6 +29,7 @@ from ._disconnected import Disconnected
from ._everyone import Everyone
from ._familywithincompleteevent import FamilyWithIncompleteEvent
from ._hasaddress import HasAddress
from ._hasaddresstext import HasAddressText
from ._hasalternatename import HasAlternateName
from ._hasassociation import HasAssociation
from ._hasattribute import HasAttribute
@@ -125,6 +126,7 @@ editor_rule_list = [
IsBookmarked,
HasAlternateName,
HasAddress,
HasAddressText,
HasAssociation,
HasIdOf,
HasLDS,
@@ -0,0 +1,54 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2008 Jerome Rapinat
# Copyright (C) 2008 Benny Malengier
#
# 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.
#
# -------------------------------------------------------------------------
#
# Gramps modules
#
# -------------------------------------------------------------------------
from .. import Rule
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
# -------------------------------------------------------------------------
#
# HasAddressText
#
# -------------------------------------------------------------------------
class HasAddressText(Rule):
"""Rule that checks for text in personal addresses"""
labels = [_('Text:')]
name = _('People with an address containing <text>')
description = _("Matches people with a personal address containing "
"the given text")
category = _('General filters')
allow_regex = True
def apply(self, db, person):
for address in person.get_address_list():
for string in address.get_text_data_list():
if self.match_substring(0, string):
return True
return False
@@ -37,10 +37,10 @@ import re
# Gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.errors import FilterError
from ....const import GRAMPS_LOCALE as glocale
from .. import Rule
from ....utils.place import conv_lat_lon
from gramps.gen.errors import FilterError
_ = glocale.translation.sgettext
@@ -81,13 +81,13 @@ class WithinArea(Rule):
"D.D8")
if self.latitude is None or self.longitude is None:
raise FilterError(_("Cannot use the filter 'within area'"),
_("The place you selected contains bad coordinates. "
"Please, run the tool 'clean input data'"))
return
_("The place you selected contains bad"
" coordinates. Please, run the tool "
"'clean input data'"))
val = self.list[1]
if isinstance(val, str):
val = re.sub(r"\D", "", val) # suppress all alpha characters
val = re.sub(r"\D", "", val) # suppress all alpha characters
value = int(val)
unit = int(self.list[2])
# earth perimeter in kilometers for latitude
@@ -25,6 +25,7 @@ Package providing filter rules for Gramps.
from ._allrepos import AllRepos
from ._hasidof import HasIdOf
from ._regexpidof import RegExpIdOf
from ._hasattribute import HasAttribute
from ._hasnoteregexp import HasNoteRegexp
from ._hasnotematchingsubstringof import HasNoteMatchingSubstringOf
from ._hasreferencecountof import HasReferenceCountOf
@@ -37,6 +38,7 @@ from ._hastag import HasTag
editor_rule_list = [
AllRepos,
HasAttribute,
HasIdOf,
RegExpIdOf,
HasNoteRegexp,
@@ -0,0 +1,49 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2019 Matthias Kemmer
#
# 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.
#
# -------------------------------------------------------------------------
#
# Standard Python modules
#
# -------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
# -------------------------------------------------------------------------
#
# Gramps modules
#
# -------------------------------------------------------------------------
from .._hasattributebase import HasAttributeBase
# -------------------------------------------------------------------------
#
# HasAttribute
#
# -------------------------------------------------------------------------
class HasAttribute(HasAttributeBase):
"""Rule that checks for a repository with a particular attribute"""
labels = [_('Repository attribute:'), _('Value:')]
name = _('Repositories with the attribute <attribute>')
description = _("Matches repositories with the attribute "
"of a particular value")
@@ -27,6 +27,7 @@ Package providing filter rules for Gramps.
from .._hassourcebase import HasSourceBase as HasSource
from ._allsources import AllSources
from ._hasattribute import HasAttribute
from ._hasgallery import HasGallery
from ._hasidof import HasIdOf
from ._regexpidof import RegExpIdOf
@@ -45,6 +46,7 @@ from ._hastag import HasTag
editor_rule_list = [
AllSources,
HasAttribute,
HasGallery,
HasIdOf,
RegExpIdOf,
@@ -0,0 +1,49 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2019 Matthias Kemmer
#
# 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.
#
# -------------------------------------------------------------------------
#
# Standard Python modules
#
# -------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
# -------------------------------------------------------------------------
#
# Gramps modules
#
# -------------------------------------------------------------------------
from .._hasattributebase import HasAttributeBase
# -------------------------------------------------------------------------
#
# HasAttribute
#
# -------------------------------------------------------------------------
class HasAttribute(HasAttributeBase):
"""Rule that checks for a source with a particular attribute"""
labels = [_('Source attribute:'), _('Value:')]
name = _('Sources with the attribute <attribute>')
description = _("Matches sources with the attribute "
"of a particular value")
+75 -2
View File
@@ -69,6 +69,12 @@ _MARRIAGE = [{'name': _("Default"), 'value': ""},
{'name': _("Below"), 'value': "marriage below"},
{'name': _("Not shown"), 'value': "no marriage"}]
_OCCUPATION = [{'name': _("Do not include"), 'value': "no"},
{'name': _("Only description"), 'value': "basic"},
{'name': _("Use date"), 'value': "date"},
{'name': _("Use place"), 'value': "place"},
{'name': _("Use date and place"), 'value': "date place"}]
_COLOR = [{'name': _("None"), 'value': "none"},
{'name': _("Default"), 'value': "default"},
{'name': _("Preferences"), 'value': "preferences"}]
@@ -153,6 +159,12 @@ class TreeOptions:
marriage.set_help(_("Position of marriage information."))
menu.add_option(category, "marriage", marriage)
occupation = EnumeratedListOption(_("Occupation"), "")
for item in _OCCUPATION:
occupation.add_item(item["value"], item["name"])
occupation.set_help(_("Details of occupation information."))
menu.add_option(category, "occupation", occupation)
nodesize = NumberOption(_("Node size"), 25, 5, 100, 5)
nodesize.set_help(_("One dimension of a node, in mm. If the timeflow "
"is up or down then this is the width, otherwise "
@@ -282,6 +294,7 @@ class TreeDocBase(BaseDoc, TreeDoc):
self.detail = get_option('detail').get_value()
self.marriage = get_option('marriage').get_value()
self.occupation = get_option('occupation').get_value()
self.nodesize = get_option('nodesize').get_value()
self.levelsize = get_option('levelsize').get_value()
self.nodecolor = get_option('nodecolor').get_value()
@@ -449,8 +462,9 @@ class TreeDocBase(BaseDoc, TreeDoc):
# Comparison with 'Occupation' for backwards compatibility with Gramps 5.0
attr_type = str(attr.get_type())
if attr_type in ('Occupation', _('Occupation')):
self.write(level+1, 'profession = {%s},\n' %
escape(attr.get_value()))
if self.occupation != "no":
self.write(level+1, 'profession = {%s},\n' %
escape(attr.get_value()))
if attr_type == 'Comment':
self.write(level+1, 'comment = {%s},\n' %
escape(attr.get_value()))
@@ -494,6 +508,8 @@ class TreeDocBase(BaseDoc, TreeDoc):
elif event.type == EventType.CREMATION:
event_type = 'burial'
modifier = 'cremated'
elif event.type == EventType.OCCUPATION:
event_type = 'occupation'
else:
return
@@ -520,6 +536,17 @@ class TreeDocBase(BaseDoc, TreeDoc):
place = escape(_pd.display_event(db, event))
if event_type == 'occupation' and self.occupation != "no":
description = escape(event.description)
self.write(level, 'profession = {%s}' % description)
if self.occupation == "date":
self.write(level+1, '{%s}' % date_str)
if self.occupation == "place":
self.write(level+1, '{%s}' % place)
if self.occupation == "date place":
self.write(level+1, '{%s}\, {%s}' % (date_str, place))
self.write(level, ',\n')
if modifier:
event_type += '+'
self.write(level, '%s = {%s}{%s}{%s},\n' %
@@ -586,6 +613,47 @@ class TreeDocBase(BaseDoc, TreeDoc):
self.write_end()
#------------------------------------------------------------------------------
#
# TreeGraphDoc
#
#------------------------------------------------------------------------------
class TreeGraphDoc(TreeDocBase):
"""
TreeGraphDoc implementation that generates a .graph file.
"""
def write_start(self):
"""
Write the start of the document - nothing for a graph file.
"""
pass
def start_tree(self, option_list):
"""
Write the start of a tree - nothing for a graph file.
"""
pass
def end_tree(self):
"""
Write the end of a tree - nothing for a graph file.
"""
pass
def write_end(self):
"""
Write the end of the document - nothing for a graph file.
"""
pass
def close(self):
""" Implements TreeDocBase.close() """
TreeDocBase.close(self)
with open(self._filename, 'w', encoding='utf-8') as texfile:
texfile.write(self._tex.getvalue())
#------------------------------------------------------------------------------
#
# TreeTexDoc
@@ -653,6 +721,11 @@ if _LATEX_FOUND:
'mime' : "application/pdf",
'class': TreePdfDoc}]
FORMATS += [{'type' : "graph",
'ext' : "graph",
'descr': _("Graph File for genealogytree"),
'class': TreeGraphDoc}]
FORMATS += [{'type' : "tex",
'ext' : "tex",
'descr': _("LaTeX File"),
+2 -2
View File
@@ -161,12 +161,12 @@ def image_size(source):
:returns: a tuple consisting of the width and height
"""
from gi.repository import GdkPixbuf
from gi.repository import GObject
from gi.repository import GLib
try:
img = GdkPixbuf.Pixbuf.new_from_file(source)
width = img.get_width()
height = img.get_height()
except GObject.GError:
except GLib.GError:
width = 0
height = 0
return (width, height)
+4 -4
View File
@@ -36,7 +36,7 @@ from hashlib import md5
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gi.repository import GObject
from gi.repository import GLib
from gi.repository import GdkPixbuf
try:
@@ -98,7 +98,7 @@ def __get_gconf_string(key):
"""
try:
val = CLIENT.get_string(key)
except GObject.GError:
except GLib.GError:
val = None
return str(val)
@@ -119,7 +119,7 @@ def __get_gconf_bool(key):
"""
try:
val = CLIENT.get_bool(key)
except GObject.GError:
except GLib.GError:
val = None
return val
@@ -318,7 +318,7 @@ def get_thumbnail_image(src_file, mtype=None, rectangle=None, size=SIZE_NORMAL):
try:
filename = get_thumbnail_path(src_file, mtype, rectangle, size)
return GdkPixbuf.Pixbuf.new_from_file(filename)
except (GObject.GError, OSError):
except (GLib.GError, OSError):
if mtype:
return find_mime_type_pixbuf(mtype)
else:
+1 -1
View File
@@ -212,7 +212,7 @@ def show_settings():
Gtk.get_minor_version(), Gtk.get_micro_version())
except: # any failure to 'get' the version
gtkver_str = 'unknown version'
except ImportError:
except (ImportError, ValueError):
gtkver_str = 'not found'
# no DISPLAY is a RuntimeError in an older pygtk (e.g. 2.17 in Fedora 14)
except RuntimeError:
+42 -50
View File
@@ -690,7 +690,7 @@ class GrampsPreferences(ConfigureDialog):
hbox.pack_start(lwidget, False, False, 0)
hbox.pack_start(self.color_scheme_box, False, False, 0)
restore_btn = Gtk.Button(_('Restore to defaults'))
restore_btn = Gtk.Button(label=_('Restore to defaults'))
restore_btn.set_tooltip_text(
_('Restore colors for current theme to default.'))
restore_btn.connect('clicked', self.restore_colors)
@@ -1256,14 +1256,15 @@ class GrampsPreferences(ConfigureDialog):
_("Years, Months, Days")]
list(map(obox.append_text, age_precision))
# Combo_box active index is from 0 to 2, we need values from 1 to 3
constant = 'preferences.age-display-precision'
active = config.get(constant) - 1
active = config.get('preferences.age-display-precision') - 1
if active >= 0 and active <= 2:
obox.set_active(active)
else:
obox.set_active(0)
obox.connect('changed',
lambda obj: config.set(constant, obj.get_active() + 1))
obox.connect(
'changed',
lambda obj: config.set('preferences.age-display-precision',
obj.get_active() + 1))
lwidget = BasicLabel(_("%s: ")
% _('Age display precision (requires restart)'))
grid.attach(lwidget, 0, row, 1, 1)
@@ -1300,10 +1301,10 @@ class GrampsPreferences(ConfigureDialog):
obox = Gtk.ComboBoxText()
formats = FamilyRelType().get_standard_names()
list(map(obox.append_text, formats))
constant = 'preferences.family-relation-type'
obox.set_active(config.get(constant))
obox.set_active(config.get('preferences.family-relation-type'))
obox.connect('changed',
lambda obj: config.set(constant, obj.get_active()))
lambda obj: config.set('preferences.family-relation-type',
obj.get_active()))
lwidget = BasicLabel(_("%s: ") % _('Default family relationship'))
grid.attach(lwidget, 0, row, 1, 1)
grid.attach(obox, 1, row, 2, 1)
@@ -1489,6 +1490,26 @@ class GrampsPreferences(ConfigureDialog):
align=Gtk.Align.CENTER, bold=True)
row = 1
self.add_pos_int_entry(
grid, _('Markup for invalid date format'),
row, 'preferences.invalid-date-format',
self.update_markup_entry,
helptext=_(
'Convenience markups are:\n'
'<b>&lt;b&gt;Bold&lt;/b&gt;</b>\n'
'<big>&lt;big&gt;'
'Makes font relatively larger&lt;/big&gt;</big>\n'
'<i>&lt;i&gt;Italic&lt;/i&gt;</i>\n'
'<s>&lt;s&gt;Strikethrough&lt;/s&gt;</s>\n'
'<sub>&lt;sub&gt;Subscript&lt;/sub&gt;</sub>\n'
'<sup>&lt;sup&gt;Superscript&lt;/sup&gt;</sup>\n'
'<small>&lt;small&gt;'
'Makes font relatively smaller&lt;/small&gt;</small>\n'
'<tt>&lt;tt&gt;Monospace font&lt;/tt&gt;</tt>\n'
'<u>&lt;u&gt;Underline&lt;/u&gt;</u>\n\n'
'For example: &lt;u&gt;&lt;b&gt;%s&lt;/b&gt;&lt;/u&gt;\n'
'will display <u><b>Underlined bold date</b></u>.\n'))
row += 1
self.add_spinner(
grid, _('Date about range'),
row, 'behavior.date-about-range', (1, 9999))
@@ -1516,26 +1537,6 @@ class GrampsPreferences(ConfigureDialog):
self.add_spinner(
grid, _('Average years between generations'),
row, 'behavior.avg-generation-gap', (10, 30))
row += 1
self.add_pos_int_entry(
grid, _('Markup for invalid date format'),
row, 'preferences.invalid-date-format',
self.update_markup_entry,
helptext=_(
'Convenience markups are:\n'
'<b>&lt;b&gt;Bold&lt;/b&gt;</b>\n'
'<big>&lt;big&gt;'
'Makes font relatively larger&lt;/big&gt;</big>\n'
'<i>&lt;i&gt;Italic&lt;/i&gt;</i>\n'
'<s>&lt;s&gt;Strikethrough&lt;/s&gt;</s>\n'
'<sub>&lt;sub&gt;Subscript&lt;/sub&gt;</sub>\n'
'<sup>&lt;sup&gt;Superscript&lt;/sup&gt;</sup>\n'
'<small>&lt;small&gt;'
'Makes font relatively smaller&lt;/small&gt;</small>\n'
'<tt>&lt;tt&gt;Monospace font&lt;/tt&gt;</tt>\n'
'<u>&lt;u&gt;Underline&lt;/u&gt;</u>\n\n'
'For example: &lt;u&gt;&lt;b&gt;%s&lt;/b&gt;&lt;/u&gt;\n'
'will display <u><b>Underlined bold date</b></u>.\n'))
return _('Dates'), grid
@@ -1827,12 +1828,10 @@ class GrampsPreferences(ConfigureDialog):
Show dialog to choose media directory.
"""
f = Gtk.FileChooserDialog(title=_("Select media directory"),
parent=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Apply'),
Gtk.ResponseType.OK))
transient_for=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER)
f.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Apply'), Gtk.ResponseType.OK)
mpath = media_path(self.dbstate.db)
f.set_current_folder(os.path.dirname(mpath))
@@ -1877,12 +1876,10 @@ class GrampsPreferences(ConfigureDialog):
Show dialog to choose backup directory.
"""
f = Gtk.FileChooserDialog(title=_("Select backup directory"),
parent=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Apply'),
Gtk.ResponseType.OK))
transient_for=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER)
f.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Apply'), Gtk.ResponseType.OK)
backup_path = config.get('database.backup-path')
if not backup_path:
backup_path = config.get('database.path')
@@ -2093,9 +2090,9 @@ class GrampsPreferences(ConfigureDialog):
self.all_avail_fonts, callback=self.utf8_update_font,
valueactive=True, setactive=active_val)
if len(available_fonts) == 1:
single_font = self.all_avail_fonts[choosefont.get_active()][1]
single_font = self.all_avail_fonts[choosefont.get_active()][0]
config.set('utf8.selected-font',
self.all_avail_fonts[single_font])
self.all_avail_fonts[single_font][1])
self.utf8_show_example()
symbols = Symbols()
all_sbls = symbols.get_death_symbols()
@@ -2162,11 +2159,9 @@ class GrampsPreferences(ConfigureDialog):
scrollw.set_size_request(600, 100)
text = Gtk.Label()
text.set_line_wrap(True)
font_description = Pango.font_description_from_string(font)
text.modify_font(font_description)
self.activate_change_font()
text.set_halign(Gtk.Align.START)
text.set_text(my_characters)
text.set_markup("<span font='%s'>%s</span>" % (font, my_characters))
scrollw.add(text)
scrollw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
self.grid.attach(scrollw, 1, 7, 8, 1)
@@ -2179,12 +2174,9 @@ class GrampsPreferences(ConfigureDialog):
my_characters += symbols.get_death_symbol_for_char(death_symbl)
text = Gtk.Label()
text.set_line_wrap(True)
font_description = Pango.font_description_from_string(font)
text.modify_font(font_description)
text.set_halign(Gtk.Align.START)
text.set_markup("<big><big><big><big>" +
my_characters +
"</big></big></big></big>")
text.set_markup("<big><big><big><big><span font='%s'>%s</span>"
"</big></big></big></big>" % (font, my_characters))
self.grid.attach(text, 1, 8, 8, 1)
scrollw.show_all()
text.show_all()
+1 -1
View File
@@ -380,7 +380,7 @@ class GrampsLoginDialog(ManagedWindow):
self.title = _("Login")
ManagedWindow.__init__(self, uistate, [], self.__class__, modal=True)
dialog = Gtk.Dialog(parent=uistate.window)
dialog = Gtk.Dialog(transient_for=uistate.window)
grid = Gtk.Grid()
grid.set_border_width(6)
grid.set_row_spacing(6)
+7 -6
View File
@@ -42,6 +42,7 @@ import pickle
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import Pango
from gi.repository.GLib import markup_escape_text
#-------------------------------------------------------------------------
#
@@ -435,7 +436,6 @@ class EditPerson(EditPrimary):
obj.connect('changed', self._changed_name)
self.preview_name = self.top.get_object("full_name")
self.preview_name.override_font(Pango.FontDescription('sans bold 12'))
self.surntab = SurnameTab(self.dbstate, self.uistate, self.track,
self.obj.get_primary_name(),
on_change=self._changed_name)
@@ -550,7 +550,9 @@ class EditPerson(EditPrimary):
Update the window title, and default name in name tab
"""
self.update_title(self.get_menu_title())
self.preview_name.set_text(self.get_preview_name())
self.preview_name.set_markup(
"<span size='x-large' weight='bold'>%s</span>" %
markup_escape_text(self.get_preview_name(), -1))
self.name_list.update_defname()
def name_callback(self):
@@ -638,7 +640,6 @@ class EditPerson(EditPrimary):
"""
self.imgmenu = Gtk.Menu()
menu = self.imgmenu
menu.set_title(_("Media Object"))
obj = self.db.get_media_from_handle(photo.get_reference_handle())
if obj:
add_menuitem(menu, _("View"), photo,
@@ -1086,9 +1087,9 @@ class EditPerson(EditPrimary):
class GenderDialog(Gtk.MessageDialog):
def __init__(self, parent=None):
Gtk.MessageDialog.__init__(self,
parent,
flags=Gtk.DialogFlags.MODAL,
type=Gtk.MessageType.QUESTION,
transient_for=parent,
modal=True,
message_type=Gtk.MessageType.QUESTION,
)
self.set_icon(ICON)
self.set_title('')
+11 -5
View File
@@ -158,24 +158,30 @@ class EditPlace(EditPrimary):
self.obj.set_code, self.obj.get_code,
self.db.readonly)
entry = self.top.get_object("lon_entry")
entry.set_ltr_mode()
self.longitude = MonitoredEntry(
self.top.get_object("lon_entry"),
entry,
self.obj.set_longitude, self.obj.get_longitude,
self.db.readonly)
self.longitude.connect("validate", self._validate_coordinate, "lon")
#force validation now with initial entry
self.top.get_object("lon_entry").validate(force=True)
entry.validate(force=True)
entry = self.top.get_object("lat_entry")
entry.set_ltr_mode()
self.latitude = MonitoredEntry(
self.top.get_object("lat_entry"),
entry,
self.obj.set_latitude, self.obj.get_latitude,
self.db.readonly)
self.latitude.connect("validate", self._validate_coordinate, "lat")
#force validation now with initial entry
self.top.get_object("lat_entry").validate(force=True)
entry.validate(force=True)
entry = self.top.get_object("latlon_entry")
entry.set_ltr_mode()
self.latlon = MonitoredEntry(
self.top.get_object("latlon_entry"),
entry,
self.set_latlongitude, self.get_latlongitude,
self.db.readonly)
+11 -5
View File
@@ -151,24 +151,30 @@ class EditPlaceRef(EditReference):
self.source.set_code, self.source.get_code,
self.db.readonly)
entry = self.top.get_object("lon_entry")
entry.set_ltr_mode()
self.longitude = MonitoredEntry(
self.top.get_object("lon_entry"),
entry,
self.source.set_longitude, self.source.get_longitude,
self.db.readonly)
self.longitude.connect("validate", self._validate_coordinate, "lon")
#force validation now with initial entry
self.top.get_object("lon_entry").validate(force=True)
entry.validate(force=True)
entry = self.top.get_object("lat_entry")
entry.set_ltr_mode()
self.latitude = MonitoredEntry(
self.top.get_object("lat_entry"),
entry,
self.source.set_latitude, self.source.get_latitude,
self.db.readonly)
self.latitude.connect("validate", self._validate_coordinate, "lat")
#force validation now with initial entry
self.top.get_object("lat_entry").validate(force=True)
entry.validate(force=True)
entry = self.top.get_object("latlon_entry")
entry.set_ltr_mode()
self.latlon = MonitoredEntry(
self.top.get_object("latlon_entry"),
entry,
self.set_latlongitude, self.get_latlongitude,
self.db.readonly)
+1 -1
View File
@@ -101,7 +101,7 @@ class EditTagList(ManagedWindow):
Create a dialog box to select tags.
"""
# pylint: disable-msg=E1101
top = Gtk.Dialog(parent=self.uistate.window)
top = Gtk.Dialog(transient_for=self.uistate.window)
top.vbox.set_spacing(5)
columns = [('', -1, 300),
+8 -4
View File
@@ -311,7 +311,10 @@ class PlaceEntry(ObjEntry):
def get_label(self, place):
place_title = place_displayer.display(self.db, place)
return "%s [%s]" % (place_title, place.gramps_id)
# When part of the place title contains RTL text, the gramps_id gets
# messed up; so use Unicode FSI/PDI and LRM chars to isolate it.
# see bug 10124 and PR924
return "%s \u2068[%s]\u200e\u2069" % (place_title, place.gramps_id)
def call_editor(self, obj=None):
if obj is None:
@@ -356,7 +359,7 @@ class SourceEntry(ObjEntry):
return self.db.get_source_from_handle(handle)
def get_label(self, source):
return "%s [%s]" % (source.get_title(), source.gramps_id)
return "%s \u2068[%s]\u200e\u2069" % (source.get_title(), source.gramps_id)
def call_editor(self, obj=None):
if obj is None:
@@ -402,7 +405,8 @@ class MediaEntry(ObjEntry):
return self.db.get_media_from_handle(handle)
def get_label(self, object):
return "%s [%s]" % (object.get_description(), object.gramps_id)
return "%s \u2068[%s]\u200e\u2069" % (object.get_description(),
object.gramps_id)
def call_editor(self, obj=None):
if obj is None:
@@ -462,7 +466,7 @@ class NoteEntry(ObjEntry):
txt = " ".join(note.get().split())
if len(txt) > 35:
txt = txt[:35] + "..."
return "%s [%s]" % (txt, note.gramps_id)
return "%s \u2068[%s]\u200e\u2069" % (txt, note.gramps_id)
def call_editor(self, obj=None):
if obj is None:
+1 -1
View File
@@ -618,7 +618,7 @@ class Gramps:
and not gettext.find(GTK_GETTEXT_DOMAIN)):
_display_gtk_gettext_message(parent=self._vm.window)
#_display_welcome_message(parent=self._vm.window)
_display_welcome_message(parent=self._vm.window)
_display_translator_message(parent=self._vm.window)
+21 -14
View File
@@ -284,7 +284,8 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"information included in the error please remove "
"it."))
label.set_halign(Gtk.Align.START)
label.set_padding(0, 4)
label.set_margin_top(4)
label.set_margin_bottom(4)
label.set_line_wrap(True)
swin = Gtk.ScrolledWindow()
@@ -300,9 +301,9 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
sw_frame = Gtk.Frame()
sw_frame.add(swin)
reset = Gtk.Button("Reset")
reset = Gtk.Button(label="Reset")
reset.connect('clicked', self._reset_error_details)
clear = Gtk.Button("Clear")
clear = Gtk.Button(label="Clear")
clear.connect('clicked', self._clear_error_details)
button_box = Gtk.ButtonBox()
@@ -364,7 +365,8 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"remove anything that you would rather not have "
"included in the bug report."))
label.set_halign(Gtk.Align.START)
label.set_padding(0, 4)
label.set_margin_top(4)
label.set_margin_bottom(4)
label.set_line_wrap(True)
swin = Gtk.ScrolledWindow()
@@ -380,9 +382,9 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
sw_frame = Gtk.Frame()
sw_frame.add(swin)
reset = Gtk.Button("Reset")
reset = Gtk.Button(label="Reset")
reset.connect('clicked', self._reset_sys_information)
clear = Gtk.Button("Clear")
clear = Gtk.Button(label="Clear")
clear.connect('clicked', self._clear_sys_information)
@@ -441,7 +443,8 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"can about what you were doing when the error "
"occurred."))
label.set_halign(Gtk.Align.START)
label.set_padding(0, 4)
label.set_margin_top(4)
label.set_margin_bottom(4)
label.set_line_wrap(True)
swin = Gtk.ScrolledWindow()
@@ -456,7 +459,7 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
sw_frame = Gtk.Frame()
sw_frame.add(swin)
clear = Gtk.Button("Clear")
clear = Gtk.Button(label="Clear")
clear.connect('clicked', self._clear_user_information)
button_box = Gtk.ButtonBox()
@@ -514,7 +517,8 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"that it does not contain anything that you do not "
"want to be sent to the developers."))
label.set_halign(Gtk.Align.START)
label.set_padding(0, 4)
label.set_margin_top(4)
label.set_margin_bottom(4)
label.set_line_wrap(True)
swin = Gtk.ScrolledWindow()
@@ -580,7 +584,8 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"clipboard and then open a webbrowser to file a bug report at "),
URL_BUGTRACKER))
label.set_halign(Gtk.Align.START)
label.set_padding(0, 4)
label.set_margin_top(4)
label.set_margin_bottom(4)
label.set_line_wrap(True)
label.set_use_markup(True)
@@ -589,11 +594,12 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"and file a bug report on the Gramps bug "
"tracking system."))
url_label.set_halign(Gtk.Align.START)
url_label.set_padding(0, 4)
url_label.set_margin_top(4)
url_label.set_margin_bottom(4)
url_label.set_line_wrap(True)
url_label.set_size_request(200, -1)
url_button = Gtk.Button("File bug report")
url_button = Gtk.Button(label="File bug report")
url_button.connect('clicked', self._start_gramps_bts_in_browser)
url_button_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
url_button_vbox.pack_start(url_button, True, False, 0)
@@ -613,11 +619,12 @@ class ErrorReportAssistant(ManagedWindow, Gtk.Assistant):
"the button below, paste the report and click "
"submit report"))
clip_label.set_halign(Gtk.Align.START)
clip_label.set_padding(0, 4)
clip_label.set_margin_top(4)
clip_label.set_margin_bottom(4)
clip_label.set_line_wrap(True)
clip_label.set_size_request(200, -1)
clip_button = Gtk.Button("Copy to clipboard")
clip_button = Gtk.Button(label="Copy to clipboard")
clip_button.connect('clicked', self._copy_to_clipboard)
clip_button_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
clip_button_vbox.pack_start(clip_button, True, False, 0)
+1 -1
View File
@@ -105,7 +105,7 @@ class ErrorView(ManagedWindow):
def draw_window(self):
title = "%s - Gramps" % _("Error Report")
self.top = Gtk.Dialog(title)
self.top = Gtk.Dialog(title=title)
# look over the top level windows, it seems the oldest come first, so
# the most recent still visible window appears to be a good choice for
# a transient parent
+10 -11
View File
@@ -75,16 +75,17 @@ class LastNameDialog(ManagedWindow):
def __init__(self, database, uistate, track, surnames, skip_list=set()):
ManagedWindow.__init__(self, uistate, track, self, modal=True)
flags = Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT
buttons = (_('_Cancel'), Gtk.ResponseType.REJECT,
_('_OK'), Gtk.ResponseType.ACCEPT)
self.__dlg = Gtk.Dialog(None, uistate.window, flags, buttons)
self.__dlg = Gtk.Dialog(
transient_for=uistate.window, destroy_with_parent=True,
modal=True)
self.__dlg.add_buttons(_('_Cancel'), Gtk.ResponseType.REJECT,
_('_OK'), Gtk.ResponseType.ACCEPT)
self.set_window(self.__dlg, None, _('Select surname'))
self.setup_configs('interface.lastnamedialog', 400, 400)
# build up a container to display all of the people of interest
self.__model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_INT)
self.__tree_view = Gtk.TreeView(self.__model)
self.__tree_view = Gtk.TreeView(model=self.__model)
col1 = Gtk.TreeViewColumn(_('Surname'), Gtk.CellRendererText(), text=0)
col2 = Gtk.TreeViewColumn(_('Count'), Gtk.CellRendererText(), text=1)
col1.set_resizable(True)
@@ -1739,12 +1740,10 @@ class GuiDestinationOption(Gtk.Box):
else:
my_action = Gtk.FileChooserAction.SAVE
fcd = Gtk.FileChooserDialog(_("Save As"), action=my_action,
parent=self.__uistate.window,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Open'),
Gtk.ResponseType.OK))
fcd = Gtk.FileChooserDialog(title=_("Save As"), action=my_action,
transient_for=self.__uistate.window)
fcd.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Open'), Gtk.ResponseType.OK)
name = os.path.abspath(self.__option.get_value())
if self.__option.get_directory_entry():
+10 -12
View File
@@ -435,12 +435,10 @@ class PluginStatus(ManagedWindow):
"""
Select a file from the file system.
"""
fcd = Gtk.FileChooserDialog(_("Load Addon"),
parent=self.__uistate.window,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Open'),
Gtk.ResponseType.OK))
fcd = Gtk.FileChooserDialog(title=_("Load Addon"),
transient_for=self.__uistate.window)
fcd.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Open'), Gtk.ResponseType.OK)
name = self.install_addon_path.get_text()
dir = os.path.dirname(name)
if not os.path.isdir(dir):
@@ -688,10 +686,10 @@ class PluginTrace(ManagedWindow):
) % {'str1': _("Plugin Error"), 'str2': name}
ManagedWindow.__init__(self, uistate, track, self)
self.set_window(Gtk.Dialog("", uistate.window,
Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_Close'), Gtk.ResponseType.CLOSE)),
None, title)
dlg = Gtk.Dialog(title="", transient_for=uistate.window,
destroy_with_parent=True)
dlg.add_button(_('_Close'), Gtk.ResponseType.CLOSE),
self.set_window(dlg, None, title)
self.setup_configs('interface.plugintrace', 600, 400)
self.window.connect('response', self.close)
@@ -742,7 +740,7 @@ class ToolManagedWindowBase(ManagedWindow):
self.format_menu = None
self.style_button = None
window = Gtk.Dialog('Tool')
window = Gtk.Dialog(title='Tool')
self.set_window(window, None, self.get_title())
#self.window.connect('response', self.close)
@@ -768,7 +766,7 @@ class ToolManagedWindowBase(ManagedWindow):
self.notebook = Gtk.Notebook()
self.notebook.set_border_width(6)
self.window.get_content_area().add(self.notebook)
self.window.get_content_area().pack_start(self.notebook, True, True, 0)
self.results_text = Gtk.TextView()
self.results_text.connect('button-press-event',
+1 -1
View File
@@ -286,7 +286,7 @@ class ExportAssistant(ManagedWindow, Gtk.Assistant):
self.set_page_complete(vbox, True)
def create_page_fileselect(self):
self.chooser = Gtk.FileChooserWidget(Gtk.FileChooserAction.SAVE)
self.chooser = Gtk.FileChooserWidget(action=Gtk.FileChooserAction.SAVE)
self.chooser.set_homogeneous(False) # Fix for bug #8350.
#add border
self.chooser.set_border_width(12)
+16 -11
View File
@@ -164,9 +164,9 @@ class WriterOptionBox:
full_database_row.pack_start(label, True, True, 0)
people_count = len(self.dbstate.db.get_person_handles())
# translators: leave all/any {...} untranslated
button = Gtk.Button(ngettext("{number_of} Person",
"{number_of} People", people_count
).format(number_of=people_count) )
button = Gtk.Button(label=ngettext("{number_of} Person",
"{number_of} People", people_count
).format(number_of=people_count))
button.set_tooltip_text(_("Click to see preview of unfiltered data"))
button.set_size_request(107, -1)
button.connect("clicked", self.show_preview_data)
@@ -271,9 +271,9 @@ class WriterOptionBox:
from gi.repository import Gtk
from ...widgets import SimpleButton
# translators: leave all/any {...} untranslated
button = Gtk.Button(ngettext("{number_of} Person",
"{number_of} People", 0
).format(number_of=0) )
button = Gtk.Button(label=ngettext("{number_of} Person",
"{number_of} People", 0
).format(number_of=0))
button.set_size_request(107, -1)
button.connect("clicked", self.show_preview_data)
button.proxy_name = proxy_name
@@ -283,7 +283,8 @@ class WriterOptionBox:
label = Gtk.Label(label=_('_Person Filter') + COLON)
label.set_halign(Gtk.Align.START)
label.set_size_request(120, -1)
label.set_padding(5, 0)
label.set_margin_start(5)
label.set_margin_end(5)
label.set_use_underline(True)
label.set_mnemonic_widget(self.filter_obj)
box = Gtk.Box()
@@ -301,7 +302,8 @@ class WriterOptionBox:
label_note = Gtk.Label(label=_('_Note Filter') + COLON)
label_note.set_halign(Gtk.Align.START)
label_note.set_size_request(120, -1)
label_note.set_padding(5, 0)
label_note.set_margin_start(5)
label_note.set_margin_end(5)
label_note.set_use_underline(True)
label_note.set_mnemonic_widget(self.filter_note)
box = Gtk.Box()
@@ -317,7 +319,8 @@ class WriterOptionBox:
label = Gtk.Label(label=_("Privacy Filter") + COLON)
label.set_halign(Gtk.Align.START)
label.set_size_request(120, -1)
label.set_padding(5, 0)
label.set_margin_start(5)
label.set_margin_end(5)
box = Gtk.Box()
box.pack_start(label, False, True, 0)
box.add(self.private_check)
@@ -327,7 +330,8 @@ class WriterOptionBox:
label = Gtk.Label(label=_("Living Filter") + COLON)
label.set_halign(Gtk.Align.START)
label.set_size_request(120, -1)
label.set_padding(5, 0)
label.set_margin_start(5)
label.set_margin_end(5)
box = Gtk.Box()
box.pack_start(label, False, True, 0)
self.restrict_option = Gtk.ComboBox()
@@ -339,7 +343,8 @@ class WriterOptionBox:
label = Gtk.Label(label=_('Reference Filter') + COLON)
label.set_halign(Gtk.Align.START)
label.set_size_request(120, -1)
label.set_padding(5, 0)
label.set_margin_start(5)
label.set_margin_end(5)
box = Gtk.Box()
box.pack_start(label, False, True, 0)
box.pack_start(self.reference_filter, True, True, 0)
+5 -7
View File
@@ -58,13 +58,11 @@ class FileEntry(Gtk.Box):
else:
my_action = Gtk.FileChooserAction.SAVE
dialog = Gtk.FileChooserDialog(self.title,
self.parent,
action=my_action,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Open'),
Gtk.ResponseType.OK))
dialog = Gtk.FileChooserDialog(title=self.title,
transient_for=self.parent,
action=my_action)
dialog.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Open'), Gtk.ResponseType.OK)
name = os.path.basename(self.entry.get_text())
if self.dir:
+2 -1
View File
@@ -175,7 +175,8 @@ class PaperFrame(Gtk.Box):
self.paper_grid.show_all()
# Shift the grid from glade toplevel window to this box
self.paper_grid.reparent(self)
self.paper_grid.get_parent().remove(self.paper_grid)
self.add(self.paper_grid)
# need to get rid of glade toplevel now that we are done with it.
self.top.destroy()
+1 -1
View File
@@ -414,7 +414,7 @@ class StyleEditor(ManagedWindow):
spin.set_value(t.get_column_width(i))
self.column.append(spin)
hbox.pack_start(spin, False, False, 6)
hbox.pack_start(Gtk.Label('%'), False, False, 6)
hbox.pack_start(Gtk.Label(label='%'), False, False, 6)
hbox.show_all()
self.vbox.pack_start(hbox, False, False, 3)
+5 -4
View File
@@ -551,16 +551,17 @@ def color_graph_box(alive=False, gender=Person.MALE):
def hex_to_rgb_float(value):
"""
Convert a hexademical value #FF00FF to rgb. Returns tuple of float between
0 and 1
Convert a 6 or 12 digit hexademical value to rgb. Returns tuple of floats
between 0 and 1.
"""
value = value.lstrip('#')
lenv = len(value)
return tuple(int(value[i:i+lenv//3], 16)/256.0 for i in range(0, lenv, lenv//3))
return tuple(int(value[i:i+lenv//3], 16)/16.0**(lenv//3)
for i in range(0, lenv, lenv//3))
def hex_to_rgb(value):
"""
Convert a hexadecimal value #FF00FF to rgb. Returns tuple of integers
Convert a 6 or 12 digit hexadecimal value to rgb. Returns tuple of integers.
"""
value = value.lstrip('#')
lenv = len(value)
+7 -9
View File
@@ -1649,9 +1649,9 @@ class QuickBackup(ManagedWindow): # TODO move this class into its own module
self.user = user
ManagedWindow.__init__(self, uistate, [], self.__class__)
window = Gtk.Dialog('',
self.uistate.window,
Gtk.DialogFlags.DESTROY_WITH_PARENT, None)
window = Gtk.Dialog(title='',
transient_for=self.uistate.window,
destroy_with_parent=True)
self.set_window(window, None, _("Gramps XML Backup"))
self.setup_configs('interface.quick-backup', 500, 150)
close_button = window.add_button(_('_Close'),
@@ -1787,12 +1787,10 @@ class QuickBackup(ManagedWindow): # TODO move this class into its own module
"""
fdialog = Gtk.FileChooserDialog(
title=_("Select backup directory"),
parent=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Apply'),
Gtk.ResponseType.OK))
transient_for=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER)
fdialog.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Apply'), Gtk.ResponseType.OK)
mpath = path_entry.get_text()
if not mpath:
mpath = HOME_DIR
+1 -1
View File
@@ -269,7 +269,7 @@ class BookmarksDialog(ManagedWindow):
def draw_window(self):
"""Draw the bookmark dialog box."""
self.top = Gtk.Dialog(parent=self.parent_window)
self.top = Gtk.Dialog(transient_for=self.parent_window)
self.top.vbox.set_spacing(5)
label = Gtk.Label(label='<span size="larger" weight="bold">%s</span>'
% _("Organize Bookmarks"))
+5 -5
View File
@@ -1059,11 +1059,11 @@ class ListView(NavigationView):
####################################################################
def export(self, *obj):
chooser = Gtk.FileChooserDialog(
_("Export View as Spreadsheet"),
self.uistate.window,
Gtk.FileChooserAction.SAVE,
(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Save'), Gtk.ResponseType.OK))
title=_("Export View as Spreadsheet"),
transient_for=self.uistate.window,
action=Gtk.FileChooserAction.SAVE)
chooser.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Save'), Gtk.ResponseType.OK)
chooser.set_do_overwrite_confirmation(True)
combobox = Gtk.ComboBoxText()
+10 -13
View File
@@ -331,7 +331,8 @@ class NavigationView(PageView):
"""
A dialog to move to a Gramps ID entered by the user.
"""
dialog = Gtk.Dialog(_('Jump to by Gramps ID'), self.uistate.window)
dialog = Gtk.Dialog(title=_('Jump to by Gramps ID'),
transient_for=self.uistate.window)
dialog.set_border_width(12)
label = Gtk.Label(label='<span weight="bold" size="larger">%s</span>' %
_('Jump to by Gramps ID'))
@@ -434,19 +435,15 @@ class NavigationView(PageView):
hobj = self.get_history()
menu_len = min(len(items) - 1, MRU_SIZE)
for index in range(0, menu_len):
name, obj = navigation_label(self.dbstate.db, nav_type,
items[index])
menus += menuitem % (nav_type, index, html.escape(name))
self.mru_ui = [MRU_TOP + menus + MRU_BTM]
mitems = items[-MRU_SIZE - 1:-1] # Ignore current handle
mitems.reverse()
data = []
for index, handle in enumerate(mitems):
data.append(('%s%02d'%(nav_type, index),
make_callback(hobj.push, handle),
"%s%d" % (mod_key(), index)))
for index in range(menu_len - 1, -1, -1):
name, _obj = navigation_label(self.dbstate.db, nav_type,
items[index])
menus += menuitem % (nav_type, index, html.escape(name))
data.append(('%s%02d' % (nav_type, index),
make_callback(hobj.push, items[index]),
"%s%d" % (mod_key(), menu_len - 1 - index)))
self.mru_ui = [MRU_TOP + menus + MRU_BTM]
self.mru_action = ActionGroup(name=self.title + '/MRU')
self.mru_action.add_actions(data)
+33 -4
View File
@@ -241,14 +241,21 @@ class Tags(DbGUIElement):
tag_menu = ''
menuitem = '''
<item>
<attribute name="action">win.TAG-%s</attribute>
<attribute name="action">win.%s</attribute>
<attribute name="label">%s</attribute>
</item>'''
for tag_name, handle in self.__tag_list:
tag_menu += menuitem % (handle, escape(tag_name))
tag_menu += menuitem % ("TAG-%s" % handle,
"Add tag '%s'" % tag_name)
actions.append(('TAG-%s' % handle,
make_callback(self.tag_selected_rows, handle)))
for tag_name, handle in self.__tag_list:
tag_menu += menuitem % ("R-TAG-%s" % handle,
"Remove tag '%s'" % tag_name)
actions.append(('R-TAG-%s' % handle,
make_callback(self.remove_tag_selected_rows,
handle)))
tag_menu = TAG_MENU % tag_menu
self.tag_ui = [TAG_1 % tag_menu, TAG_2, TAG_3 % tag_menu]
@@ -315,6 +322,28 @@ class Tags(DbGUIElement):
view.add_tag(trans, object_handle, tag_handle)
status.end()
def remove_tag_selected_rows(self, tag_handle):
"""
Remove tag from selected rows.
"""
view = self.uistate.viewmanager.active_page
selected = view.selected_handles()
# Make the dialog modal so that the user can't start another
# database transaction while the one setting tags is still running.
pmon = progressdlg.ProgressMonitor(progressdlg.GtkProgressDialog,
("", self.uistate.window, Gtk.DialogFlags.MODAL), popup_time=2)
status = progressdlg.LongOpStatus(msg=_("Adding Tags"),
total_steps=len(selected),
interval=len(selected)//20)
pmon.add_op(status)
tag = self.db.get_tag_from_handle(tag_handle)
msg = _('Tag Selection (%s)') % tag.get_name()
with DbTxn(msg, self.db) as trans:
for object_handle in selected:
status.heartbeat()
view.remove_tag(trans, object_handle, tag_handle)
status.end()
def cb_menu_position(*args):
"""
Determine the position of the popup menu.
@@ -430,7 +459,7 @@ class OrganizeTagsDialog(ManagedWindow):
Create a dialog box to organize tags.
"""
# pylint: disable-msg=E1101
top = Gtk.Dialog(parent=self.parent_window)
top = Gtk.Dialog(transient_for=self.parent_window)
top.vbox.set_spacing(5)
label = Gtk.Label(label='<span size="larger" weight="bold">%s</span>'
% _("Organize Tags"))
@@ -659,7 +688,7 @@ class EditTag(ManagedWindow):
Create a dialog box to enter a new tag.
"""
# pylint: disable-msg=E1101
top = Gtk.Dialog(parent=self.parent_window)
top = Gtk.Dialog(transient_for=self.parent_window)
top.vbox.set_spacing(5)
hbox = Gtk.Box()
+2 -2
View File
@@ -143,7 +143,7 @@ class PlaceBaseModel:
value = conv_lat_lon('0', data[3], format='DEG')[1]
if not value:
return _("Error in format")
return value
return ("\u202d" + value + "\u202e") if glocale.rtl_locale else value
def column_latitude(self, data):
if not data[4]:
@@ -151,7 +151,7 @@ class PlaceBaseModel:
value = conv_lat_lon(data[4], '0', format='DEG')[0]
if not value:
return _("Error in format")
return value
return ("\u202d" + value + "\u202e") if glocale.rtl_locale else value
def sort_longitude(self, data):
if not data[3]:
+7 -8
View File
@@ -630,13 +630,11 @@ class DetachedWindow(ManagedWindow):
self.grampletbar = grampletbar
self.gramplet = gramplet
ManagedWindow.__init__(self, gramplet.uistate, [],
self.title)
self.set_window(Gtk.Dialog("", gramplet.uistate.window,
Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_Close'), Gtk.ResponseType.CLOSE)),
None,
self.title)
ManagedWindow.__init__(self, gramplet.uistate, [], self.title)
dlg = Gtk.Dialog(transient_for=gramplet.uistate.window,
destroy_with_parent = True)
dlg.add_button(_('_Close'), Gtk.ResponseType.CLOSE)
self.set_window(dlg, None, self.title)
self.window.move(x_pos, y_pos)
self.window.set_default_size(gramplet.detached_width,
gramplet.detached_height)
@@ -701,7 +699,8 @@ class DetachedWindow(ManagedWindow):
self.gramplet.detached_width = size[0]
self.gramplet.detached_height = size[1]
self.gramplet.detached_window = None
self.gramplet.reparent(self.grampletbar)
self.notebook.remove(self.gramplet)
self.grampletbar.add(self.gramplet)
ManagedWindow.close(self, *args)
#-------------------------------------------------------------------------
+9 -8
View File
@@ -233,12 +233,11 @@ class GrampletWindow(ManagedWindow):
self.docked_state = gramplet.gstate
# Now detach it
self.gramplet.set_state("detached")
ManagedWindow.__init__(self, gramplet.uistate, [],
self.title)
self.set_window(Gtk.Dialog("", gramplet.uistate.window,
Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_Close'), Gtk.ResponseType.CLOSE)),
None, self.title)
ManagedWindow.__init__(self, gramplet.uistate, [], self.title)
dlg = Gtk.Dialog(transient_for=gramplet.uistate.window,
destroy_with_parent=True)
dlg.add_button(_('_Close'), Gtk.ResponseType.CLOSE)
self.set_window(dlg, None, self.title)
cfg_name = gramplet.gname.replace(' ', '').lower() + '-gramplet'
self.setup_configs('interface.' + cfg_name,
gramplet.detached_width, gramplet.detached_height)
@@ -246,7 +245,8 @@ class GrampletWindow(ManagedWindow):
# add gramplet:
if self.gramplet.pui:
self.gramplet.pui.active = True
self.gramplet.mainframe.reparent(self.window.vbox)
self.gramplet.mainframe.get_parent().remove(self.gramplet.mainframe)
self.window.vbox.add(self.gramplet.mainframe)
self.window.connect('response', self.handle_response)
self.show()
# After we show, then we hide:
@@ -310,7 +310,8 @@ class GrampletWindow(ManagedWindow):
expand = self.gramplet.gstate == "maximized" and self.gramplet.expand
column = pane.columns[col]
parent = self.gramplet.pane.get_column_frame(self.gramplet.column)
self.gramplet.mainframe.reparent(parent)
self.gramplet.mainframe.get_parent().remove(self.gramplet.mainframe)
parent.add(self.gramplet.mainframe)
if self.gramplet.pui:
self.gramplet.pui.active = self.gramplet.pane.pageview.active
for gframe in stack:
+7 -19
View File
@@ -18,7 +18,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
__all__ = ["LinkLabel", "EditLabel", "BasicLabel", "GenderLabel",
__all__ = ["LinkLabel", "EditLabel", "BasicLabel",
"MarkupLabel", "DualMarkupLabel"]
#-------------------------------------------------------------------------
@@ -127,7 +127,7 @@ class LinkLabel(Gtk.EventBox):
hbox = Gtk.Box()
hbox.pack_start(self.label, False, False, 0)
if label[1]:
hbox.pack_start(GenderLabel(label[1]), False, False, 0)
hbox.pack_start(Gtk.Label(label=label[1]), False, False, 0)
hbox.set_spacing(4)
self.add(hbox)
@@ -138,7 +138,10 @@ class LinkLabel(Gtk.EventBox):
self.connect('realize', realize_cb)
def set_padding(self, x, y):
self.label.set_padding(x, y)
self.label.set_margin_start(x)
self.label.set_margin_end(x)
self.label.set_margin_top(x)
self.label.set_margin_bottom(x)
def enter_text(self, obj, event, handle):
if self.emph:
@@ -205,20 +208,6 @@ class BasicLabel(Gtk.Label):
self.set_ellipsize(ellipsize)
self.show()
#-------------------------------------------------------------------------
#
# GenderLabel class
#
#-------------------------------------------------------------------------
class GenderLabel(Gtk.Label):
def __init__(self, text):
Gtk.Label.__init__(self, label=text)
self.set_halign(Gtk.Align.START)
if win():
pangoFont = Pango.FontDescription('Arial')
self.override_font(pangoFont)
self.show()
#-------------------------------------------------------------------------
#
@@ -247,7 +236,6 @@ class DualMarkupLabel(Gtk.Box):
label.set_use_markup(True)
self.pack_start(label, False, False, 0)
b = GenderLabel(alt)
b.set_use_markup(True)
b = Gtk.Label(label=alt)
self.pack_start(b, False, False, 4)
self.show()
+3 -37
View File
@@ -64,8 +64,6 @@ from gramps.gen.errors import ValidationError
_RETURN = Gdk.keyval_from_name("Return")
_KP_ENTER = Gdk.keyval_from_name("KP_Enter")
# table for skipping illegal control chars
INVISIBLE = dict.fromkeys(list(range(32)))
#-------------------------------------------------------------------------
#
@@ -141,14 +139,10 @@ class MonitoredEntry:
self.obj.connect(signal, callback, *data)
def _on_quit(self, obj, event):
text = obj.get_text().translate(INVISIBLE).strip()
self.set_val(text)
obj.set_text(text)
self.set_val(obj.get_text().strip())
def _on_change(self, obj):
new_text = obj.get_text().translate(INVISIBLE)
self.set_val(new_text)
obj.set_text(new_text)
self.set_val(obj.get_text())
if self.changed:
self.changed(obj)
@@ -183,36 +177,8 @@ class MonitoredEntryIndicator(MonitoredEntry):
autolist=None, changed=None):
MonitoredEntry.__init__(self, obj, set_val, get_val, read_only,
autolist, changed)
self.origcolor = obj.get_style_context().get_color(Gtk.StateType.NORMAL)
if get_val():
self.indicatorshown = False
else:
self.indicatorshown = True
self.indicator = indicator
self.obj.set_text(indicator)
rgba = Gdk.RGBA()
Gdk.RGBA.parse(rgba, 'grey')
self.obj.override_color(Gtk.StateType.NORMAL, rgba)
self.obj.override_font(Pango.FontDescription('sans italic'))
self.fockey = self.obj.connect('focus-in-event',
self._obj_focus)
self.obj.set_placeholder_text(indicator)
def _on_change(self, obj):
if not self.indicatorshown:
self.set_val(str(obj.get_text()))
if self.changed:
self.changed(obj)
def _obj_focus(self, widg, eve):
"""
callback for when prefix obtains focus
"""
self.set_text('')
self.obj.override_color(Gtk.StateType.NORMAL, self.origcolor)
self.obj.override_font(Pango.FontDescription('normal'))
self.obj.disconnect(self.fockey)
self.indicatorshown = False
return False
#-------------------------------------------------------------------------
#
-1
View File
@@ -84,7 +84,6 @@ class Photo(Gtk.EventBox):
elif is_right_click(event):
if self.handle and self.uistate:
self.menu = Gtk.Menu()
self.menu.set_title(_("Media Object"))
add_menuitem(self.menu, _("Make Active Media"), widget,
lambda obj: self.uistate.set_active(self.handle, "Media"))
self.menu.popup(None, None, None, None, event.button, event.time)
+2 -2
View File
@@ -26,7 +26,7 @@
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GdkPixbuf
from gi.repository import GObject
from gi.repository import GLib, GObject
#-------------------------------------------------------------------------
#
@@ -305,7 +305,7 @@ class SelectionWidget(Gtk.ScrolledWindow):
viewport_size.height)
self._rescale()
self.loaded = True
except (GObject.GError, OSError):
except (GLib.GError, OSError):
self.show_missing()
def show_missing(self):
+100 -29
View File
@@ -46,6 +46,11 @@ from gi.repository import Gtk
#
#-------------------------------------------------------------------------
from .undoablebuffer import Stack
from gramps.gen.const import GRAMPS_LOCALE as glocale
# table for skipping illegal control chars
INVISIBLE = dict.fromkeys(list(range(32)) + [0x202d, 0x202e])
class UndoableInsertEntry:
"""something that has been inserted into our Gtk.editable"""
@@ -84,6 +89,10 @@ class UndoableEntry(Gtk.Entry, Gtk.Editable):
Additional features:
- Undo and Redo on CTRL-Z/CTRL-SHIFT-Z
- ltr_mode (forces the field to always be left to right, useful for GPS
coordinates and similar numbers that might contain RTL characters.
See set_ltr_mode.
"""
__gtype_name__ = 'UndoableEntry'
@@ -94,12 +103,12 @@ class UndoableEntry(Gtk.Entry, Gtk.Editable):
undo_stack_size = 50
def __init__(self):
Gtk.Entry.__init__(self)
self.undo_stack = Stack(self.undo_stack_size)
self.redo_stack = []
self.not_undoable_action = False
self.undo_in_progress = False
self.ltr_mode = False
Gtk.Entry.__init__(self)
self.connect('delete-text', self._on_delete_text)
self.connect('key-press-event', self._on_key_press_event)
@@ -156,10 +165,17 @@ class UndoableEntry(Gtk.Entry, Gtk.Editable):
return False
return True
text = text.translate(INVISIBLE)
if self.ltr_mode:
if position == 0:
position = 1
elif position >= self.get_text_length():
position -= 1
if not self.undo_in_progress:
self.__empty_redo_stack()
while not self.not_undoable_action:
undo_action = self.insertclass(text, length, self.get_position())
undo_action = self.insertclass(text, length, position)
try:
prev_insert = self.undo_stack.pop()
except IndexError:
@@ -180,6 +196,7 @@ class UndoableEntry(Gtk.Entry, Gtk.Editable):
self.get_buffer().insert_text(position, text, len(text))
return position + len(text)
def _on_delete_text(self, editable, start, end):
def can_be_merged(prev, cur):
"""
@@ -206,32 +223,49 @@ class UndoableEntry(Gtk.Entry, Gtk.Editable):
return False
return True
if not self.undo_in_progress:
self.__empty_redo_stack()
if self.not_undoable_action:
return
undo_action = self.deleteclass(editable, start, end)
try:
prev_delete = self.undo_stack.pop()
except IndexError:
self.undo_stack.append(undo_action)
return
if not isinstance(prev_delete, self.deleteclass):
self.undo_stack.append(prev_delete)
self.undo_stack.append(undo_action)
return
if can_be_merged(prev_delete, undo_action):
if prev_delete.start == undo_action.start: # delete key used
prev_delete.text += undo_action.text
prev_delete.end += (undo_action.end - undo_action.start)
else: # Backspace used
prev_delete.text = "%s%s" % (undo_action.text,
prev_delete.text)
prev_delete.start = undo_action.start
self.undo_stack.append(prev_delete)
else:
self.undo_stack.append(prev_delete)
self.undo_stack.append(undo_action)
if self.ltr_mode: # limit deletes to area between LRO/PDF
if start == 0:
start = 1
elif start > self.get_text_length() - 1:
start -= 1
if end == 0:
end = 1
elif end > self.get_text_length() - 1:
end -= 1
elif end < 0:
end = self.get_text_length() - 1
while True:
if not self.undo_in_progress:
self.__empty_redo_stack()
if self.not_undoable_action:
break
undo_action = self.deleteclass(self, start, end)
try:
prev_delete = self.undo_stack.pop()
except IndexError:
self.undo_stack.append(undo_action)
break
if not isinstance(prev_delete, self.deleteclass):
self.undo_stack.append(prev_delete)
self.undo_stack.append(undo_action)
break
if can_be_merged(prev_delete, undo_action):
if prev_delete.start == undo_action.start: # delete key used
prev_delete.text += undo_action.text
prev_delete.end += (undo_action.end - undo_action.start)
else: # Backspace used
prev_delete.text = "%s%s" % (undo_action.text,
prev_delete.text)
prev_delete.start = undo_action.start
self.undo_stack.append(prev_delete)
else:
self.undo_stack.append(prev_delete)
self.undo_stack.append(undo_action)
break
self.get_buffer().delete_text(start, end - start)
self.stop_emission_by_name('delete-text')
return True
def begin_not_undoable_action(self):
"""don't record the next actions
@@ -323,3 +357,40 @@ class UndoableEntry(Gtk.Entry, Gtk.Editable):
def _handle_redo(self, redo_action):
raise NotImplementedError
def set_ltr_mode(self):
""" sets up the Entry to always be in LTR left to right even if some
characters are RTL.
This works by inserting the LRO/PDF Unicode Explicit Directional
Override characters around the entry text. These characters are then
protected agains insert/delete operations.
This call must be made before other text is inserted to the Entry.
Note: we only enable this during rtl_local languages because it has a
minor consequence; if cutting a field from this Entry with this mode
enabled, the LRO/PDF characters may end up in the clipboard. If pasted
back into another UndoableEntry, this is ignored, but if pasted in
another app it may be noticable.
"""
if glocale.rtl_locale:
self.get_buffer().set_text("\u202d\u202e", -1)
self.ltr_mode = True
def do_set_position(self, position):
""" In ltr_mode, this ensures that the cursor cannot be put outside
the LRO/PDF characters on the ends of the buffer. """
if position < 0:
position = self.get_text_length()
if self.ltr_mode:
if position == 0:
position = 1
elif position == self.get_text_length():
position -= 1
Gtk.Editable.select_region(self, position, position)
def get_text(self):
""" Used to remove the LRO/PDF characters when in ltr_mode.
"""
text = Gtk.Entry.get_text(self)
return text[1:-1] if self.ltr_mode else text
+8 -4
View File
@@ -191,7 +191,7 @@ class MaskedEntry(UndoableEntry):
:param mask: the mask to set
"""
if not mask:
self.override_font(Pango.FontDescription("sans"))
# self.override_font(Pango.FontDescription("sans"))
self._mask = mask
return
@@ -221,7 +221,9 @@ class MaskedEntry(UndoableEntry):
pos += 1
self._mask_fields.append((field_begin, field_end))
self.override_font(Pango.FontDescription("monospace"))
# The set_mask function doesn't seem to be used, except for the test
# so removing the monospace doesn't change visible functionality
# self.override_font(Pango.FontDescription("monospace"))
self._really_delete_text(0, -1)
self._insert_mask(0, input_length)
@@ -940,6 +942,8 @@ VALIDATION_ICON_WIDTH = 16
MANDATORY_ICON = 'dialog-information'
ERROR_ICON = 'process-stop'
DELAY_TIME = 2500
READWRITE = (GObject.PARAM_READWRITE if GLib.check_version(2, 42, 0) else
GObject.ParamFlags.READWRITE)
class ValidatableMaskedEntry(MaskedEntry):
"""
@@ -969,12 +973,12 @@ class ValidatableMaskedEntry(MaskedEntry):
'data-type': (GObject.TYPE_PYOBJECT,
'Data Type of the widget',
'Type object',
GObject.PARAM_READWRITE),
READWRITE),
'mandatory': (GObject.TYPE_BOOLEAN,
'Mandatory',
'Mandatory',
False,
GObject.PARAM_READWRITE),
READWRITE),
}
# FIXME put the data type support back
+1
View File
@@ -81,6 +81,7 @@ class DbTest(unittest.TestCase):
"get_number_of_places",
"get_number_of_repositories",
"get_number_of_sources",
"get_number_of_citations",
"get_number_of_tags",
"get_media_from_gramps_id",
"get_media_from_handle",
+1 -1
View File
@@ -1541,7 +1541,7 @@ class ODFDoc(BaseDoc, TextDoc, DrawDoc):
Insert a mark at this point in the document.
"""
if mark:
key = escape(mark.key, ESC_MAP)
key = escape(mark.key)
key = key.replace('"', '&quot;')
if mark.type == INDEX_TYPE_ALP:
self.cntnt.write(
+59 -51
View File
@@ -42,7 +42,6 @@ from gramps.gen.plug.menu import (TextOption, NumberOption, BooleanOption,
EnumeratedListOption, StringOption,
PersonOption)
from gramps.gen.plug.report import Report, MenuReportOptions, stdoptions
from gramps.gen.plug.report import utils
from gramps.gen.plug.docgen import (FontStyle, ParagraphStyle, GraphicsStyle,
FONT_SANS_SERIF, PARA_ALIGN_CENTER)
from gramps.plugins.lib.libtreebase import *
@@ -64,6 +63,7 @@ _MARR = _("marriage abbreviation|m."),
LVL_GEN, LVL_INDX, LVL_Y = range(3)
#------------------------------------------------------------------------
#
# Box classes
@@ -82,6 +82,7 @@ class PersonBox(BoxBase):
def __lt__(self, other):
return self.level[LVL_Y] < other.level[LVL_Y]
class FamilyBox(BoxBase):
"""
Calculates information about the box that will print on a page
@@ -114,6 +115,7 @@ class TitleN(TitleNoDisplay):
self.mark_text = self._("Ancestor Graph")
self.text = ''
class TitleA(TitleBox):
"""Title class for the report """
def __init__(self, doc, locale, name_displayer):
@@ -172,31 +174,32 @@ class CalcItems:
def calc_person(self, index, indi_handle, fams_handle):
working_lines = ""
if index[1] % 2 == 0 or (index[1] == 1 and self.center_use == 0):
if indi_handle == fams_handle == None:
if indi_handle == fams_handle is None:
working_lines = self.__calc_l.calc_lines(
None, None, self._gui.get_val("father_disp"))
else:
working_lines = self.disp_father
else:
if indi_handle == fams_handle == None:
if indi_handle == fams_handle is None:
working_lines = self.__calc_l.calc_lines(
None, None, self._gui.get_val("mother_disp"))
else:
working_lines = self.disp_mother
if indi_handle == fams_handle == None:
if indi_handle == fams_handle is None:
return working_lines
else:
return self.__calc_l.calc_lines(indi_handle, fams_handle,
working_lines)
def calc_marriage(self, indi_handle, fams_handle):
if indi_handle == fams_handle == None:
if indi_handle == fams_handle is None:
return self.__blank_marriage
else:
return self.__calc_l.calc_lines(indi_handle, fams_handle,
self.disp_marr)
class MakeAncestorTree(AscendPerson):
"""
The main procedure to use recursion to make the tree based off of a person.
@@ -223,9 +226,9 @@ class MakeAncestorTree(AscendPerson):
""" Makes a person box and add that person into the Canvas. """
#print str(index) + " add_person " + str(indi_handle)
myself = PersonBox((index[0]-1,) + index[1:])
myself = PersonBox((index[0] - 1,) + index[1:])
if index[LVL_GEN] == 1: #Center Person
if index[LVL_GEN] == 1: # Center Person
self.center_family = fams_handle
if index[LVL_GEN] > self.max_generation:
@@ -235,7 +238,7 @@ class MakeAncestorTree(AscendPerson):
indi_handle, fams_handle)
# myself.text[0] = myself.text[0] + ' ' + repr(index) # for debugging
if indi_handle is not None: # None is legal for an empty box
if indi_handle is not None: # None is legal for an empty box
myself.add_mark(self.database,
self.database.get_person_from_handle(indi_handle))
@@ -245,12 +248,12 @@ class MakeAncestorTree(AscendPerson):
indx = index[LVL_GEN]
self.lines[indx] = myself
if indx > 1:
if self.lines[indx-1].line_to is None:
line = LineBase(self.lines[indx-1])
self.lines[indx-1].line_to = line
if self.lines[indx - 1].line_to is None:
line = LineBase(self.lines[indx - 1])
self.lines[indx - 1].line_to = line
self.canvas.add_line(line)
else:
line = self.lines[indx-1].line_to
line = self.lines[indx - 1].line_to
line.add_to(myself)
return myself
@@ -264,7 +267,7 @@ class MakeAncestorTree(AscendPerson):
if not self.inlc_marr:
return
myself = FamilyBox((index[0]-1,) + index[1:])
myself = FamilyBox((index[0] - 1,) + index[1:])
#calculate the text.
myself.text = self.calc_items.calc_marriage(indi_handle, fams_handle)
@@ -280,7 +283,7 @@ class MakeAncestorTree(AscendPerson):
tmp_y = index - (2**x_level)
#Calculate which row in the table (yes table) of people.
delta = (2**self.max_generation) // (2**(x_level))
return int((delta/2) + (tmp_y*delta)) -1
return int((delta / 2) + (tmp_y * delta)) - 1
def do_y_indx(self):
''' Make the y_index for all boxes
@@ -292,8 +295,8 @@ class MakeAncestorTree(AscendPerson):
for box in self.canvas.boxes:
if "fam" in box.boxstr:
box.level = box.level + \
(self.y_index(box.level[LVL_GEN]-1,
int(box.level[LVL_INDX]/2)),)
(self.y_index(box.level[LVL_GEN] - 1,
int(box.level[LVL_INDX] / 2)),)
else:
box.level = box.level + \
(self.y_index(box.level[LVL_GEN], box.level[LVL_INDX]),)
@@ -304,10 +307,10 @@ class MakeAncestorTree(AscendPerson):
#Then there could be a gap. Remove this gap
if min_y > 0:
for box in self.canvas.boxes:
box.level = box.level[:LVL_Y] + (box.level[LVL_Y]-min_y,)
box.level = box.level[:LVL_Y] + (box.level[LVL_Y] - min_y,)
#Now that we have y_index, lets see if we need to squish the tree
self.canvas.boxes.sort() #Sort them on the y_index
self.canvas.boxes.sort() # Sort them on the y_index
if not self.compress_tree:
return
#boxes are already in top down [LVL_Y] form so lets
@@ -336,20 +339,19 @@ class MakeAncestorTree(AscendPerson):
line = center.line_to
level = center.level[LVL_Y]
move = level - (len(mykids)//2) + ((len(mykids)+1)%2)
move = level - (len(mykids) // 2) + ((len(mykids) + 1) % 2)
if move < 0:
# more kids than parents. ran off the page. Move them all down
for box in self.canvas.boxes:
box.level = (box.level[0], box.level[1], box.level[2]-move)
box.level = (box.level[0], box.level[1], box.level[2] - move)
move = 0
line.start = []
rrr = -1 # if len(mykids)%2 == 1 else 0
for kid in mykids:
rrr += 1
mee = self.add_person((1, 1, move+rrr), kid, self.center_family)
mee = self.add_person((1, 1, move + rrr), kid, self.center_family)
line.add_from(mee)
#mee.level = (0, 1, level - (len(mykids)//2)+rrr)
mee.line_to = line
@@ -387,7 +389,8 @@ class LRTransform:
def __init__(self, canvas, max_generations):
self.canvas = canvas
self.rept_opts = canvas.report_opts
self.y_offset = self.rept_opts.littleoffset*2 + self.canvas.title.height
self.y_offset = (self.rept_opts.littleoffset * 2 +
self.canvas.title.height)
def _place(self, box):
""" put the box in it's correct spot """
@@ -410,6 +413,7 @@ class LRTransform:
for box in self.canvas.boxes:
self._place(box)
#------------------------------------------------------------------------
#
# class make_report
@@ -441,7 +445,7 @@ class MakeReport:
self.canvas.set_box_height_width(box)
if box.width > self.canvas.report_opts.max_box_width:
self.canvas.report_opts.max_box_width = box.width #+ box.shadow
self.canvas.report_opts.max_box_width = box.width # + box.shadow
if box.level[LVL_Y] > 0:
if box.level[LVL_INDX] % 2 == 0 and box.height > self.father_ht:
@@ -456,7 +460,7 @@ class MakeReport:
return self.max_generations
def start(self):
## __gui = GUIConnect()
# __gui = GUIConnect()
# 1.
#set the sizes for each box and get the max_generations.
self.father_ht = 0.0
@@ -466,10 +470,10 @@ class MakeReport:
if self.compress_tree and not self.inlc_marr:
self.canvas.report_opts.max_box_height = \
min(self.father_ht, self.mother_ht)
min(self.father_ht, self.mother_ht)
else:
self.canvas.report_opts.max_box_height = \
max(self.father_ht, self.mother_ht)
max(self.father_ht, self.mother_ht)
#At this point we know everything we need to make the report.
#Size of each column of people - self.rept_opt.box_width
@@ -492,7 +496,8 @@ class GUIConnect:
"""
__shared_state = {}
def __init__(self): #We are BORG!
def __init__(self): # We are BORG!
self.__dict__ = self.__shared_state
def set__opts(self, options, locale, name_displayer):
@@ -533,6 +538,7 @@ class GUIConnect:
def compress_tree(self):
return self.get_val("compress_tree")
#------------------------------------------------------------------------
#
# AncestorTree
@@ -600,7 +606,7 @@ class AncestorTree(Report):
ReportOptions(self.doc, font_normal, 'AC2-line'))
self.canvas.report_opts.box_shadow *= \
self.connect.get_val('shadowscale')
self.connect.get_val('shadowscale')
self.canvas.report_opts.box_pgap *= self.connect.get_val('box_Yscale')
self.canvas.report_opts.box_mgap *= self.connect.get_val('box_Yscale')
@@ -608,7 +614,7 @@ class AncestorTree(Report):
_('Making the Tree...'), 4) as step:
#make the tree onto the canvas
## inlc_marr = self.connect.get_val("inc_marr")
# inlc_marr = self.connect.get_val("inc_marr")
self.max_generations = self.connect.get_val('maxgen')
tree = MakeAncestorTree(database, self.canvas)
tree.start(self.connect.get_val('pid'))
@@ -626,7 +632,7 @@ class AncestorTree(Report):
#make the report as big as it wants to be.
report = MakeReport(database, self.doc, self.canvas, font_normal)
report.start()
self.max_generations = report.get_generations() #already know
self.max_generations = report.get_generations() # already know
report = None
step()
@@ -670,8 +676,9 @@ class AncestorTree(Report):
colsperpage = self.doc.get_usable_width()
colsperpage += self.canvas.report_opts.col_width
colsperpage = int(colsperpage / (self.canvas.report_opts.max_box_width +
self.canvas.report_opts.col_width))
colsperpage = int(
colsperpage / (self.canvas.report_opts.max_box_width +
self.canvas.report_opts.col_width))
colsperpage = colsperpage or 1
#####################
@@ -761,6 +768,7 @@ class AncestorTree(Report):
self.doc.set_style_sheet(style_sheet)
#------------------------------------------------------------------------
#
# AncestorTreeOptions
@@ -853,8 +861,7 @@ class AncestorTreeOptions(MenuReportOptions):
self.scale.add_item(1, _("Scale tree to fit page width only"))
self.scale.add_item(2, _("Scale tree to fit the size of the page"))
self.scale.set_help(
_("Whether to scale the tree to fit a specific paper size")
)
_("Whether to scale the tree to fit a specific paper size"))
menu.add_option(category_name, "scale_tree", self.scale)
self.scale.connect('value-changed', self.__check_blank)
@@ -863,7 +870,7 @@ class AncestorTreeOptions(MenuReportOptions):
_("Resize Page to Fit Tree size\n"
"\n"
"Note: Overrides options in the 'Paper Option' tab"
),
),
False)
self.__onepage.set_help(
_("Whether to resize the page to fit the size \n"
@@ -880,7 +887,7 @@ class AncestorTreeOptions(MenuReportOptions):
"\n"
"With 'Scale tree to fit the size of the page' the page\n"
" is resized to remove any gap in either height or width"
))
))
menu.add_option(category_name, "resize_page", self.__onepage)
self.__onepage.connect('value-changed', self.__check_blank)
else:
@@ -910,8 +917,8 @@ class AncestorTreeOptions(MenuReportOptions):
disp = TextOption(_("Father\nDisplay Format"),
["$n",
"%s $b" %_BORN,
"-{%s $d}" %_DIED])
"%s $b" % _BORN,
"-{%s $d}" % _DIED])
disp.set_help(_("Display format for the fathers box."))
menu.add_option(category_name, "father_disp", disp)
@@ -925,9 +932,9 @@ class AncestorTreeOptions(MenuReportOptions):
disp_mom = TextOption(_("Mother\nDisplay Format"),
["$n",
"%s $b" %_BORN,
"%s $m" %_MARR,
"-{%s $d}" %_DIED])
"%s $b" % _BORN,
"%s $m" % _MARR,
"-{%s $d}" % _DIED])
disp_mom.set_help(_("Display format for the mothers box."))
menu.add_option(category_name, "mother_disp", disp_mom)
@@ -945,7 +952,7 @@ class AncestorTreeOptions(MenuReportOptions):
self.incmarr.connect('value-changed', self._incmarr_changed)
self.marrdisp = StringOption(_("Marriage\nDisplay Format"),
"%s $m" % _MARR)
"%s $m" % _MARR)
self.marrdisp.set_help(_("Display format for the marital box."))
menu.add_option(category_name, "marr_disp", self.marrdisp)
self._incmarr_changed()
@@ -964,7 +971,8 @@ class AncestorTreeOptions(MenuReportOptions):
# _('Include thumbnail images of people'), False)
# self.__include_images.set_help(
# _("Whether to include thumbnails of people."))
# menu.add_option(category_name, "includeImages", self.__include_images)
# menu.add_option(category_name, "includeImages",
# self.__include_images)
self.usenote = BooleanOption(_('Include a note'), False)
self.usenote.set_help(_("Whether to include a note on the report."))
@@ -991,7 +999,7 @@ class AncestorTreeOptions(MenuReportOptions):
menu.add_option(category_name, "box_Yscale", self.box_Y_sf)
self.box_shadow_sf = NumberOption(_("box shadow scale factor"),
1.00, 0.00, 2.00, 0.01) # down to 0
1.00, 0.00, 2.00, 0.01) # down to 0
self.box_shadow_sf.set_help(_("Make the box shadow bigger or smaller"))
menu.add_option(category_name, "shadowscale", self.box_shadow_sf)
@@ -1033,13 +1041,13 @@ class AncestorTreeOptions(MenuReportOptions):
for itr in range(2, max_gen))
self.fillout.set_items(item_list)
if old_val+2 > len(item_list):
self.fillout.set_value(len(item_list) -2)
if old_val + 2 > len(item_list):
self.fillout.set_value(len(item_list) - 2)
def make_default_style(self, default_style):
"""Make the default output style for the Ancestor Tree."""
## Paragraph Styles:
# Paragraph Styles:
font = FontStyle()
font.set_size(9)
font.set_type_face(FONT_SANS_SERIF)
@@ -1068,16 +1076,16 @@ class AncestorTreeOptions(MenuReportOptions):
para_style.set_description(_('The style used for the title.'))
default_style.add_paragraph_style("AC2-Title", para_style)
## Draw styles
# Draw styles
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("AC2-Normal")
graph_style.set_shadow(1, box_shadow) #shadow set by text size
graph_style.set_shadow(1, box_shadow) # shadow set by text size
graph_style.set_fill_color((255, 255, 255))
default_style.add_draw_style("AC2-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("AC2-Normal")
#graph_style.set_shadow(0, PT2CM(9)) #shadow set by text size
#graph_style.set_shadow(0, PT2CM(9)) # shadow set by text size
graph_style.set_fill_color((255, 255, 255))
default_style.add_draw_style("AC2-fam-box", graph_style)
+16 -9
View File
@@ -225,7 +225,10 @@ class TitleDPY(DescendantTitleBase):
center = self.database.get_person_from_gramps_id(person_id)
family2_h = center.get_main_parents_family_handle()
family2 = self.database.get_family_from_handle(family2_h)
if family2_h:
family2 = self.database.get_family_from_handle(family2_h)
else:
family2 = None
person_list = None
if family2:
@@ -270,8 +273,11 @@ class TitleDFY(DescendantTitleBase):
parent_list = None
family_h = person.get_main_parents_family_handle()
family = self.database.get_family_from_handle(family_h)
if family: #family = fathers parents
if family_h:
family = self.database.get_family_from_handle(family_h)
else:
family = None
if family: # family = fathers parents
father_h = family.get_father_handle()
mother_h = family.get_mother_handle()
parent_list = [self.database.get_person_from_handle(handle)
@@ -1814,30 +1820,31 @@ class DescendTreeOptions(MenuReportOptions):
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("CG2-Normal")
graph_style.set_fill_color((255, 255, 255))
graph_style.set_description(_("The style for the marriage box."))
default_style.add_draw_style("CG2-fam-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("CG2-Normal")
graph_style.set_shadow(1, box_shadow)
graph_style.set_fill_color((255, 255, 255))
graph_style.set_description(_("The style for the spouse box."))
default_style.add_draw_style("CG2-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("CG2-Bold")
graph_style.set_shadow(1, box_shadow)
graph_style.set_fill_color((255, 255, 255))
graph_style.set_description(
_("The style for the direct descendant box."))
default_style.add_draw_style("CG2b-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_paragraph_style("CG2-Note")
graph_style.set_fill_color((255, 255, 255))
graph_style.set_description(_("The style for the note box."))
default_style.add_draw_style("CG2-note-box", graph_style)
graph_style = GraphicsStyle()
graph_style.set_description(
_("The style for the connection lines and report border."))
default_style.add_draw_style("CG2-line", graph_style)
#=====================================
#So do not fear, for I am with you; do not be dismayed,
#for I am your God. I will strengthen you and help you;
#I will uphold you with my righteous right hand.
#Isaiah 41:10
+2 -1
View File
@@ -82,7 +82,8 @@ class FtreeWriter:
self.option_box.parse_options()
self.db = option_box.get_filtered_database(self.db)
self.plist = [x for x in self.db.iter_person_handles()]
self.plist = self.db.get_person_handles()
self.plist.sort()
# the following are used to update the progress meter
self.total = 2 * len(self.plist)
self.count = 0
+14 -13
View File
@@ -596,7 +596,7 @@ class GedcomWriter(UpdateCallback):
if val.strip():
self._writeln(2, 'TYPE', val)
else:
self._writeln(2, 'TYPE', str(event.get_type()))
self._writeln(2, 'TYPE', event.get_type().xml_str())
self._dump_event_stats(event, event_ref)
if etype == EventType.ADOPT and not adop_written:
adop_written = True
@@ -656,7 +656,7 @@ class GedcomWriter(UpdateCallback):
attr_type = int(attr.get_type())
name = libgedcom.PERSONALCONSTANTATTRIBUTES.get(attr_type)
key = str(attr.get_type())
key = attr.get_type().xml_str()
value = attr.get_value().strip().replace('\r', ' ')
if key in ("AFN", "RFN", "REFN", "_UID", "_FSFTID"):
@@ -735,14 +735,14 @@ class GedcomWriter(UpdateCallback):
child.mrel == ChildRefType.FOSTER:
self._writeln(2, 'PEDI foster')
elif child.frel == child.mrel:
self._writeln(2, 'PEDI %s' % str(child.frel))
self._writeln(2, 'PEDI %s' % child.frel.xml_str())
else:
self._writeln(2, '_FREL %s' %
PEDIGREE_TYPES.get(child.frel.value,
str(child.frel)))
self._writeln(2, '_MREL %s' %
PEDIGREE_TYPES.get(child.mrel.value,
str(child.mrel)))
self._writeln(
2, '_FREL %s' % PEDIGREE_TYPES.get(
child.frel.value, child.frel.xml_str()))
self._writeln(
2, '_MREL %s' % PEDIGREE_TYPES.get(
child.mrel.value, child.mrel.xml_str()))
def _parent_families(self, person):
"""
@@ -910,9 +910,9 @@ class GedcomWriter(UpdateCallback):
self._writeln(1, 'EVEN', descr)
else:
self._writeln(1, 'EVEN')
the_type = str(event.get_type())
the_type = event.get_type()
if the_type:
self._writeln(2, 'TYPE', the_type)
self._writeln(2, 'TYPE', the_type.xml_str())
def _family_event_attrs(self, attr_list, level):
"""
@@ -946,7 +946,7 @@ class GedcomWriter(UpdateCallback):
attr_type = int(attr.get_type())
name = libgedcom.FAMILYCONSTANTATTRIBUTES.get(attr_type)
key = str(attr.get_type())
key = attr.get_type().xml_str()
value = attr.get_value().replace('\r', ' ')
if key in ("AFN", "RFN", "REFN", "_UID"):
@@ -1097,7 +1097,8 @@ class GedcomWriter(UpdateCallback):
if reporef.get_call_number():
self._writeln(level + 1, 'CALN', reporef.get_call_number())
if reporef.get_media_type():
self._writeln(level + 2, 'MEDI', str(reporef.get_media_type()))
self._writeln(level + 2, 'MEDI',
reporef.get_media_type().xml_str())
def _person_event_ref(self, key, event_ref):
"""
+2 -1
View File
@@ -91,7 +91,8 @@ class GeneWebWriter:
self.dirname = os.path.dirname (self.filename)
try:
with open(self.filename, "wb") as self.g:
self.flist = [x for x in self.db.iter_family_handles()]
self.flist = self.db.get_family_handles()
self.flist.sort()
if len(self.flist) < 1:
self.user.notify_error(_("No families matched by selected filter"))
return False
+56 -58
View File
@@ -30,7 +30,7 @@
#-------------------------------------------------------------------------
import os
import sys
from time import localtime
import time
#------------------------------------------------------------------------
#
@@ -51,10 +51,10 @@ _ = glocale.translation.gettext
from gramps.gui.plug.export import WriterOptionBox
from gramps.gen.utils.db import family_name
from gramps.gen.lib import Date, EventType
from gramps.gui.glade import Glade
from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.display.place import displayer as _pd
class CalendarWriter:
def __init__(self, database, filename, user, option_box=None):
self.db = database
@@ -95,24 +95,27 @@ class CalendarWriter:
def export_data(self, filename):
self.dirname = os.path.dirname (filename)
self.dirname = os.path.dirname(filename)
try:
with open(filename,"w") as self.g:
with open(filename, "w", encoding='utf8',
newline='\r\n') as self.g:
self.writeln("BEGIN:VCALENDAR")
self.writeln("PRODID:-//GNU//Gramps//EN")
self.writeln("VERSION:1.0")
self.writeln("VERSION:2.0")
self.total = (len([x for x in self.db.iter_person_handles()]) +
len([x for x in self.db.iter_family_handles()]))
for key in self.db.iter_person_handles():
p_hndls = self.db.get_person_handles()
p_hndls.sort()
f_hndls = self.db.get_family_handles()
f_hndls.sort()
self.total = len(p_hndls) + len(f_hndls)
for key in p_hndls:
self.write_person(key)
self.update()
for key in self.db.iter_family_handles():
for key in f_hndls:
self.write_family(key)
self.update()
self.writeln("")
self.writeln("END:VCALENDAR")
return True
@@ -129,16 +132,11 @@ class CalendarWriter:
if family:
for event_ref in family.get_event_ref_list():
event = self.db.get_event_from_handle(event_ref.ref)
if event.get_type() == EventType.MARRIAGE:
m_date = event.get_date_object()
place_handle = event.get_place_handle()
if event and event.get_type() == EventType.MARRIAGE:
# feature requests 2356, 1657: avoid genitive form
text = "%s - %s" % (family_name(family, self.db), _("Marriage"))
if place_handle:
place_title = _pd.display_event(self.db, event)
self.write_vevent( text, m_date, place_title)
else:
self.write_vevent( text, m_date)
text = "%s - %s" % (family_name(family, self.db),
_("Marriage"))
self.write_vevent(text, event)
def write_person(self, person_handle):
person = self.db.get_person_from_handle(person_handle)
@@ -147,45 +145,26 @@ class CalendarWriter:
if birth_ref:
birth = self.db.get_event_from_handle(birth_ref.ref)
if birth:
b_date = birth.get_date_object()
place_handle = birth.get_place_handle()
if place_handle:
# feature requests 2356, 1657: avoid genitive form
place_title = _pd.display_event(self.db, birth)
self.write_vevent("%s - %s" %
(name_displayer.display(person), _("Birth")),
b_date, place_title)
else:
# feature requests 2356, 1657: avoid genitive form
self.write_vevent("%s - %s" %
(name_displayer.display(person), _("Birth")),
b_date)
# feature requests 2356, 1657: avoid genitive form
self.write_vevent("%s - %s" %
(name_displayer.display(person),
_("Birth")), birth)
death_ref = person.get_death_ref()
if death_ref:
death = self.db.get_event_from_handle(death_ref.ref)
if death:
d_date = death.get_date_object()
place_handle = death.get_place_handle()
if place_handle:
# feature requests 2356, 1657: avoid genitive form
place_title = _pd.display_event(self.db, death)
self.write_vevent("%s - %s" %
(name_displayer.display(person), _("Death")),
d_date, place_title)
else:
# feature requests 2356, 1657: avoid genitive form
self.write_vevent("%s - %s" %
(name_displayer.display(person), _("Death")),
d_date)
# feature requests 2356, 1657: avoid genitive form
self.write_vevent("%s - %s" %
(name_displayer.display(person),
_("Death")), death)
def format_single_date(self, subdate, thisyear, cal):
retval = ""
(day, month, year, sl) = subdate
if thisyear:
year = localtime().tm_year
year = time.localtime().tm_year
if not cal == Date.CAL_GREGORIAN:
return ""
@@ -196,7 +175,6 @@ class CalendarWriter:
retval = "%s%02d%02d" % (year, month, day)
return retval
def format_date(self, date, thisyear=0):
retval = ""
if date.get_modifier() == Date.MOD_TEXTONLY:
@@ -220,23 +198,43 @@ class CalendarWriter:
start)
return retval
def write_vevent(self, event_text, date, location=""):
def write_vevent(self, event_text, event):
date = event.get_date_object()
place_handle = event.get_place_handle()
date_string = self.format_date(date, 1)
if date_string is not "":
self.writeln("")
# self.writeln("")
self.writeln("BEGIN:VEVENT")
self.writeln("SUMMARY:%s %s" % (date.get_year(), event_text))
if location:
self.writeln("LOCATION:%s" % location)
time_s = time.gmtime(event.change)
self.writeln("DTSTAMP:%04d%02d%02dT%02d%02d%02dZ" % time_s[0:6])
self.writeln("UID:%s@gramps.com" % event.handle)
self.writeln(fold("SUMMARY:%s %s" % (date.get_year(), event_text)))
if place_handle:
location = _pd.display_event(self.db, event)
if location:
self.writeln("LOCATION:%s" % location)
self.writeln("RRULE:FREQ=YEARLY")
self.writeln(date_string)
self.writeln("END:VEVENT")
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
# -------------------------------------------------------------------------
def fold(txt):
""" Limit line length to 75 octets (per RFC 5545) """
l_len = 0
text = ''
for char in txt:
c_len = len(char.encode('utf8'))
if c_len + l_len > 75:
l_len = 1
text += '\n ' + char
else:
l_len += c_len
text += char
return text
def exportData(database, filename, user, option_box=None):
cw = CalendarWriter(database, filename, user, option_box)
return cw.export_data(filename)
+4 -4
View File
@@ -51,13 +51,13 @@ class AgeStatsGramplet(Gramplet):
def build_options(self):
from gramps.gen.plug.menu import NumberOption
self.add_option(NumberOption(_("Max age"),
self.max_age, 1, 150))
self.max_age, 5, 150, 5))
self.add_option(NumberOption(_("Max age of Mother at birth"),
self.max_mother_diff, 1, 150))
self.max_mother_diff, 5, 150, 5))
self.add_option(NumberOption(_("Max age of Father at birth"),
self.max_father_diff, 1, 150))
self.max_father_diff, 5, 150, 5))
self.add_option(NumberOption(_("Chart width"),
self.chart_width, 1, 150))
self.chart_width, 45, 150))
def save_options(self):
self.max_age = int(self.get_option(_("Max age")).get_value())
-1
View File
@@ -139,7 +139,6 @@ class GeoEvents(Gramplet, DbGUIElement):
"""
self.menu = Gtk.Menu()
menu = self.menu
menu.set_title(_('Edit'))
title = _('Edit the event')
add_item = Gtk.MenuItem(label=title)
add_item.connect("activate", self.edit_event, treeview)
@@ -70,7 +70,7 @@ class FanChart2WayGramplet(FanChart2WayGrampsGUI, Gramplet):
self.on_popup))
# Replace the standard textview with the fan chart widget:
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add_with_viewport(self.fan)
self.gui.get_container_widget().add(self.fan)
# Make sure it is visible:
self.fan.show()
+6 -5
View File
@@ -24,7 +24,7 @@
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
from gi.repository import Pango
from gi.repository.GLib import markup_escape_text
#-------------------------------------------------------------------------
#
@@ -61,7 +61,6 @@ class PersonDetails(Gramplet):
self.photo = Photo(self.uistate.screen_height() < 1000)
self.photo.show()
self.name = Gtk.Label(halign=Gtk.Align.START)
self.name.override_font(Pango.FontDescription('sans bold 12'))
self.name.set_selectable(True)
vbox.pack_start(self.name, fill=True, expand=False, padding=7)
self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL)
@@ -150,7 +149,9 @@ class PersonDetails(Gramplet):
Display details of the active person.
"""
self.load_person_image(active_person)
self.name.set_text(name_displayer.display(active_person))
self.name.set_markup(
"<span size='large' weight='bold'>%s</span>" %
markup_escape_text(name_displayer.display(active_person), -1))
self.clear_grid()
self.display_alternate_names(active_person)
self.display_parents(active_person)
@@ -177,8 +178,8 @@ class PersonDetails(Gramplet):
"""
Display an empty row to separate groupd of entries.
"""
label = Gtk.Label(label='')
label.override_font(Pango.FontDescription('sans 4'))
label = Gtk.Label()
label.set_markup("<span font='sans 4'> </span>")
label.set_selectable(True)
label.show()
self.grid.add(label)
+5 -5
View File
@@ -23,7 +23,7 @@
#
#-------------------------------------------------------------------------
from gi.repository import Gtk
from gi.repository import Pango
from gi.repository.GLib import markup_escape_text
#-------------------------------------------------------------------------
#
@@ -55,7 +55,6 @@ class PlaceDetails(Gramplet):
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.photo = Photo(self.uistate.screen_height() < 1000)
self.title = Gtk.Label(halign=Gtk.Align.START)
self.title.override_font(Pango.FontDescription('sans bold 12'))
self.title.set_selectable(True)
vbox.pack_start(self.title, False, True, 7)
self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL)
@@ -119,7 +118,8 @@ class PlaceDetails(Gramplet):
"""
self.load_place_image(place)
title = place_displayer.display(self.dbstate.db, place)
self.title.set_text(title)
self.title.set_markup("<span size='large' weight='bold'>%s</span>" %
markup_escape_text(title))
self.clear_grid()
self.add_row(_('Name'), place.get_name().get_value())
@@ -158,8 +158,8 @@ class PlaceDetails(Gramplet):
"""
Display an empty row to separate groupd of entries.
"""
label = Gtk.Label(label='')
label.override_font(Pango.FontDescription('sans 4'))
label = Gtk.Label()
label.set_markup("<span font='sans 4'> </span>")
label.set_selectable(True)
label.show()
self.grid.add(label)
+6 -4
View File
@@ -24,6 +24,7 @@
#-------------------------------------------------------------------------
from gi.repository import Gtk
from gi.repository import Pango
from gi.repository.GLib import markup_escape_text
#-------------------------------------------------------------------------
#
@@ -51,7 +52,6 @@ class RepositoryDetails(Gramplet):
self.top = Gtk.Box()
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.name = Gtk.Label(halign=Gtk.Align.START)
self.name.override_font(Pango.FontDescription('sans bold 12'))
self.name.set_selectable(True)
vbox.pack_start(self.name, fill=True, expand=False, padding=7)
self.grid = Gtk.Grid(orientation=Gtk.Orientation.VERTICAL)
@@ -112,7 +112,9 @@ class RepositoryDetails(Gramplet):
"""
Display details of the active repository.
"""
self.name.set_text(repo.get_name())
self.name.set_markup(
"<span size='large' weight='bold'>%s</span>" %
markup_escape_text(repo.get_name(), -1))
self.clear_grid()
address_list = repo.get_address_list()
@@ -154,8 +156,8 @@ class RepositoryDetails(Gramplet):
"""
Display an empty row to separate groupd of entries.
"""
label = Gtk.Label(label='')
label.override_font(Pango.FontDescription('sans 4'))
label = Gtk.Label()
label.set_markup("<span font='sans 4'> </span>")
label.set_selectable(True)
label.show()
self.grid.add(label)
+13 -10
View File
@@ -33,6 +33,7 @@ Family Lines, a Graphviz-based plugin for Gramps.
#
#------------------------------------------------------------------------
from functools import partial
import html
#------------------------------------------------------------------------
#
@@ -818,10 +819,10 @@ class FamilyLinesReport(Report):
if bth_event and self._incdates:
date = bth_event.get_date_object()
if self._just_years and date.get_year_valid():
birth_str = self._get_date( # localized year
birth_str = self.get_date( # localized year
Date(date.get_year()))
else:
birth_str = self._get_date(date)
birth_str = self.get_date(date)
# get birth place (one of: hamlet, village, town, city, parish,
# county, province, region, state or country)
@@ -834,10 +835,10 @@ class FamilyLinesReport(Report):
if dth_event and self._incdates:
date = dth_event.get_date_object()
if self._just_years and date.get_year_valid():
death_str = self._get_date( # localized year
death_str = self.get_date( # localized year
Date(date.get_year()))
else:
death_str = self._get_date(date)
death_str = self.get_date(date)
# get death place (one of: hamlet, village, town, city, parish,
# county, province, region, state or country)
@@ -876,8 +877,7 @@ class FamilyLinesReport(Report):
label += '<TD>'
# at the very least, the label must have the person's name
name = name.replace('"', '&#34;')
label += name.replace('<', '&#60;').replace('>', '&#62;')
label += html.escape(name)
if self.includeid == 1: # same line
label += " (%s)" % p_id
elif self.includeid == 2: # own line
@@ -964,10 +964,10 @@ class FamilyLinesReport(Report):
if self._incdates:
date = event.get_date_object()
if self._just_years and date.get_year_valid():
wedding_date = self._get_date( # localized year
wedding_date = self.get_date( # localized year
Date(date.get_year()))
else:
wedding_date = self._get_date(date)
wedding_date = self.get_date(date)
# get the wedding location
if self._incplaces:
wedding_place = self.get_event_place(event)
@@ -1090,6 +1090,9 @@ class FamilyLinesReport(Report):
place = self._db.get_place_from_handle(place_handle)
if place:
place_text = _pd.display(self._db, place)
place_text = place_text.replace('<', '&#60;')
place_text = place_text.replace('>', '&#62;')
place_text = html.escape(place_text)
return place_text
def get_date(self, date):
""" return a formatted date """
return html.escape(self._get_date(date))
+8 -6
View File
@@ -32,6 +32,7 @@ Generate an hourglass graph using the Graphviz generator.
# python modules
#
#------------------------------------------------------------------------
import html
#------------------------------------------------------------------------
#
@@ -251,18 +252,17 @@ class HourGlassReport(Report):
"""
p_id = person.get_gramps_id()
name = self._name_display.display(person)
name = name.replace('"', '&#34;')
name = name.replace('<', '&#60;').replace('>', '&#62;')
name = html.escape(name)
birth_evt = get_birth_or_fallback(self.__db, person)
if birth_evt:
birth = self._get_date(birth_evt.get_date_object())
birth = self.get_date(birth_evt.get_date_object())
else:
birth = ""
death_evt = get_death_or_fallback(self.__db, person)
if death_evt:
death = self._get_date(death_evt.get_date_object())
death = self.get_date(death_evt.get_date_object())
else:
death = ""
@@ -295,7 +295,7 @@ class HourGlassReport(Report):
label = ""
marriage = utils.find_marriage(self.__db, family)
if marriage:
label = self._get_date(marriage.get_date_object())
label = self.get_date(marriage.get_date_object())
if self.includeid == 1 and label: # same line
label = "%s (%s)" % (label, family_id)
elif self.includeid == 1 and not label:
@@ -343,7 +343,9 @@ class HourGlassReport(Report):
else:
fill = self.colors['unknown']
return(shape, style, color, fill)
def get_date(self, date):
""" return a formatted date """
return html.escape(self._get_date(date))
#------------------------------------------------------------------------
#
+8 -5
View File
@@ -40,6 +40,7 @@ Create a relationship graph using Graphviz
#
#------------------------------------------------------------------------
from functools import partial
import html
#------------------------------------------------------------------------
#
@@ -616,8 +617,7 @@ class RelGraphReport(Report):
# at the very least, the label must have the person's name
p_name = self._name_display.display(person)
p_name = p_name.replace('"', '&#34;')
label += p_name.replace('<', '&#60;').replace('>', '&#62;')
label += html.escape(p_name)
p_id = person.get_gramps_id()
if self.includeid == 1: # same line
label += " (%s)" % p_id
@@ -751,10 +751,10 @@ class RelGraphReport(Report):
event_date = event.get_date_object()
if event_date.get_year_valid():
if self.event_choice in [4, 5]:
return self._get_date( # localized year
return self.get_date( # localized year
Date(event_date.get_year()))
elif self.event_choice in [1, 2, 3, 7]:
return self._get_date(event_date)
return self.get_date(event_date)
return ''
def get_place_string(self, event):
@@ -768,8 +768,11 @@ class RelGraphReport(Report):
"""
if event and self.event_choice in [2, 3, 5, 6, 7]:
place = _pd.display_event(self._db, event)
return place.replace('<', '&#60;').replace('>', '&#62;')
return html.escape(place)
return ''
def get_date(self, date):
""" return a formatted date """
return html.escape(self._get_date(date))
#------------------------------------------------------------------------
#
+8
View File
@@ -559,6 +559,14 @@ class BasePersonView(ListView):
person.add_tag(tag_handle)
self.dbstate.db.commit_person(person, transaction)
def remove_tag(self, transaction, person_handle, tag_handle):
"""
Remove the given tag from the given person.
"""
person = self.dbstate.db.get_person_from_handle(person_handle)
person.remove_tag(tag_handle)
self.dbstate.db.commit_person(person, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
+8
View File
@@ -595,6 +595,14 @@ class PlaceBaseView(ListView):
place.add_tag(tag_handle)
self.dbstate.db.commit_place(place, transaction)
def remove_tag(self, transaction, place_handle, tag_handle):
"""
Remove the given tag from the given place.
"""
place = self.dbstate.db.get_place_from_handle(place_handle)
place.remove_tag(tag_handle)
self.dbstate.db.commit_place(place, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
+22 -16
View File
@@ -22,7 +22,6 @@
"""
from gramps.gen.plug.report import utils
from gramps.gen.lib import ChildRefType
#------------------------------------------------------------------------
@@ -56,6 +55,7 @@ class _PersonSeen:
if person_handle is not None:
self.people_seen.add(person_handle)
class _FamilySeen:
""" librecurse base boject only
Keep track of the famalies that have been seen so we can call the correct
@@ -80,6 +80,7 @@ class _FamilySeen:
self.add_marriage(level, person_handle, family_handle)
self.families_seen.add(family_handle)
class _StopRecurse:
""" A simple class to break out the
. stop_recursion
@@ -101,7 +102,7 @@ class _StopRecurse:
def can_recurse(self):
""" Has the upper class told up to stop or can we continue? """
return self.__stop_recursion == False
return not self.__stop_recursion
#------------------------------------------------------------------------
@@ -276,7 +277,7 @@ class DescendPerson(_StopRecurse, _PersonSeen, _FamilySeen):
for family_handle in family_handles:
#Marriage box if the option is there.
self._add_marriage((g_level, s_level + 1),
person_handle, family_handle)
person_handle, family_handle)
if not self.can_recurse():
self.continue_recursion()
@@ -288,7 +289,7 @@ class DescendPerson(_StopRecurse, _PersonSeen, _FamilySeen):
if self.max_spouses > s_level:
self.__this_slevel = s_level + 1
self._add_person((g_level, s_level + 1),
spouse_handle, family_handle)
spouse_handle, family_handle)
if not self.can_recurse:
self.continue_recursion()
@@ -446,13 +447,13 @@ class AscendPerson(_StopRecurse, _PersonSeen):
# Recursively call the function. It is okay if the handle is None,
# since routine handles a handle of None
self.__fill(generation+1, index*2, mx_fill-1)
self.__fill(generation + 1, index * 2, mx_fill - 1)
if mx_fill > 1: # marriage of parents
self.add_marriage((generation+1, index*2), None, None)
self.add_marriage((generation + 1, index * 2), None, None)
if not self.can_recurse():
self.continue_recursion()
return
self.__fill(generation+1, (index*2)+1, mx_fill-1)
self.__fill(generation + 1, (index * 2) + 1, mx_fill - 1)
def __iterate(self, generation, index, person_handle, full_family_handle):
"""
@@ -478,15 +479,15 @@ class AscendPerson(_StopRecurse, _PersonSeen):
person = self.database.get_person_from_handle(person_handle)
# we have a valid person, add him/her
self._add_person((generation, index), person_handle, full_family_handle)
self._add_person((generation, index), person_handle,
full_family_handle)
# has the user canceled recursion?
if not self.can_recurse():
self.continue_recursion()
return
#Now recurse on the parents
# Now recurse on the parents
family_handle = person.get_main_parents_family_handle()
if family_handle is not None:
@@ -498,21 +499,26 @@ class AscendPerson(_StopRecurse, _PersonSeen):
mother_handle = None
# Recursively call the function. It is okay if the handle is None,
self.__iterate(generation+1, index*2, father_handle, family_handle) #recurse on dad
self.__iterate(generation + 1, index * 2, father_handle,
family_handle) # recurse on dad
if generation < self.max_generations:
if father_handle is not None: # Stil winin max_generations
self.add_marriage((generation+1, index*2), father_handle, family_handle)
self.add_marriage((generation + 1, index * 2), father_handle,
family_handle)
elif mother_handle is not None:
self.add_marriage((generation+1, index*2), mother_handle, family_handle)
self.add_marriage((generation + 1, index * 2), mother_handle,
family_handle)
elif family_handle is not None:
self.add_marriage((generation+1, index*2), None, family_handle)
self.add_marriage((generation + 1, index * 2), None,
family_handle)
elif self.fill_out > 0:
self.add_marriage((generation+1, index*2), None, None)
self.add_marriage((generation + 1, index * 2), None, None)
if not self.can_recurse():
self.continue_recursion()
return
self.__iterate(generation+1, (index*2)+1, mother_handle, family_handle) #recurse mom
self.__iterate(generation + 1, (index * 2) + 1, mother_handle,
family_handle) # recurse mom
def recurse(self, person_handle):
"""
+8 -12
View File
@@ -405,7 +405,6 @@ class GeoGraphyView(OsmGps, NavigationView):
self.changemap = Gtk.Menu()
changemap = self.changemap
changemap.set_title(title)
changemap.show()
add_item.set_submenu(changemap)
# show in the map menu all available providers
@@ -885,7 +884,6 @@ class GeoGraphyView(OsmGps, NavigationView):
menu.append(add_item)
self.itemoption = Gtk.Menu()
itemoption = self.itemoption
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = Gtk.MenuItem(label=_("Edit Place"))
@@ -990,11 +988,11 @@ class GeoGraphyView(OsmGps, NavigationView):
filtering = Gtk.FileFilter()
filtering.add_pattern("*.kml")
kml = Gtk.FileChooserDialog(
_("Select a kml file used to add places"),
title=_("Select a kml file used to add places"),
action=Gtk.FileChooserAction.OPEN,
parent=self.uistate.window,
buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Apply'), Gtk.ResponseType.OK))
transient_for=self.uistate.window)
kml.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Apply'), Gtk.ResponseType.OK)
mpath = HOME_DIR
kml.set_current_folder(os.path.dirname(mpath))
kml.set_filter(filtering)
@@ -1286,13 +1284,11 @@ class GeoGraphyView(OsmGps, NavigationView):
"""
dummy_obj = obj
selected_dir = Gtk.FileChooserDialog(
_("Select tile cache directory for offline mode"),
title=_("Select tile cache directory for offline mode"),
action=Gtk.FileChooserAction.SELECT_FOLDER,
parent=self.uistate.window,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Apply'),
Gtk.ResponseType.OK))
transient_for=self.uistate.window)
selected_dir.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Apply'), Gtk.ResponseType.OK)
mpath = config.get('geography.path')
if not mpath:
mpath = HOME_DIR
+6 -6
View File
@@ -115,10 +115,10 @@ class PlaceSelection(ManagedWindow, OsmGps):
self.selection_layer = layer
self.layer = layer
self.warning = False
self.set_window(
Gtk.Dialog(_('Place Selection in a region'), uistate.window,
buttons=(_('_Close'), Gtk.ResponseType.CLOSE)),
None, _('Place Selection in a region'), None)
dlg = Gtk.Dialog(title=_('Place Selection in a region'),
transient_for=uistate.window)
dlg.add_button(_('_Close'), Gtk.ResponseType.CLOSE)
self.set_window(dlg, None, _('Place Selection in a region'), None)
mylabel = _('Choose the radius of the selection.\n'
'On the map you should see a circle or an'
' oval depending on the latitude.')
@@ -139,11 +139,11 @@ class PlaceSelection(ManagedWindow, OsmGps):
slider.connect('value-changed', self.slider_change, self.lat, self.lon)
self.window.vbox.pack_start(slider, False, True, 0)
self.vadjust = Gtk.Adjustment(page_size=15)
self.scroll = Gtk.ScrolledWindow(self.vadjust)
self.scroll = Gtk.ScrolledWindow(vadjustment=self.vadjust)
self.scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
self.scroll.set_shadow_type(Gtk.ShadowType.IN)
self.plist = Gtk.ListStore(str, str, str, str, str)
self.choices = Gtk.TreeView(self.plist)
self.choices = Gtk.TreeView(model=self.plist)
self.scroll.add(self.choices)
self.renderer = Gtk.CellRendererText()
self.tvcol1 = Gtk.TreeViewColumn(_('Country'), self.renderer, markup=0)
+83
View File
@@ -22,6 +22,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
import unittest
import os
import difflib
from unittest.mock import patch
from time import localtime, strptime
from gramps.test.test_util import Gramps
from gramps.gen.const import TEMP_DIR, DATA_DIR
@@ -33,6 +35,13 @@ TREE_NAME = "Test_exporttest"
TEST_DIR = os.path.abspath(os.path.join(DATA_DIR, "tests"))
def mock_localtime(*args):
"""
Mock up a dummy to replace the varying 'time string results'
"""
return strptime("25 Dec 1999", "%d %b %Y")
def call(*args):
""" Call Gramps to perform the action with out and err captured """
#print("call:", args)
@@ -84,6 +93,8 @@ def compare(expect_file, result_file, dfilter=None):
msg += line
if dfilter:
fail += dfilter(line)
else:
fail = True
return msg if fail else ""
@@ -184,6 +195,9 @@ class ExportControl(unittest.TestCase):
export dates, file names etc. that don't count as differences.
"""
def setUp(self):
config.set('behavior.date-before-range', 50)
config.set('behavior.date-after-range', 50)
config.set('behavior.date-about-range', 10)
self.tearDown() # removes it if it existed
# out, err = self.call("-C", TREE_NAME,
@@ -195,6 +209,17 @@ class ExportControl(unittest.TestCase):
def test_csv(self):
""" Run a csv export test """
set_format(0) # Use ISO date for test
config.set('database.backend', 'bsddb')
src_file = 'exp_sample_csv.gramps'
tst_file = 'exp_sample_csv.csv'
msg = do_it(src_file, tst_file)
if msg:
self.fail(tst_file + ': ' + msg)
def test_csv_sq(self):
""" Run a csv export test """
set_format(0) # Use ISO date for test
config.set('database.backend', 'sqlite')
src_file = 'exp_sample_csv.gramps'
tst_file = 'exp_sample_csv.csv'
msg = do_it(src_file, tst_file)
@@ -204,6 +229,17 @@ class ExportControl(unittest.TestCase):
def test_ged(self):
""" Run a Gedcom export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'bsddb')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample_ged.ged'
msg = do_it(src_file, tst_file, gedfilt)
if msg:
self.fail(tst_file + ': ' + msg)
def test_ged_sq(self):
""" Run a Gedcom export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'sqlite')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample_ged.ged'
msg = do_it(src_file, tst_file, gedfilt)
@@ -213,15 +249,39 @@ class ExportControl(unittest.TestCase):
def test_vcard(self):
""" Run a vcard export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'bsddb')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.vcf'
msg = do_it(src_file, tst_file, vcffilt)
if msg:
self.fail(tst_file + ': ' + msg)
def test_vcard_sq(self):
""" Run a vcard export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'sqlite')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.vcf'
msg = do_it(src_file, tst_file, vcffilt)
if msg:
self.fail(tst_file + ': ' + msg)
@patch('gramps.plugins.export.exportvcalendar.time.localtime', mock_localtime)
def test_vcs(self):
""" Run a Vcalandar export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'bsddb')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.vcs'
msg = do_it(src_file, tst_file)
if msg:
self.fail(tst_file + ': ' + msg)
@patch('gramps.plugins.export.exportvcalendar.time.localtime', mock_localtime)
def test_vcs_sq(self):
""" Run a Vcalandar export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'sqlite')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.vcs'
msg = do_it(src_file, tst_file)
@@ -231,6 +291,17 @@ class ExportControl(unittest.TestCase):
def test_gw(self):
""" Run a Geneweb export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'bsddb')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.gw'
msg = do_it(src_file, tst_file)
if msg:
self.fail(tst_file + ': ' + msg)
def test_gw_sq(self):
""" Run a Geneweb export test """
config.set('preferences.place-auto', True)
config.set('database.backend', 'sqlite')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.gw'
msg = do_it(src_file, tst_file)
@@ -241,6 +312,18 @@ class ExportControl(unittest.TestCase):
""" Run a Web Family Tree export test """
set_format(0) # Use ISO date for test
config.set('preferences.place-auto', True)
config.set('database.backend', 'bsddb')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.wft'
msg = do_it(src_file, tst_file)
if msg:
self.fail(tst_file + ': ' + msg)
def test_wft_sq(self):
""" Run a Web Family Tree export test """
set_format(0) # Use ISO date for test
config.set('preferences.place-auto', True)
config.set('database.backend', 'sqlite')
src_file = 'exp_sample.gramps'
tst_file = 'exp_sample.wft'
msg = do_it(src_file, tst_file)
+4 -4
View File
@@ -775,10 +775,10 @@ class CheckIntegrity:
'kept')
fs_top = Gtk.FileChooserDialog(
"%s - Gramps" % _("Select file"),
parent=self.parent_window,
buttons=(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_OK'), Gtk.ResponseType.OK))
title="%s - Gramps" % _("Select file"),
transient_for=self.parent_window)
fs_top.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_OK'), Gtk.ResponseType.OK)
fs_top.set_current_folder(self.last_img_dir)
response = fs_top.run()
if response == Gtk.ResponseType.OK:
+4 -6
View File
@@ -393,12 +393,10 @@ class EventComparisonResults(ManagedWindow):
def on_write_table(self, obj):
f = Gtk.FileChooserDialog(_("Select filename"),
parent=self.window,
action=Gtk.FileChooserAction.SAVE,
buttons=(_('_Cancel'),
Gtk.ResponseType.CANCEL,
_('_Save'),
Gtk.ResponseType.OK))
transient_for=self.window,
action=Gtk.FileChooserAction.SAVE)
f.add_buttons(_('_Cancel'), Gtk.ResponseType.CANCEL,
_('_Save'), Gtk.ResponseType.OK)
f.set_current_folder(get_curr_dir())
status = f.run()
+10 -9
View File
@@ -84,15 +84,16 @@ class PopulateSources(tool.Tool, ManagedWindow):
num_citations = self.options.handler.options_dict['citations']
# GUI setup:
dialog = Gtk.Dialog("Populate sources and citations tool",
self.uistate.window,
Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_Cancel'), Gtk.ResponseType.REJECT,
_('_OK'), Gtk.ResponseType.ACCEPT))
label = Gtk.Label("Enter a valid number of sources and citations."
" This will create the requested number of sources,"
" and for each source, will create the requested"
" number of citations.")
dialog = Gtk.Dialog(title="Populate sources and citations tool",
transient_for=self.uistate.window,
modal=True, destroy_with_parent=True)
dialog.add_buttons(_('_Cancel'), Gtk.ResponseType.REJECT,
_('_OK'), Gtk.ResponseType.ACCEPT)
label = Gtk.Label(
label="Enter a valid number of sources and citations."
" This will create the requested number of sources,"
" and for each source, will create the requested"
" number of citations.")
label.set_line_wrap(True)
hbox1 = Gtk.Box()
+14 -4
View File
@@ -66,6 +66,9 @@ WIKI_HELP_SEC = _('manual|Reorder_Gramps_ID')
PREFIXES = {'person': 'i', 'family': 'f', 'event': 'e', 'place': 'p',
'source': 's', 'citation': 'c', 'repository': 'r',
'media': 'o', 'note': 'n'}
DB_INDXES = {'person': 'p', 'family': 'f', 'event': 'e', 'place': 'l',
'source': 's', 'citation': 'c', 'repository': 'r',
'media': 'o', 'note': 'n'}
#-------------------------------------------------------------------------
#
# Actual tool
@@ -244,7 +247,7 @@ class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
self.prim_methods, self.obj_methods = {}, {}
for prim_obj, prim_objs in self.xobjects:
iter_handles = "iter_%s_handles" % prim_obj
get_handles = "get_%s_handles" % prim_obj
get_number_obj = "get_number_of_%s" % prim_objs
prefix_fmt = "%s_prefix" % prim_obj
get_from_id = "get_%s_from_gramps_id" % prim_obj
@@ -255,7 +258,7 @@ class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
self.prim_methods[prim_obj] = (getattr(self.db, prefix_fmt),
getattr(self.db, get_number_obj)(),
getattr(self.db, next_from_id)())
self.obj_methods[prim_obj] = (getattr(self.db, iter_handles),
self.obj_methods[prim_obj] = (getattr(self.db, get_handles),
getattr(self.db, commit),
getattr(self.db, get_from_id),
getattr(self.db, get_from_handle),
@@ -548,6 +551,9 @@ class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
self.progress.set_pass(
_('Reorder %s IDs ...') % _(prim_objs.title()),
self.obj_values[prim_obj].quant_id)
# reset the db next_id index to zero so we restart new IDs
# at lowest possible position
setattr(self.db, DB_INDXES[prim_obj] + 'map_index', 0)
# Process reordering
self._reorder(prim_obj)
@@ -572,7 +578,7 @@ class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
dup_ids = [] # list of duplicate identifiers
new_ids = {} # list of new identifiers
iter_handles, commit, get_from_id, get_from_handle, next_from_id = \
get_handles, commit, get_from_id, get_from_handle, next_from_id = \
self.obj_methods[prim_obj]
prefix_fmt = self.obj_values[prim_obj].get_fmt()
@@ -585,8 +591,12 @@ class ReorderIds(tool.BatchTool, ManagedWindow, UpdateCallback):
change = self.obj_values[prim_obj].get_change()
index_max = int("9" * self.obj_values[prim_obj].width_fmt)
do_same = False
# Process in handle order, which is in order handles were created.
# This makes renumberd IDs more consistant.
handles = get_handles()
handles.sort()
for handle in iter_handles():
for handle in handles:
# Update progress
if self.uistate:
self.progress.step()
+1 -1
View File
@@ -272,7 +272,7 @@ class TestcaseGenerator(tool.BatchTool):
def init_gui(self, uistate):
title = "%s - Gramps" % _("Generate testcases")
self.top = Gtk.Dialog(title, parent=uistate.window)
self.top = Gtk.Dialog(title=title, transient_for=uistate.window)
self.window = uistate.window
self.top.set_default_size(400, 150)
self.top.vbox.set_spacing(5)
+8
View File
@@ -453,6 +453,14 @@ class CitationListView(ListView):
citation.add_tag(tag_handle)
self.dbstate.db.commit_citation(citation, transaction)
def remove_tag(self, transaction, citation_handle, tag_handle):
"""
Remove the given tag from the given citation.
"""
citation = self.dbstate.db.get_citation_from_handle(citation_handle)
citation.remove_tag(tag_handle)
self.dbstate.db.commit_citation(citation, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
+12
View File
@@ -742,6 +742,18 @@ class CitationTreeView(ListView):
source.add_tag(tag_handle)
self.dbstate.db.commit_source(source, transaction)
def remove_tag(self, transaction, handle, tag_handle):
"""
Remove the given tag from the given source or citation.
"""
source, citation = self.get_source_or_citation(handle)
if citation:
citation.remove_tag(tag_handle)
self.dbstate.db.commit_citation(citation, transaction)
else:
source.remove_tag(tag_handle)
self.dbstate.db.commit_source(source, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
+8
View File
@@ -468,6 +468,14 @@ class EventView(ListView):
event.add_tag(tag_handle)
self.dbstate.db.commit_event(event, transaction)
def remove_tag(self, transaction, event_handle, tag_handle):
"""
Remove the given tag from the given event.
"""
event = self.dbstate.db.get_event_from_handle(event_handle)
event.remove_tag(tag_handle)
self.dbstate.db.commit_event(event, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
+8
View File
@@ -483,6 +483,14 @@ class FamilyView(ListView):
family.add_tag(tag_handle)
self.dbstate.db.commit_family(family, transaction)
def remove_tag(self, transaction, family_handle, tag_handle):
"""
Remove the given tag from the given family.
"""
family = self.dbstate.db.get_family_from_handle(family_handle)
family.remove_tag(tag_handle)
self.dbstate.db.commit_family(family, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
+4 -4
View File
@@ -135,7 +135,7 @@ class FanChart2WayView(fanchart2way.FanChart2WayGrampsGUI, NavigationView):
self.scrolledwindow.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC)
self.fan.show_all()
self.scrolledwindow.add_with_viewport(self.fan)
self.scrolledwindow.add(self.fan)
return self.scrolledwindow
@@ -573,9 +573,9 @@ class CairoPrintSave():
(typically evince not installed)!
"""
dummy_preview = preview
dlg = Gtk.MessageDialog(parent,
flags=Gtk.DialogFlags.MODAL,
type=Gtk.MessageType.WARNING,
dlg = Gtk.MessageDialog(transient_for=parent,
modal=True,
message_type=Gtk.MessageType.WARNING,
buttons=Gtk.ButtonsType.CLOSE,
message_format=_('No preview available'))
self.preview = dlg

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