Compare commits
639 Commits
geps/gep-0
...
geps/gep-0
Author | SHA1 | Date | |
---|---|---|---|
|
7fb1ad876a | ||
|
89909f87cd | ||
|
5903853640 | ||
|
7c90638ad3 | ||
|
9037f827a5 | ||
|
367de337a4 | ||
|
06de73c8f4 | ||
|
c4ecfaafe9 | ||
|
2430607b63 | ||
|
94fe287886 | ||
|
6cf005cb38 | ||
|
38db8959fa | ||
|
6c04f8b151 | ||
|
85cc487ee9 | ||
|
38d7ee72f2 | ||
|
9ce8403106 | ||
|
ee3350e9d5 | ||
|
6cde88e22d | ||
|
e9efb9debc | ||
|
0a2580e9c5 | ||
|
4664f77608 | ||
|
5b6da40866 | ||
|
e9629f77e0 | ||
|
0d3aec7313 | ||
|
a7e5ecbadf | ||
|
6e22f80784 | ||
|
242fd1372d | ||
|
6d9fbe0238 | ||
|
39395150f7 | ||
|
1158e77e13 | ||
|
3fd0762ae0 | ||
|
54ef9241a1 | ||
|
1fd823bb71 | ||
|
b8a18b02b5 | ||
|
8af57bcf07 | ||
|
32172f1168 | ||
|
a4558b3ccc | ||
|
8bbbae41aa | ||
|
d30ade0488 | ||
|
99671bdfaf | ||
|
d03fc19188 | ||
|
1dc1f6c0c2 | ||
|
face94275c | ||
|
4ba97726a2 | ||
|
f3fc5c5257 | ||
|
aa7516cbb4 | ||
|
fab092f6fd | ||
|
87499c96bc | ||
|
dc690b7071 | ||
|
8ad6600746 | ||
|
8ca5d92883 | ||
|
a971eb7d66 | ||
|
2b6ee1aa60 | ||
|
8b37ca4119 | ||
|
3a42651fb1 | ||
|
5c0b6dd023 | ||
|
cc839bf167 | ||
|
f177537525 | ||
|
dce3fc0605 | ||
|
9391218f20 | ||
|
dc853e2ee6 | ||
|
06e4dcd11d | ||
|
5c71b46283 | ||
|
3135b2b304 | ||
|
3208db231d | ||
|
a3c422b592 | ||
|
5ee5ef158e | ||
|
33343437a5 | ||
|
5ffcd383ac | ||
|
e2f87c965b | ||
|
8204724f32 | ||
|
f80bf8eb15 | ||
|
973e143b22 | ||
|
34b13775b7 | ||
|
e5f80e521c | ||
|
ccf1f2eac5 | ||
|
1e99275b84 | ||
|
b28bd17980 | ||
|
ac730cf013 | ||
|
860360af2f | ||
|
8e922b562d | ||
|
72748498b2 | ||
|
9310d5c32d | ||
|
6e2272bb78 | ||
|
da93d7134b | ||
|
d6c216bbd0 | ||
|
be45ac54fe | ||
|
b28bfb39db | ||
|
6ef2e77568 | ||
|
9543f44080 | ||
|
28d20c52f8 | ||
|
a8ddc8e635 | ||
|
30e051a7fe | ||
|
3b99b31656 | ||
|
a091d97677 | ||
|
69cfbe7a02 | ||
|
6dce67703e | ||
|
c449bbf588 | ||
|
cfebdf3429 | ||
|
8755619584 | ||
|
62da0fbaa9 | ||
|
aa71eb19a6 | ||
|
cc8b166138 | ||
|
9b1af034fc | ||
|
f167507a0f | ||
|
b07717ad86 | ||
|
b7d1f6906c | ||
|
b2b6bcb56a | ||
|
9a0bc027fe | ||
|
77ceea2931 | ||
|
e50182508a | ||
|
2ffbd49b55 | ||
|
a5700a28df | ||
|
facfeada47 | ||
|
8f412bae1c | ||
|
188587bbaf | ||
|
0a8c9bc2e2 | ||
|
bf29e57039 | ||
|
3d9559cfae | ||
|
2b5d7efdce | ||
|
25c5e6fbc8 | ||
|
6a4a4a3a9c | ||
|
7792f0f5de | ||
|
98ef6cfcb3 | ||
|
266a2936bf | ||
|
57d2951cdf | ||
|
43e5416d0e | ||
|
bf9257bb92 | ||
|
ff21b0bb27 | ||
|
873df14509 | ||
|
ff7f04d7e9 | ||
|
3fe84ba8fe | ||
|
76a7d7adde | ||
|
0d38f4f5a4 | ||
|
9a9f47dc28 | ||
|
919005c539 | ||
|
532a6d6171 | ||
|
0c5beeecfd | ||
|
0dbeb270f9 | ||
|
c627290799 | ||
|
e3697e183a | ||
|
b40119cedf | ||
|
f5665dc67b | ||
|
574384268e | ||
|
076fdac5a7 | ||
|
5999f7c0a1 | ||
|
49645c6957 | ||
|
8744e93fd9 | ||
|
b0a3666e5a | ||
|
04e3543274 | ||
|
6d8d8a3b6b | ||
|
6ec4227248 | ||
|
9c847462a0 | ||
|
fcd2296461 | ||
|
0ce4b749d0 | ||
|
9aa9d43856 | ||
|
7edd984b91 | ||
|
9e757e2249 | ||
|
7f264b91f5 | ||
|
98bfecc918 | ||
|
be23e20276 | ||
|
ab15b85566 | ||
|
cf04a983a4 | ||
|
7ba9ca93da | ||
|
620ba618c2 | ||
|
0a22c95aa2 | ||
|
11e45f293f | ||
|
86b7a99101 | ||
|
735adfb0c1 | ||
|
547f0cacf7 | ||
|
be6665e99d | ||
|
f215a12733 | ||
|
d8e3e0fb6f | ||
|
ce44a4e57a | ||
|
3555289c39 | ||
|
612b893956 | ||
|
6930887aa1 | ||
|
31699972b8 | ||
|
7187eb8ab6 | ||
|
4621d09d4d | ||
|
7f411bb964 | ||
|
6c50df1ff8 | ||
|
2201a7d4db | ||
|
b2b693ae19 | ||
|
9cddf824a2 | ||
|
5e42724282 | ||
|
a268271833 | ||
|
73d1d080b5 | ||
|
d5537ab93a | ||
|
16dbd437e1 | ||
|
52f2b9e46a | ||
|
ecdc91160f | ||
|
dc89736d4a | ||
|
a2d84df7c8 | ||
|
4ecedd6148 | ||
|
0509177b08 | ||
|
da7f594765 | ||
|
da72bfbafb | ||
|
eb0bbd43d1 | ||
|
c685be2973 | ||
|
4cb0e92643 | ||
|
9f61c09829 | ||
|
af584bb950 | ||
|
6a15e552ef | ||
|
3ab598d8f9 | ||
|
eca2313b31 | ||
|
bdafcda182 | ||
|
c4e7179bfa | ||
|
dc39360017 | ||
|
c3ce490fa2 | ||
|
4d0ed91cfa | ||
|
a243a9bfac | ||
|
a831bb0113 | ||
|
e709c127f6 | ||
|
f5eae77246 | ||
|
ad6ed26f70 | ||
|
8e76c93f25 | ||
|
c1b9b826ef | ||
|
2050e3f896 | ||
|
647bd5800c | ||
|
f4cbda07ec | ||
|
346f982b27 | ||
|
6aeb49aefc | ||
|
be53411b39 | ||
|
df431da250 | ||
|
c939b9d832 | ||
|
f546908d17 | ||
|
0149435358 | ||
|
49c0af18ee | ||
|
8a4f89f8e3 | ||
|
4f61f03bec | ||
|
5db0763970 | ||
|
143dcc08fa | ||
|
2e453b678a | ||
|
a579fd1ad9 | ||
|
2054c0ad46 | ||
|
a2e17b7b4a | ||
|
1832f7bdb5 | ||
|
9daf584c74 | ||
|
e9770ef48f | ||
|
7a17f9b420 | ||
|
fefe1f842a | ||
|
b7f6055af8 | ||
|
467a9b1c43 | ||
|
769203162c | ||
|
963712e978 | ||
|
0a6ff725ac | ||
|
6400b8b29c | ||
|
6804278fc1 | ||
|
a364740fae | ||
|
dc128110bc | ||
|
3a06d7b204 | ||
|
9804301762 | ||
|
f0ea234060 | ||
|
57f6f389a8 | ||
|
cceb28c5b9 | ||
|
12777d3fb9 | ||
|
2ded1e5e8a | ||
|
86686c764b | ||
|
83fb5d353d | ||
|
07b84e5e11 | ||
|
d50b4ced58 | ||
|
5f98900c27 | ||
|
bc63594df4 | ||
|
227dc5f7b4 | ||
|
00aa00fbf5 | ||
|
56254d4a14 | ||
|
665206df85 | ||
|
27f667e343 | ||
|
db66851363 | ||
|
6f078627ca | ||
|
2c532baf1c | ||
|
a422b30fd6 | ||
|
25315ceece | ||
|
87c11877f4 | ||
|
d96c766cb1 | ||
|
3702704ef2 | ||
|
36f27ebefb | ||
|
aa0e413d5f | ||
|
a71e8f5689 | ||
|
3aaa4641d7 | ||
|
59d9bc25c0 | ||
|
b5997bdb45 | ||
|
f91db9f5e1 | ||
|
d2c5629b9d | ||
|
99075d48a7 | ||
|
6d60fadb4e | ||
|
cb028cea56 | ||
|
c5fe6ed881 | ||
|
8fbddda976 | ||
|
01b4b7dc4e | ||
|
e21ba6c432 | ||
|
445f10396a | ||
|
61205f8783 | ||
|
60b57a996e | ||
|
b72ddb7f47 | ||
|
04c146669b | ||
|
fc23bbd93a | ||
|
0daf403859 | ||
|
689e4d4b47 | ||
|
fe6fb5e67a | ||
|
4bf42dc5ca | ||
|
7b7836267a | ||
|
0c2c56ec4c | ||
|
6ddff4b560 | ||
|
df1ab10041 | ||
|
a8c7156b76 | ||
|
ea9ddaba69 | ||
|
4dc31ff808 | ||
|
f2809f4249 | ||
|
4be0f93da9 | ||
|
0196351c25 | ||
|
a15e676eef | ||
|
1e96009cd7 | ||
|
a3cc615398 | ||
|
4ceba9fd03 | ||
|
a715d8b699 | ||
|
b10de7808d | ||
|
0cab5e576c | ||
|
2fe5255b11 | ||
|
54c228882c | ||
|
da5d7212b2 | ||
|
97782082d5 | ||
|
a88de7bf8a | ||
|
262dae3374 | ||
|
9ad832be33 | ||
|
491885b419 | ||
|
7be12778b2 | ||
|
33ec71c6f7 | ||
|
95e86802c7 | ||
|
415d6c6367 | ||
|
df45f4645b | ||
|
1937a9932b | ||
|
d6f621fe72 | ||
|
ba97c071ef | ||
|
900c2e9ff8 | ||
|
2636d36245 | ||
|
1a36e77b0c | ||
|
16ba9f25de | ||
|
3783a8039b | ||
|
591f695bc9 | ||
|
f4d503744f | ||
|
c64f64657f | ||
|
f59b8fb7d8 | ||
|
ccb23bd7c4 | ||
|
c45a2a0e88 | ||
|
e670f27f3c | ||
|
dee6a9b829 | ||
|
e86bd066c1 | ||
|
aac3f0d2e3 | ||
|
ba5a42eb3f | ||
|
cd6a2b70c4 | ||
|
f431346394 | ||
|
f432853dc4 | ||
|
e142003601 | ||
|
c8a6b91113 | ||
|
bd87b3f310 | ||
|
dc054763c3 | ||
|
b4b9300f6d | ||
|
e64adc8ddd | ||
|
bd1020314e | ||
|
c34610e60d | ||
|
b5d75c54d4 | ||
|
4db73f0422 | ||
|
5adc2102a2 | ||
|
c4d6d17d69 | ||
|
8ed298daa0 | ||
|
0c46e5d91a | ||
|
64b44a16db | ||
|
2c41488ea3 | ||
|
9be852fe2c | ||
|
f97c241af6 | ||
|
156ae935af | ||
|
e3193c7511 | ||
|
b51b6b59a6 | ||
|
548507008b | ||
|
796b2da855 | ||
|
ec787da3fa | ||
|
9e8f6aaab6 | ||
|
d3a389750f | ||
|
71c2655976 | ||
|
d643dde344 | ||
|
8882527e56 | ||
|
084b816d5b | ||
|
c3a58693e3 | ||
|
aa609f7587 | ||
|
12396e858b | ||
|
68158b3859 | ||
|
29292a404a | ||
|
76ef85b43f | ||
|
66ded552dd | ||
|
80ac126dfa | ||
|
c25d94b3a7 | ||
|
f270f08be8 | ||
|
9e844f0d64 | ||
|
7a70853eb5 | ||
|
2299b7fe5d | ||
|
33e45f9b40 | ||
|
a6c09ef304 | ||
|
33d9b19ac7 | ||
|
29cf6674b5 | ||
|
ee639ec7da | ||
|
fa0eb6cebe | ||
|
56e29c162b | ||
|
7055827260 | ||
|
709eb0ebcd | ||
|
55e2863a0b | ||
|
b60dbf2782 | ||
|
40ff796d93 | ||
|
068d50cc26 | ||
|
f984692474 | ||
|
c9698f51e0 | ||
|
9856e108e6 | ||
|
7823280d22 | ||
|
47b8dc8131 | ||
|
a5b4759f40 | ||
|
5a64a968ff | ||
|
b5dc0630a6 | ||
|
b262eeaab7 | ||
|
2dcc870dbc | ||
|
dd3bb6122c | ||
|
b57e7b7508 | ||
|
cf4a3aefbd | ||
|
78624360cd | ||
|
09f276990f | ||
|
7892d02a5d | ||
|
1d4ae20433 | ||
|
694f757463 | ||
|
649bdf7bb7 | ||
|
46d7c95f86 | ||
|
ee3469233a | ||
|
87838a3178 | ||
|
1e208f02bb | ||
|
f6ab91e87f | ||
|
67e975b31f | ||
|
41ff6f2fbd | ||
|
3cdfa558d6 | ||
|
968b4a882d | ||
|
80f25e3806 | ||
|
40b8b02838 | ||
|
58a2be3264 | ||
|
b73e758a84 | ||
|
b87c663612 | ||
|
ee7fdca6ef | ||
|
1e41e76682 | ||
|
991447264a | ||
|
38dcbbae58 | ||
|
ca80adeb01 | ||
|
c0aa613e4a | ||
|
4eb3e7c926 | ||
|
512c57cb04 | ||
|
b2319f90d4 | ||
|
2024c027c6 | ||
|
b78c9b358e | ||
|
bf438cddd6 | ||
|
0599914223 | ||
|
4e04ec09fb | ||
|
d3077942e1 | ||
|
41ba5c838e | ||
|
5e8623cf1b | ||
|
ed8b6b9edf | ||
|
138bbb047b | ||
|
ff7cef7d4e | ||
|
cdf619cf62 | ||
|
624314e8bc | ||
|
07b52e2a11 | ||
|
3178850a29 | ||
|
388ec0cbf1 | ||
|
1773d661e7 | ||
|
6f8fc1be58 | ||
|
af0f98d3b7 | ||
|
14a38b91bc | ||
|
dc671cf212 | ||
|
0b30e204bf | ||
|
4decf95b07 | ||
|
ddf9dc9f14 | ||
|
7c0e4e4eb4 | ||
|
808c3d1183 | ||
|
71edc3e710 | ||
|
c5ae536432 | ||
|
daf8669dc3 | ||
|
3578392de5 | ||
|
e62eb831f0 | ||
|
c2a6e0e5d7 | ||
|
31745aaf8f | ||
|
5e6fe3a996 | ||
|
670592122a | ||
|
bf65ad1e7c | ||
|
6deead53fc | ||
|
f075325399 | ||
|
834a14fc38 | ||
|
a1daf098b2 | ||
|
658134e464 | ||
|
5d6e2c991a | ||
|
8abf7677d6 | ||
|
d12314ccbd | ||
|
ee56e5723a | ||
|
8ddb3711b0 | ||
|
80e27a63c0 | ||
|
b816603119 | ||
|
96e042919c | ||
|
705355104a | ||
|
539fed3314 | ||
|
c56bd35ce0 | ||
|
fcab654305 | ||
|
f48ca367b9 | ||
|
b98ea511cc | ||
|
6353e06fa6 | ||
|
f568077d1e | ||
|
1dfd067e52 | ||
|
280c455eba | ||
|
1db1aefc81 | ||
|
2cb390881b | ||
|
1a5be24d56 | ||
|
553baa596a | ||
|
404c2f154b | ||
|
e46c38bf0e | ||
|
ff8a97a5d6 | ||
|
9b7a34d9c0 | ||
|
06ce88cef4 | ||
|
85ae2aca09 | ||
|
b225c71885 | ||
|
a8bbb91d25 | ||
|
5f8575241b | ||
|
f8a4ad6cb1 | ||
|
d6f9af95ad | ||
|
964d13ab40 | ||
|
6d91a3fd07 | ||
|
fd61b21a2d | ||
|
f238be30ef | ||
|
0c2263a327 | ||
|
ad61ad70a5 | ||
|
ef7ee8cb36 | ||
|
f0ed16a9eb | ||
|
e2f4e39f7e | ||
|
7afc3f7112 | ||
|
17e70f14b3 | ||
|
7de1d4d40e | ||
|
8e1a0a7ca5 | ||
|
ee96c874ba | ||
|
fa1151ef05 | ||
|
9755c2f794 | ||
|
c2164fbb37 | ||
|
57be65f556 | ||
|
bf9af55a3f | ||
|
9ea3e520cb | ||
|
853351397e | ||
|
ee032e67df | ||
|
72051dd488 | ||
|
091782abf7 | ||
|
febd8842fd | ||
|
da7ab966d1 | ||
|
23c9ce10b9 | ||
|
1200a57d53 | ||
|
a8a177d396 | ||
|
5f9651927e | ||
|
3e80ed51e0 | ||
|
284ee7dce9 | ||
|
4a1c769a7e | ||
|
7d9cc19ed0 | ||
|
33fe531672 | ||
|
b0f79b5bbe | ||
|
9c66c62d5c | ||
|
1b14c1d2a1 | ||
|
4ae494bff9 | ||
|
5ae04dfc19 | ||
|
7fb81b5c21 | ||
|
8c5d7afb5c | ||
|
5e505f2c21 | ||
|
795b45c82f | ||
|
2f77462320 | ||
|
c4802bd210 | ||
|
1d002b3218 | ||
|
c91b53f0c4 | ||
|
dc9c445878 | ||
|
9e09c4233f | ||
|
b0e9f158d5 | ||
|
d5d0523303 | ||
|
1a43859587 | ||
|
d189448f39 | ||
|
ddff6f95d9 | ||
|
e4c0e079e7 | ||
|
5e914292fe | ||
|
85a082bb6d | ||
|
d9409a8998 | ||
|
3f7d8933c7 | ||
|
b79eb50aba | ||
|
42de599bd0 | ||
|
e920cbfac1 | ||
|
df46941e73 | ||
|
807512cd05 | ||
|
09a875db11 | ||
|
cc4ec85b4d | ||
|
a58ef2b73f | ||
|
ef7e047b4b | ||
|
ef6892abbd | ||
|
d3c2a8a490 | ||
|
eecf57a0f6 | ||
|
7bb5c75d6a | ||
|
a323f92482 | ||
|
ae65778d27 | ||
|
b3ceb3e828 | ||
|
aa021c36c8 | ||
|
0b2ccdee6d | ||
|
7672f64221 | ||
|
01dbd41081 | ||
|
48f3002e95 | ||
|
6f42885a79 | ||
|
926dbca98f | ||
|
6783e60a7a | ||
|
22f646ccce | ||
|
00bd4b81f8 | ||
|
ae517eb9c7 | ||
|
7af413bbc4 | ||
|
b20e711c30 | ||
|
4cbdd52389 | ||
|
87e7945b65 | ||
|
892143ed4b | ||
|
a769890c26 | ||
|
094726c14f | ||
|
347d371b77 | ||
|
8369658800 | ||
|
7fc4d4ec3f | ||
|
192e7eccf6 | ||
|
f0d8d4bc8d | ||
|
9a1f3abd59 | ||
|
47b1b251bc | ||
|
73b26752b0 | ||
|
f14c20f20b | ||
|
ff2774985f | ||
|
ecd18dfbce | ||
|
6c313b0a58 | ||
|
c72a3f2492 | ||
|
bb491fa5ef | ||
|
0cffe803a5 | ||
|
f40ec85d39 | ||
|
35add93f04 | ||
|
620446303f | ||
|
d59317881a |
1
.gitignore
vendored
@@ -8,6 +8,5 @@ dist/
|
||||
|
||||
# Gramps
|
||||
data/tips.xml
|
||||
gramps/gen/const.py
|
||||
gramps/plugins/lib/holidays.xml
|
||||
po/.intltool-merge-cache
|
||||
|
@@ -27,5 +27,7 @@ able to run gramps from the source directory without setting PYTHONPATH
|
||||
|
||||
From this position, import gramps works great
|
||||
"""
|
||||
import os
|
||||
os.environ['GRAMPS_RESOURCES'] = os.path.dirname(os.path.abspath(__file__))
|
||||
import gramps.grampsapp as app
|
||||
app.main()
|
||||
|
9
INSTALL
@@ -15,11 +15,12 @@ version by deleting the installed directories (for example,
|
||||
/usr/lib/pythonx.x/site-packages/gramps
|
||||
/usr/lib/pythonx.x/dist-packages/gramps
|
||||
where pythonx.x is python2.7 or whatever version you installed gramps with.
|
||||
Also remove the gramps .egg files that are installed along the gramps directory.
|
||||
Also remove the gramps .egg files that are installed along with the gramps
|
||||
directory.
|
||||
|
||||
If you don't know the list of all files that Gramps installed, you can reinstall
|
||||
it with the --record option, and take a look at the list this produces (so
|
||||
python setup.py install --record grampsfiles.txt
|
||||
If you don't know the list of all files that Gramps installed, you can
|
||||
reinstall it with the --record option, and take a look at the list this
|
||||
produces (so python setup.py install --record grampsfiles.txt
|
||||
|
||||
GRAMPS is a python application, so loading happens on reading the
|
||||
files, meaning that files of a previous version that are no longer
|
||||
|
@@ -21,7 +21,6 @@ recursive-include windows *
|
||||
|
||||
# Remove files created in the build
|
||||
exclude data/tips.xml
|
||||
exclude gramps/gen/const.py
|
||||
exclude gramps/plugins/lib/holidays.xml
|
||||
exclude po/.intltool-merge-cache
|
||||
global-exclude *.pyc
|
||||
|
84
NEWS
@@ -1,3 +1,87 @@
|
||||
2013-05-15
|
||||
Version 3.4.4 of Gramps! "The Ministry of Silly Names", a maintenance release.
|
||||
* infinite recursion bug in narrative web generation
|
||||
* protection on family trees when using version 3.4 and 4.0 on the same PC (road to 4.0)
|
||||
* merging notes of media with citations now works
|
||||
* crash during Calculate Preview of a filtered XML export
|
||||
* fix annoying errors on navigation related to citations gramplet and tag object.
|
||||
* listing the Family Trees can corrupt them.
|
||||
* various fix around handling Gedcom file format
|
||||
* fix citations and sources import on ProGen format
|
||||
* better date handling and better alternate translation support on some textual reports according to locale under windows
|
||||
* avoid Errors when setting wrong value as markup for invalid dates (Preferences)
|
||||
* fix paragraph layout on PDF format or print output
|
||||
* New: New-Zealand holidays
|
||||
* Polish and backport code on XML import (road to 4.0)
|
||||
* Regular expression rules now use search rather than match, fix design issues on regex filter rules
|
||||
* Disable/Enable indent spouse on descendants tree
|
||||
* fix regular expressions on Place filter rule
|
||||
* consistency on cli arguments (road to 4.0)
|
||||
* fix call of non-existant process on references proxy, enhanced tests on proxy filter
|
||||
* fix NarWeb creation via cli for some non-english locales
|
||||
* Various updated translations: ca, de, fr, it, nl, pt_BR, ru, sv, uk
|
||||
|
||||
2013-03-19
|
||||
Version 3.4.3 of Gramps! "Whenever life gets you down, Mrs. Brown", a maintenance release.
|
||||
* Sorting (both in the main display window, and particularly in Narrative Web output) now uses PyICU (if that module is available). Inclusion of PyICU is 'strongly recommended'. This resolves a number of bugs particularly related to sorting of non-Latin characters, and sorting on MS Windows and Mac OS X. Some changes have been made in Narrative Web to support contractions for alphabetic indices.
|
||||
* The automatic Addon checking and download now works once again (the location used in Gramps 3.4.2 and before had been changed, so the the automatic process was no longer working).
|
||||
* Import from Pro-Gen has been updated (at last) to take account of the change to Citations (in 3.4.0)
|
||||
* Import and Export of address fields in GEDCOM has been improved so that the round-trip works properly.
|
||||
* GEDCOM Repositories not imported correctly from FTM for Windows and Heredis.
|
||||
* Fixes to a number of errors in filtering notes.
|
||||
* Fix some errors in determining whether someone is alive (e.g. for filtering out alive people).
|
||||
* Make availability of GraphViz settings depend on output format
|
||||
* Improve the descriptions and tooltip for GraphViz aspect ratio option
|
||||
* Fixed update problems with citation bottombar gramplet (bug #6336)
|
||||
* Fixed Open Document Text output in Book report (bug #6457)
|
||||
* A number of changes to Narrative Web:
|
||||
** Media objects attached to Marriage events and Sources are not included in Narrative Web Site
|
||||
** restructure the families index so families are indexed under both spouses, and the family name is normalised
|
||||
** separate out Families section in individual and families pages so individual page links to the family page and family page links to both people
|
||||
** normalise links to families so the link is only displayed if the family page is present, and the gid is included when appropriate
|
||||
** remove highlighting of media subregions except in the media pages (it was confusing and not very well implemented)
|
||||
** include people whose surname is absent in the individual, surname and families indexes
|
||||
** html_escape names and surnames
|
||||
** always display media thumbnails for first image in Gallery list (in some cases they were suppressed if they had been displayed at the top of the page)
|
||||
** change partner and parent columns in families index to improve the layout of the HTML and put the comma between multiple partners in the right place
|
||||
** use event description (where present) instead of just event type in back references
|
||||
** fix bug in the way obj_dict and bkref_dict were initialised
|
||||
** fix missing document.png for missing media
|
||||
** fixed problems that bibliography ignores media attached to citations, so if that is the only 'interesting' thing about the citation, the citation media is not output
|
||||
** Replaced person link routine with one that takes into account whether there is a page for the person.
|
||||
** Included repository reference media type and call number in the 'Repositories' section of the relevant source instead of the Repository page.
|
||||
** Implemented a generalised back reference function to display the 'References' section of all pages. This recursively displays references till one is found for which a page exists.
|
||||
** Removed list of people and families from heading of the event pages as these are now in the 'References' section.
|
||||
** Fixed bug "0005968: Narrated Web Site not copying Source Citations files such as jpg or pdf docs to web site
|
||||
** Fixed bug "0005946 GRAMPS failed to insert jpeg image into proper place for an event" by displaying a thumbnail for citation media in the 'Source References' section (with a link to the media page)
|
||||
** Tidy up media pages - remove unused parameters, use list of media items generated in first pass. Should fix bugs 2365, 5905 and 6009.
|
||||
** Tidy up sources pages - fix numbering of repositories, remove unused parameters, fix title of individual source pages
|
||||
** Bug: reset NarrWeb navigation menu layout when style sheet doesn't support it
|
||||
** Change Source Pages to use the list of sources generated by the first pass that finds objects to be output, and simplify references section on the Source page to use the references passed to it.
|
||||
** Fix option to suppress Gramps ID (bug #6237)
|
||||
* a number of technical changes to Narrative Web
|
||||
** Removed a lot of redundant code and parameters (mainly connected with the old way of determining the objects to be included in the report).
|
||||
** Movement of some large chunks of code within the source file and some initial work towards GEPS 022: Narrative Website Refactor. Functionality should be unchanged.
|
||||
** Moved routines for calculating objects to be output so they can be part of default list building classes.
|
||||
* Various updated translations: da, de, es, fr, it, nb, nl, pt_BR, pt_PT, sv, uk
|
||||
|
||||
2012-10-28
|
||||
Version 3.4.2 -- the "We're all individuals!" bug fix release.
|
||||
* Some fixes on NarrativeWeb report
|
||||
* Some fixes on book report
|
||||
* Improvement on database path interface and user's preferences
|
||||
* Consistency on Name display and regex support
|
||||
* Some platform-specific fixes for Windows system environment
|
||||
* Better support for media links on Gedcom file format
|
||||
* Fix possible incorrect family relations on Gedcom file format
|
||||
* Various fixes on citation records
|
||||
* Fix and improve places handling on Geography views
|
||||
* Fix on command line arguments
|
||||
* Consistency on PDF file format
|
||||
* New language: Greek
|
||||
* Various updated translations
|
||||
* Changelog: http://www.gramps-project.org/bugs/changelog_page.php?version_id=32
|
||||
|
||||
2012-08-23
|
||||
Version 3.4.1 -- The "A tiger? In Africa?!" bug fix release.
|
||||
Mention in the release that upgrading is advised for two critical issues:
|
||||
|
65
README
@@ -1,40 +1,62 @@
|
||||
$Id$
|
||||
|
||||
Please read the COPYING file first.
|
||||
|
||||
If building from source, also read the INSTALL file (at least through the
|
||||
"SUPER-SHORT VERSION") before going further.
|
||||
|
||||
Requirements
|
||||
--------------------------------
|
||||
The following packages *MUST* be installed in order for Gramps to work:
|
||||
Python 2.7 or greater, Python 3.2 or greater (python version cannot be mixed)
|
||||
Python 2.7 or greater, Python 3.2 or greater (or both python versions)
|
||||
GTK 3.0 or greater
|
||||
pygobject 3.3.2 or greater
|
||||
cairo, pango, pangocairo with instrospection bindings (the gi packages)
|
||||
cairo, pango, pangocairo with introspection bindings (the gi packages)
|
||||
librsvg2 (svg icon view)
|
||||
xdg-utils
|
||||
bsddb3 is required for Python 3.2 (not python 2.7)
|
||||
|
||||
The following package is needed for full translation of the interface
|
||||
to your language:
|
||||
language-pack-gnome-xx
|
||||
Translation of GTK elements to your language, with
|
||||
xx your language code eg for Dutch you need
|
||||
Translation of GTK elements to your language, with
|
||||
xx your language code; e.g. for Dutch you need
|
||||
language-pack-gnome-nl. The translation of the
|
||||
Gramps strings is included with the source code.
|
||||
Gramps strings is included with the gramps source.
|
||||
|
||||
|
||||
The following packages are *STRONGLY RECOMMENDED* to be installed:
|
||||
|
||||
osmgpsmap Used to show maps in the geography view.
|
||||
It may be osmgpsmap, osm-gps-map, or python-osmgpsmap,
|
||||
but the Python bindings for this must also be present.
|
||||
Without this the GeoView will not be active, see
|
||||
http://gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_Main_Window#Geography_Category
|
||||
The package is named osmgpsmap, osm-gps-map
|
||||
or python-osmgpsmap. Or obtain it from: http://nzjrs.github.com/osm-gps-map/
|
||||
!! PACKAGERS: unfortunately, at the moment (March 2013),
|
||||
the patches which gramps 4.0 needs osm-gps-map to have
|
||||
are not yet released (as a new osm-gps-map version). The
|
||||
osm-gps-map sources must be dated 6 February 2013 (or
|
||||
later) to have the necessary patches. You may obtain
|
||||
it from: http://nzjrs.github.com/osm-gps-map/ or else
|
||||
http://sourceforge.net/projects/gramps/files/Dependencies
|
||||
(The necessary version seems to be 0.8 -- or later.)
|
||||
|
||||
GraphViz Enable creation of graphs using GraphViz engine.
|
||||
Without this no beautiful graphs can be created.
|
||||
Without this, three reports cannot be run.
|
||||
Obtain it from: http://www.graphviz.org
|
||||
pyexiv2 Enables Gramps to manage Exif metadata embedded in your
|
||||
media. Gramps needs version 0.1.3 or greater.
|
||||
Obtain it from: http://tilloy.net/dev/pyexiv2/download.html
|
||||
|
||||
PyICU Improves localised sorting in Gramps. In particular, this
|
||||
applies to sorting in the various views and in the
|
||||
Narrative Web output. It is particularly helpful for
|
||||
non-Latin characters, for non-English locales and on MS
|
||||
Windows and Mac OS X platforms. If it is not available,
|
||||
sorting is done through built-in libraries. PyICU is
|
||||
fairly widely available through the package managers of
|
||||
distributions. See http://pyicu.osafoundation.org/
|
||||
(These are Python bindings for the ICU package.)
|
||||
|
||||
The following packages are optional
|
||||
|
||||
gtkspell Enable spell checking in the notes. Gtkspell depends on
|
||||
enchant. A version of gtkspell with gobject introspection
|
||||
is needed, so minimally version 3.0.0
|
||||
@@ -44,15 +66,22 @@ The following packages are optional
|
||||
http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_Manage_Family_Trees#Archiving_a_Family_Tree
|
||||
Only rcs is needed, NO python bindings are required
|
||||
|
||||
PIL Python Image Library is needed to convert non jpg images to
|
||||
jpg so as to include them in LaTeX output
|
||||
PIL Python Image Library is needed to crop
|
||||
images and also to convert non-JPG images to
|
||||
JPG so as to include them in LaTeX output.
|
||||
(For Python3 a different source may be needed.)
|
||||
|
||||
GExiv2 Enables Gramps to manage Exif metadata embedded in your
|
||||
media. Gramps needs version 0.5 or greater.
|
||||
See http://www.gramps-project.org/wiki/index.php?title=GEPS_029:_GTK3-GObject_introspection_Conversion#GExiv2_for_Image_metadata
|
||||
|
||||
ttf-freefont More font support in the reports
|
||||
|
||||
gir-webkit GObject introspection data of WebKit is required for the
|
||||
hidden view 'Htmlview', which allows websites to be opened in
|
||||
Gramps. Users can unhide the view in the plugin manager.
|
||||
A html renderer must be installed to use the view.
|
||||
hidden view 'Htmlview', which allows websites to be
|
||||
opened in Gramps. Users can unhide the view in the
|
||||
plugin manager. A html renderer must be installed to
|
||||
use the view.
|
||||
!! PACKAGERS, Test if on your distribution
|
||||
webkit and Gramps is stable. If you obtain crashes, patch
|
||||
src/plugins/view/htmlrenderer.py and
|
||||
@@ -60,10 +89,10 @@ The following packages are optional
|
||||
from gi.repository import WebKit as webkit
|
||||
|
||||
goocanvas2:
|
||||
Required for the Graphview plugin
|
||||
Required for the (user-downloadable) Graphview plugin
|
||||
|
||||
No longer needed in 4.0:
|
||||
pygoocanvas, pygtk
|
||||
pygoocanvas, pygtk, pyexiv2
|
||||
No longer needed in 3.3:
|
||||
python-enchant Enchant
|
||||
No longer needed in 3.2:
|
||||
|
@@ -1,11 +1,14 @@
|
||||
"UNSTABLE Gramps 4.0.0 Alpha1 release.
|
||||
$Id$
|
||||
|
||||
This is a technology preview to allow plugin writers and packagers-installer
|
||||
writers to update their plugins and scripts. This release is not production
|
||||
ready, so use for testing!"
|
||||
UNSTABLE Gramps 4.0.0 Beta2 release.
|
||||
|
||||
It is recommended to use Gramps 4.0.0 with python 3.2 so as to be ready
|
||||
for the future (python 2.7 works though).
|
||||
This is a technology preview to allow distribution packagers (and plugin
|
||||
writers) to update their scripts (and plugins). This release is not
|
||||
production ready, so only use it for testing!
|
||||
|
||||
It is recommended that Gramps 4.0.0 be used with python 2.7 since many
|
||||
dependent packages do not yet have python 3 versions. A determined person
|
||||
can probably download their sources and build them, however.
|
||||
|
||||
The dependencies for Gramps 4.0.0 are _completely_ different than 3.4 due
|
||||
to the switch to GObject introspection, and the removal of autotools. So
|
||||
|
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 137 B After Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 136 B After Width: | Height: | Size: 136 B |
Before Width: | Height: | Size: 183 B After Width: | Height: | Size: 183 B |
Before Width: | Height: | Size: 144 B After Width: | Height: | Size: 144 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
18
data/evidencestyle/README
Normal file
@@ -0,0 +1,18 @@
|
||||
* Original evidence_style templates are provided in the public domain courtesy of
|
||||
John H. Yates (see more info on http://jytangledweb.org/genealogy/evidencestyle )
|
||||
|
||||
* Several fixes done in the csv file which I believe were errors
|
||||
|
||||
* Run
|
||||
|
||||
$ python evidencefield.py
|
||||
|
||||
to generate two files with python code usable in srcattrtype.py in Gramps.
|
||||
|
||||
* If in the future one wants to insert _NEW_ evidence styles, add them at the
|
||||
bottom of the csv file, generate the data, and copy to srcattrtype.py
|
||||
|
||||
* CAREFUL: When adding or changing things, DON'T change the type of already
|
||||
released versions in Gramps! That means the integer indexes used must remain
|
||||
the same! If only styles are added at the bottom and no lines removed,
|
||||
this should not be a problem.
|
3144
data/evidencestyle/evidence_style.csv
Normal file
469
data/evidencestyle/evidencefieldgenerator.py
Normal file
@@ -0,0 +1,469 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
This module parses the evidence csv file and generates the code we need in
|
||||
Gramps to use the evidence style.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import csv
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Code
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
csvfilename = "evidence_style.csv"
|
||||
NRCOL = 0
|
||||
CATCOL = 1
|
||||
CATTYPECOL = 2
|
||||
TYPECOL = 3
|
||||
DESCRCOL= 4
|
||||
CITETYPECOL = 5
|
||||
IDENTCOL = 6
|
||||
LDELCOL = 7 # left delimiter
|
||||
FIELDCOL = 8
|
||||
LABELCOL = 9
|
||||
RDELCOL = 10 # right delimiter
|
||||
GEDCOMCOL = 11
|
||||
SHORTERCOL = 12
|
||||
STYLECOL = 13
|
||||
PRIVACYCOL = 14
|
||||
OPTCOL = 15
|
||||
HINTCOL = 16
|
||||
TOOLTIPCOL = 17
|
||||
|
||||
CITE_TYPES = {'F': 'REF_TYPE_F', 'L': 'REF_TYPE_L', 'S': 'REF_TYPE_S'}
|
||||
GEDCOMFIELDS = {'A': 'GED_AUTHOR', 'T': 'GED_TITLE',
|
||||
'P': 'GED_PUBINF', 'D': 'GED_DATE'}
|
||||
SHORTERALG = {'LOC': 'SHORTERALG_LOC', 'YEAR': 'SHORTERALG_YEAR',
|
||||
'ETAL': 'SHORTERALG_ETAL', 'REV.': 'SHORTERALG_REVERT_TO_DOT'}
|
||||
STYLES = {'Quoted': 'STYLE_QUOTE', 'Italics': 'STYLE_EMPH',
|
||||
'QuotedCont': 'STYLE_QUOTECONT', 'Bold': 'STYLE_BOLD'}
|
||||
|
||||
#already defined srcattrtypes
|
||||
KNOWN_FIELDS = ['EVEN_REC', 'EVEN_CITED', 'EVEN_ROLE', 'GEN_BY', 'REPOSITORY',
|
||||
'REPOSITORY_ADDRESS', 'REPOSITORY_SHORT_VERSION', 'REPOSITORY_CALL_NUMBER',
|
||||
'DATE']
|
||||
|
||||
DEFAULT_HINTS = {
|
||||
"ACT": "Public Law 12-98",
|
||||
"ADDRESS": "Broadway Avenue, New York",
|
||||
"AFFILIATION": "Agent of Gramps Software",
|
||||
"AUTHOR": "Doe, D.P. & Cameron, E.",
|
||||
"AUTHOR_LOCATION": "Chicago",
|
||||
"BOOK": "The big example Gramps manual",
|
||||
"CASE": "B. Malengier versus N. Hall",
|
||||
"CEMETERY": "Greenwich Cemetery Office",
|
||||
"CHAPTER": "The first office of T. Rooseveld",
|
||||
"CHAPTER_PAGES": "24-55",
|
||||
"COLLECTION": "Bruges Lace Collection",
|
||||
"COLUMN": "col. 3",
|
||||
"COMPILER": "T. Da Silva",
|
||||
"CREATION_DATE": "13 Aug 1965",
|
||||
"CREATOR": "P. Picasso",
|
||||
"CREDIT_LINE": "Based on unnamed document lost in fire",
|
||||
"DATE": "17 Sep 1745",
|
||||
"DATE_ACCESSED": "18 Jun 2013",
|
||||
"DATE_RANGE": "2003-6",
|
||||
"DESCRIPTION": "The lace has inscriptions with names of nobility",
|
||||
"DISTRICT": "Enumeration district (ED) 14",
|
||||
"DIVISION": "Peterburg Post Office, or Portland, ward 4",
|
||||
"EDITION": "Second Edition",
|
||||
"EDITOR": "Hoover, J.E.",
|
||||
"FILE": "Membership application J. Rapinat",
|
||||
"FILE_DATE": "15 Jan 1870",
|
||||
"FILE_LOCATION": "Accession 7, Box 3",
|
||||
"FILE_NO": "1243-EB-98",
|
||||
"FILE_UNIT": "Letters to George Washington",
|
||||
"FILM_ID": "T345",
|
||||
"FILM_PUBLICATION_PLACE": "Kansas City",
|
||||
"FILM_PUBLISHER": "NY Genealogy Association",
|
||||
"FILM_TYPE": "FHL microfilm",
|
||||
"FORMAT": "Digital Images, or Database, or Cards, ...",
|
||||
"FRAME": "frames 387-432",
|
||||
"GROUP": "Miami Patent Office",
|
||||
"HOUSEHOLD": "dwelling 345, family 654",
|
||||
"ID": "I50-68, or 1910 U.S. census, or ...",
|
||||
"INSTITUTION": "Sorbonne University",
|
||||
"INTERVIEWER": "Materley, B.",
|
||||
"ISSUE_DATE": "Jun 2004",
|
||||
"ISSUE_RANGE": "145-394, scattered issues",
|
||||
"ITEM_OF_INTEREST": "entry for G. Galileo, or Doe Household, or A. Einstein Grave ...",
|
||||
"JURISDICTION": "Jackson County, Alabama",
|
||||
"LOCATION": "Istanbul",
|
||||
"NUMBER": "2, or Record Group 34, or ...",
|
||||
"NUMBER_6TOTAL9": "5",
|
||||
"ORIGINAL_REPOSITORY": "National Archives",
|
||||
"ORIGINAL_REPOSITORY_LOCATION": "Washington, D.C.",
|
||||
"ORIGINAL_YEAR": "1966",
|
||||
"PAGE": "5; or 4,6-8, ...",
|
||||
"PAGE_RANGE": "1-13",
|
||||
"PART": "Part 3",
|
||||
"PLACE_CREATED": "London",
|
||||
"POSITION": "written in the left margin, or second row, 3th line",
|
||||
"POSTING_DATE": "5 Jul 1799",
|
||||
"PROFESSIONAL_CREDENTIALS": "Prof.; or Dr. ...",
|
||||
"PROVENANCE": "add provenance of the material",
|
||||
"PUBLICATION_FORMAT": "CD-ROM or eprint or ...",
|
||||
"PUBLICATION_PLACE": "Berlin",
|
||||
"PUBLICATION_TITLE": "Title of Blog, Newsletter, DVD, ...",
|
||||
"PUBLICATION_YEAR": "2014",
|
||||
"PUBLISHER": "Springer",
|
||||
"PUB_INFO": "Springer, Berlin, 2014",
|
||||
"RECIPIENT": "J. Ralls",
|
||||
"RELATIONSHIP": "Paul's uncle and brother of Erik",
|
||||
"REPORT_DATE": "3 May 1999",
|
||||
"RESEARCH_COMMENT": "Descriptive detail or provenance or research analysis conclusion, ...",
|
||||
"RESEARCH_PROJECT": "Tahiti Natives",
|
||||
"ROLL": "176, or rolls 145-160",
|
||||
"SCHEDULE": "population schedule or slave schedule or ...",
|
||||
"SECTION": "1890 section or ER patients or ...",
|
||||
"SERIES": "Carnival County Records",
|
||||
"SERIES_NO": "series 34-38",
|
||||
"SESSION": "2nd session",
|
||||
"SHEET_NO": "sheet 13-C",
|
||||
"SUBJECT": "D. Copernicus and close family",
|
||||
"SUBSERIES": "",
|
||||
"SUBTITLE": "Subtitle of article or magazine ...",
|
||||
"TERM": "June Term 1934 or 13th Congress or Reagan Office or ...",
|
||||
"TIMESTAMP": "min. 34-36",
|
||||
"TITLE": "Diary Title, Message Title, Bible Name, Article Title, ...",
|
||||
"TRANSLATION": "A translated version, typically of the title",
|
||||
"TYPE": "Letter",
|
||||
"URL_6DIGITAL_LOCATION9": "http://gramps-project.org/blog",
|
||||
"VOLUME": "4",
|
||||
"VOLUME_INFO": "5 volumes",
|
||||
"WEBSITE": "gramps-project.org",
|
||||
"WEBSITE_CREATOR_OR_OWNER": "Family Historians Inc",
|
||||
"YEAR": "1888",
|
||||
"YEAR_ACCESSED": "2013",
|
||||
}
|
||||
|
||||
DEFAULT_TOOLTIPS = {
|
||||
"ACT": "A statute or law name passed by a legislature",
|
||||
"ADDRESS": "Store address information. Set Private if needed! Give"
|
||||
" information from lowest to highest level separated by comma's",
|
||||
"AFFILIATION": "A relevant affiliation that might influence data in the source",
|
||||
"AUTHOR": "Give names in following form: 'FirstAuthorSurname, Given Names & SecondAuthorSurname, Given Names'."
|
||||
" Like this Gramps can parse the name and shorten as needed.",
|
||||
"AUTHOR_LOCATION": "City where author resides or wrote.",
|
||||
"BOOK": "Title of the Book",
|
||||
"CASE": "Dispute between opposing parties in a court of law.",
|
||||
"CEMETERY": "Name of cemetery or cemetery office with sources.",
|
||||
"CHAPTER": "",
|
||||
"CHAPTER_PAGES": "The pages in the chapter.",
|
||||
"COLLECTION": "",
|
||||
"COLUMN": "",
|
||||
"COMPILER": "The name of the person who compiled the source.",
|
||||
"CREATION_DATE": "",
|
||||
"CREATOR": "The name of the creator of the artifact.",
|
||||
"CREDIT_LINE": "Acknowledgement of writers and contributors",
|
||||
"DATE": "",
|
||||
"DATE_ACCESSED": "",
|
||||
"DATE_RANGE": "The range of years which are present in the source.",
|
||||
"DESCRIPTION": "Some important detail of the source.",
|
||||
"DISTRICT": "District as handled by Census",
|
||||
"DIVISION": "The subdivision of a larger group that is handled in the source.",
|
||||
"EDITION": "",
|
||||
"EDITOR": "The Editor of a multi-author book.",
|
||||
"FILE": "The title of a specific file in a source.",
|
||||
"FILE_DATE": "Date of submitting the document to a clerk or court.",
|
||||
"FILE_LOCATION": "Accession method to the file",
|
||||
"FILE_NO": "Number to indicate a file",
|
||||
"FILE_UNIT": "A grouping unit for a number of files in a source.",
|
||||
"FILM_ID": "ID of a Microfilm.",
|
||||
"FILM_PUBLICATION_PLACE": "",
|
||||
"FILM_PUBLISHER": "",
|
||||
"FILM_TYPE": "The type of the microfilm.",
|
||||
"FORMAT": "The format of the source.",
|
||||
"FRAME": "What frames in the source are relevant.",
|
||||
"GROUP": "A larger grouping to which the source belongs.",
|
||||
"HOUSEHOLD": "Household of interest on a census.",
|
||||
"ID": "ID to identify the source or citation part",
|
||||
"INSTITUTION": "Institution that issued the source.",
|
||||
"INTERVIEWER": "",
|
||||
"ISSUE_DATE": "Date the source was issued.",
|
||||
"ISSUE_RANGE": "A range of magazine, journal, ... issues covered in the source",
|
||||
"ITEM_OF_INTEREST": "Specific part, item, or person of interest in the source",
|
||||
"JURISDICTION": "Area with a set of laws under the control of a system of courts or government entity."
|
||||
" Enter this from lowest to highest relevant jurisdiction, separated by comma's.",
|
||||
"LOCATION": "City that is relevant.",
|
||||
"NUMBER": "A number.",
|
||||
"NUMBER_6TOTAL9": "The maximum of entities available.",
|
||||
"ORIGINAL_REPOSITORY": "Name of the repository where the original is stored.",
|
||||
"ORIGINAL_REPOSITORY_LOCATION": "Address or only city of the repository where the original is stored.",
|
||||
"ORIGINAL_YEAR": "Year the original source was published/created",
|
||||
"PAGE": "The page or page(s) relevant for the citation",
|
||||
"PAGE_RANGE": "The range of the pages in the source. The page given for"
|
||||
" a citation must be in this range.",
|
||||
"PART": "",
|
||||
"PLACE_CREATED": "",
|
||||
"POSITION": "Where in or on the source the citation piece can be found.",
|
||||
"POSTING_DATE": "",
|
||||
"PROFESSIONAL_CREDENTIALS": "",
|
||||
"PROVENANCE": "Where the material originated from.",
|
||||
"PUBLICATION_FORMAT": "",
|
||||
"PUBLICATION_PLACE": "",
|
||||
"PUBLICATION_TITLE": "",
|
||||
"PUBLICATION_YEAR": "",
|
||||
"PUBLISHER": "",
|
||||
"PUB_INFO": "Publication Information, such as city and year of publication, name of publisher, ...",
|
||||
"RECIPIENT": "The person to who the letter is addressed.",
|
||||
"RELATIONSHIP": "The relationship of the author to the person of interest that is the subject.",
|
||||
"REPORT_DATE": "Date the report was written/submitted.",
|
||||
"RESEARCH_COMMENT": "Descriptive detail or provenance or research analysis conclusion, ...",
|
||||
"RESEARCH_PROJECT": "The genealogical or scientific research project.",
|
||||
"ROLL": "The Microfilm role.",
|
||||
"SCHEDULE": "The census schedule (the type of census table) used, eg population schedule or slave schedule. or ...",
|
||||
"SECTION": "The section or subgroup under which filed, eg 'Diplomatic correspondance, 1798-1810'",
|
||||
"SERIES": "",
|
||||
"SERIES_NO": "",
|
||||
"SESSION": "The number of the meeting or series of connected meetings devoted "
|
||||
"by a legislature to a single order of business, program, agenda, or announced purpose.",
|
||||
"SHEET_NO": "Number of a census sheet.",
|
||||
"SUBJECT": "",
|
||||
"SUBSERIES": "",
|
||||
"SUBTITLE": "",
|
||||
"TERM": "Reference to the time a person/group/parliament is in office or session.",
|
||||
"TIMESTAMP": "Indication of the time in audio or video where the relevant fragment can be found.",
|
||||
"TITLE": "",
|
||||
"TRANSLATION": "A translated version, typically of the title",
|
||||
"TYPE": "",
|
||||
"URL_6DIGITAL_LOCATION9": "Detailed internet address of the content",
|
||||
"VOLUME": "",
|
||||
"VOLUME_INFO": "Information about the volumes, eg the amount of volumes.",
|
||||
"WEBSITE": "The main internet address.",
|
||||
"WEBSITE_CREATOR_OR_OWNER": "Organization or person behind a website.",
|
||||
"YEAR": "",
|
||||
"YEAR_ACCESSED": "",
|
||||
}
|
||||
|
||||
|
||||
nr = -1
|
||||
cat = ''
|
||||
cattype = ''
|
||||
type = ''
|
||||
descr = ''
|
||||
cite_type = ''
|
||||
ident = ''
|
||||
|
||||
TYPE2CITEMAP = {}
|
||||
FIELDTYPEMAP = {}
|
||||
FIELDS_SHORT = []
|
||||
index = 100
|
||||
indexval = 10
|
||||
first = True
|
||||
|
||||
with open(csvfilename, 'rb') as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=';')
|
||||
for row in reader:
|
||||
if first:
|
||||
#skip first row with headers
|
||||
first=False
|
||||
continue
|
||||
|
||||
if row[CATCOL]:
|
||||
cat = row[CATCOL].strip()
|
||||
if cat.startswith('EE '):
|
||||
cat = cat[3:]
|
||||
EE = True
|
||||
else:
|
||||
EE = False
|
||||
cattype = row[CATTYPECOL].strip()
|
||||
types = row[TYPECOL].strip()
|
||||
descr = row[DESCRCOL].strip()
|
||||
source_type = row[IDENTCOL].strip()
|
||||
if descr:
|
||||
source_descr = '%s - %s - %s (%s)' % (cat, cattype, types, descr)
|
||||
if not EE:
|
||||
source_descr_code = "_('%(first)s - %(sec)s - %(third)s (%(fourth)s)') % { "\
|
||||
" 'first': _('" + cat + "'),"\
|
||||
" 'sec': _('" + cattype + "'),"\
|
||||
" 'third': _('" + types + "'),"\
|
||||
" 'fourth': _('" + descr + "')}"
|
||||
else:
|
||||
source_descr_code = "_('EE %(first)s - %(sec)s - %(third)s (%(fourth)s)') % { "\
|
||||
" 'first': _('" + cat + "'),"\
|
||||
" 'sec': _('" + cattype + "'),"\
|
||||
" 'third': _('" + types + "'),"\
|
||||
" 'fourth': _('" + descr + "')}"
|
||||
else:
|
||||
source_descr = '%s - %s - %s' % (cat, cattype, types)
|
||||
if not EE:
|
||||
source_descr_code = "_('%(first)s - %(sec)s - %(third)s') % { "\
|
||||
" 'first': _('" + cat + "'),"\
|
||||
" 'sec': _('" + cattype + "'),"\
|
||||
" 'third': _('" + types + "')}"
|
||||
else:
|
||||
source_descr_code = "_('EE %(first)s - %(sec)s - %(third)s') % { "\
|
||||
" 'first': _('" + cat + "'),"\
|
||||
" 'sec': _('" + cattype + "'),"\
|
||||
" 'third': _('" + types + "')}"
|
||||
if source_type in TYPE2CITEMAP:
|
||||
assert TYPE2CITEMAP[source_type] ['descr'] == source_descr, source_type + ' ' + TYPE2CITEMAP[source_type] ['descr'] + ' NOT ' + source_descr
|
||||
else:
|
||||
TYPE2CITEMAP[source_type] = {'REF_TYPE_L': [], 'REF_TYPE_F': [],
|
||||
'REF_TYPE_S': [],
|
||||
'i': indexval, 'descr': source_descr,
|
||||
'descrcode': source_descr_code}
|
||||
indexval += 1
|
||||
|
||||
if row[CITETYPECOL]:
|
||||
#new citation type,
|
||||
cite_type = row[CITETYPECOL].strip()
|
||||
if cite_type == 'S':
|
||||
shortcite = True
|
||||
else:
|
||||
shortcite = False
|
||||
cite_type = CITE_TYPES[cite_type]
|
||||
#add field for template to evidence style
|
||||
field = row[FIELDCOL].strip()
|
||||
field_type = field.replace(' ', '_').replace("'","")\
|
||||
.replace('&','AND').replace('(', '6').replace(')','9')\
|
||||
.replace('[', '').replace(']','').replace('/', '_OR_')\
|
||||
.replace(',', '').replace('.', '').replace(':', '')\
|
||||
.replace('-', '_')
|
||||
field_descr = field.replace('[', '').replace(']','').lower().capitalize()
|
||||
field_label = row[LABELCOL].strip()
|
||||
field_label = field_label.replace("'", "\\'")
|
||||
if field_type in FIELDTYPEMAP:
|
||||
assert field_descr == FIELDTYPEMAP[field_type][1], 'Problem %s %s %s' % (field_type, field_descr, FIELDTYPEMAP[field_type][1])
|
||||
elif field_type in KNOWN_FIELDS:
|
||||
#no need to add it
|
||||
pass
|
||||
else:
|
||||
FIELDTYPEMAP[field_type] = (index, field_descr)
|
||||
index += 1
|
||||
fielddata = []
|
||||
private = 'False'
|
||||
if row[PRIVACYCOL].strip():
|
||||
private = 'True'
|
||||
optional = 'False'
|
||||
if row[OPTCOL].strip():
|
||||
optional = 'True'
|
||||
shorteralg = SHORTERALG.get(row[SHORTERCOL].strip()) or 'EMPTY'
|
||||
gedcommap = GEDCOMFIELDS.get(row[GEDCOMCOL].strip()) or 'EMPTY'
|
||||
style = STYLES.get(row[STYLECOL].strip()) or 'EMPTY'
|
||||
hint = row[HINTCOL]
|
||||
tooltip = row[TOOLTIPCOL]
|
||||
|
||||
TYPE2CITEMAP[source_type][cite_type] += [(row[LDELCOL], field_type,
|
||||
row[RDELCOL], field_label, style, private, optional,
|
||||
shorteralg, gedcommap, hint, tooltip)]
|
||||
#if shorttype, we store a type for the short version so user can store
|
||||
#this
|
||||
if shortcite and shorteralg == 'EMPTY':
|
||||
field_type_short = field_type + '_SHORT_VERSION'
|
||||
if field_type_short in FIELDTYPEMAP or field_type_short in KNOWN_FIELDS:
|
||||
pass
|
||||
else:
|
||||
FIELDTYPEMAP[field_type_short] = (index, field_descr + ' (Short)')
|
||||
FIELDS_SHORT.append(field_type_short)
|
||||
index += 1
|
||||
|
||||
#now generate the python code we need in source attr types
|
||||
code = " #following fields are generated with evidencefieldgenerator.py\n" \
|
||||
" #the index starts at 100!\n"
|
||||
datamap = "\n _DATAMAP += [\n"
|
||||
allkeys = sorted(FIELDTYPEMAP.keys())
|
||||
for field_type in allkeys:
|
||||
code += " " + field_type + ' = %d\n' % FIELDTYPEMAP[field_type][0]
|
||||
datamap += ' (' + field_type + ', _("' + FIELDTYPEMAP[field_type][1] \
|
||||
+'"), "' + FIELDTYPEMAP[field_type][1] + '"),\n'
|
||||
code += "\n _DATAMAPIGNORE = [\n"
|
||||
for field in FIELDS_SHORT:
|
||||
code += " " + field + ',\n'
|
||||
code += ' ]\n\n' + datamap + ' ]\n'
|
||||
|
||||
#now add default hints
|
||||
code += "\n _DEFAULT_HINTS = {\n"
|
||||
for key in sorted(DEFAULT_HINTS.keys()):
|
||||
if DEFAULT_HINTS[key]:
|
||||
code += " " + key +': _("' + DEFAULT_HINTS[key] + '"),\n'
|
||||
code += " }\n"
|
||||
#now add default tooltips
|
||||
code += "\n _DEFAULT_TOOLTIPS = {\n"
|
||||
for key in sorted(DEFAULT_TOOLTIPS.keys()):
|
||||
if DEFAULT_TOOLTIPS[key]:
|
||||
code += " " + key + ': _("' + DEFAULT_TOOLTIPS[key] + '"),\n'
|
||||
code += " }\n"
|
||||
|
||||
with open('srcattrtype_extra.py', 'wb') as srcattrfile:
|
||||
srcattrfile.write(code)
|
||||
|
||||
#now generate the python code we need in evidencestyle
|
||||
# we have predefined sourcetypes, and these have a template for formatting
|
||||
#
|
||||
|
||||
#first an English to internationalized map
|
||||
code = " #SRCTEMPLATE has some predefined values which map to citation styles\n"
|
||||
|
||||
datamap = " _SRCTEMPLATEVAL_MAP = [\n"\
|
||||
" (UNKNOWN, _('Unknown'), 'Unknown'),\n"
|
||||
allkeys = sorted(TYPE2CITEMAP.keys())
|
||||
for source_type in allkeys:
|
||||
code += " " + source_type + ' = %d\n' % TYPE2CITEMAP[source_type]['i']
|
||||
# we use descrcode in to translate string to reduce work for translators
|
||||
datamap += " (" + source_type + ", " + TYPE2CITEMAP[source_type]['descrcode'] \
|
||||
+", '" + source_type+ "'),\n"
|
||||
|
||||
code += '\n # Localization of the different source types\n'\
|
||||
+ datamap + ' ]\n'
|
||||
|
||||
code += "\n #templates for the source types defined\n"\
|
||||
" # F: Full reference\n"\
|
||||
" # S: Short reference (if F used once, use S afterwards)\n" \
|
||||
" # L: List reference (for in bibliography list)\n"
|
||||
code += ' EVIDENCETEMPLATES = {\n'
|
||||
for source_type in allkeys:
|
||||
code += " " + source_type + ": {\n"
|
||||
for val in ['REF_TYPE_L', 'REF_TYPE_F', 'REF_TYPE_S']:
|
||||
code += " " + val + ": [\n"
|
||||
for field in TYPE2CITEMAP[source_type][val]:
|
||||
# field is tuple (row[LDELCOL], field_type, row[RDELCOL],
|
||||
# field_label, row[STYLECOL]
|
||||
# , private, optional, shorteralg, gedcommap, hint, tooltip)
|
||||
if field[9]:
|
||||
hint = '_("' + field[9] + '")'
|
||||
else:
|
||||
hint = 'None'
|
||||
if field[10]:
|
||||
tooltip = '_("' + field[10] + '")'
|
||||
else:
|
||||
tooltip = 'None'
|
||||
code += " ('"+ field[0] + "', SrcAttributeType." + field[1] + ", _('"\
|
||||
+field[3] + "'), '"+ field[2] + "', " + field[4] + ", " + field[5] + ", "\
|
||||
+ field[6] + ", " + field[7] + ", " + field[8] + ",\n" \
|
||||
+ " " +hint + ", " + tooltip + "),\n"
|
||||
code += " ],\n"
|
||||
code += " },\n"
|
||||
code += " }\n"
|
||||
|
||||
with open('srcattrtype_extraevidence.py', 'wb') as srcattrfile:
|
||||
srcattrfile.write(code)
|
98
data/evidencestyle/extract_trans_csv.py
Normal file
@@ -0,0 +1,98 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2013 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
This module parses the evidence csv file and generates the code we need in
|
||||
Gramps to use the evidence style.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import csv
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Code
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
csvfilename = "evidence_style.csv"
|
||||
NRCOL = 0
|
||||
CATCOL = 1
|
||||
CATTYPECOL = 2
|
||||
TYPECOL = 3
|
||||
DESCRCOL= 4
|
||||
CITETYPECOL = 5
|
||||
IDENTCOL = 6
|
||||
LDELCOL = 7 # left delimiter
|
||||
FIELDCOL = 8
|
||||
LABELCOL = 9
|
||||
RDELCOL = 10 # right delimiter
|
||||
GEDCOMCOL = 11
|
||||
SHORTERCOL = 12
|
||||
STYLECOL = 13
|
||||
PRIVACYCOL = 14
|
||||
OPTCOL = 15
|
||||
HINTCOL = 16
|
||||
TOOLTIPCOL = 17
|
||||
|
||||
first = True
|
||||
|
||||
trans = {}
|
||||
with open(csvfilename, 'rb') as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=';')
|
||||
for row in reader:
|
||||
if first:
|
||||
first=False
|
||||
continue
|
||||
elif row[CATCOL]:
|
||||
cat = row[CATCOL].strip()
|
||||
cattype = row[CATTYPECOL].strip()
|
||||
types = row[TYPECOL].strip()
|
||||
descr = row[DESCRCOL].strip()
|
||||
|
||||
for val in [cat, cattype, types, descr]:
|
||||
if val and val not in trans:
|
||||
trans[val] = '_("' + val + '")'
|
||||
val = row[HINTCOL]
|
||||
if val and val not in trans:
|
||||
trans[val] = '_("' + val + '")'
|
||||
val = row[TOOLTIPCOL]
|
||||
if val and val not in trans:
|
||||
trans[val] = '_("' + val + '")'
|
||||
|
||||
|
||||
|
||||
#now generate the python code we need in source attr types
|
||||
code = "#following translations are generated with extract_trans_csv.py\n"
|
||||
code += "if False:\n"
|
||||
code += " #these translations will only occur when needed first time!\n"
|
||||
|
||||
allkeys = sorted(trans.keys())
|
||||
for field in allkeys:
|
||||
code += " " + trans[field] + '\n'
|
||||
|
||||
with open('csv_trans.py', 'wb') as srcattrfile:
|
||||
srcattrfile.write(code)
|
@@ -229,17 +229,16 @@ SOURCES
|
||||
-->
|
||||
|
||||
<!ELEMENT sources (source)*>
|
||||
<!ELEMENT source (stitle?, sauthor?, spubinfo?, sabbrev?,
|
||||
noteref*, objref*, data_item*, reporef*, tagref*)>
|
||||
<!ELEMENT source (sname?, stemplate?, sabbrev?,
|
||||
noteref*, objref*, srcattribute*, reporef*, tagref*)>
|
||||
<!ATTLIST source
|
||||
id CDATA #IMPLIED
|
||||
handle ID #REQUIRED
|
||||
priv (0|1) #IMPLIED
|
||||
change CDATA #REQUIRED
|
||||
>
|
||||
<!ELEMENT stitle (#PCDATA)>
|
||||
<!ELEMENT sauthor (#PCDATA)>
|
||||
<!ELEMENT spubinfo (#PCDATA)>
|
||||
<!ELEMENT sname (#PCDATA)>
|
||||
<!ELEMENT stemplate (#PCDATA)>
|
||||
<!ELEMENT sabbrev (#PCDATA)>
|
||||
|
||||
<!-- ************************************************************
|
||||
@@ -368,14 +367,15 @@ CITATIONS
|
||||
|
||||
<!ELEMENT citations (citation)*>
|
||||
|
||||
<!ELEMENT citation ((daterange|datespan|dateval|datestr)?, page?, confidence?,
|
||||
noteref*, objref*, data_item*, sourceref, tagref*)>
|
||||
<!ELEMENT citation ((daterange|datespan|dateval|datestr)?, cname?, confidence?,
|
||||
noteref*, objref*, srcattribute*, sourceref, tagref*)>
|
||||
<!ATTLIST citation
|
||||
id CDATA #IMPLIED
|
||||
handle ID #REQUIRED
|
||||
priv (0|1) #IMPLIED
|
||||
change CDATA #REQUIRED
|
||||
>
|
||||
<!ELEMENT cname (#PCDATA)>
|
||||
|
||||
<!-- ************************************************************
|
||||
BOOKMARKS
|
||||
@@ -494,6 +494,13 @@ SHARED ELEMENTS
|
||||
value CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT srcattribute EMPTY>
|
||||
<!ATTLIST srcattribute
|
||||
priv (0|1) #IMPLIED
|
||||
type CDATA #REQUIRED
|
||||
value CDATA #REQUIRED
|
||||
>
|
||||
|
||||
<!ELEMENT place EMPTY>
|
||||
<!ATTLIST place hlink IDREF #REQUIRED>
|
||||
|
||||
|
@@ -430,7 +430,7 @@
|
||||
<define name="citation-content">
|
||||
<ref name="primary-object"/>
|
||||
<optional><ref name="date-content"/></optional>
|
||||
<optional><element name="page"><text/></element></optional>
|
||||
<optional><element name="cname"><text/></element></optional>
|
||||
<optional><element name="confidence"><text/></element></optional>
|
||||
<zeroOrMore><element name="noteref">
|
||||
<ref name="noteref-content"/>
|
||||
@@ -438,9 +438,8 @@
|
||||
<zeroOrMore><element name="objref">
|
||||
<ref name="objref-content"/>
|
||||
</element></zeroOrMore>
|
||||
<zeroOrMore><element name="data_item">
|
||||
<attribute name="key"><text/></attribute>
|
||||
<attribute name="value"><text/></attribute>
|
||||
<zeroOrMore><element name="srcattribute">
|
||||
<ref name="srcattribute-content"/>
|
||||
</element></zeroOrMore>
|
||||
<element name="sourceref">
|
||||
<ref name="sourceref-content"/>
|
||||
@@ -449,9 +448,8 @@
|
||||
|
||||
<define name="source-content">
|
||||
<ref name="primary-object"/>
|
||||
<optional><element name="stitle"><text/></element></optional>
|
||||
<optional><element name="sauthor"><text/></element></optional>
|
||||
<optional><element name="spubinfo"><text/></element></optional>
|
||||
<optional><element name="sname"><text/></element></optional>
|
||||
<optional><element name="stemplate"><text/></element></optional>
|
||||
<optional><element name="sabbrev"><text/></element></optional>
|
||||
<zeroOrMore><element name="noteref">
|
||||
<ref name="noteref-content"/>
|
||||
@@ -459,9 +457,8 @@
|
||||
<zeroOrMore><element name="objref">
|
||||
<ref name="objref-content"/>
|
||||
</element></zeroOrMore>
|
||||
<zeroOrMore><element name="data_item">
|
||||
<attribute name="key"><text/></attribute>
|
||||
<attribute name="value"><text/></attribute>
|
||||
<zeroOrMore><element name="srcattribute">
|
||||
<ref name="srcattribute-content"/>
|
||||
</element></zeroOrMore>
|
||||
<zeroOrMore><element name="reporef">
|
||||
<ref name="reporef-content"/>
|
||||
@@ -671,6 +668,14 @@
|
||||
<ref name="noteref-content"/>
|
||||
</element></zeroOrMore>
|
||||
</define>
|
||||
|
||||
<define name="srcattribute-content">
|
||||
<optional><attribute name="priv">
|
||||
<ref name="priv-content"/>
|
||||
</attribute></optional>
|
||||
<attribute name="type"><text/></attribute>
|
||||
<attribute name="value"><text/></attribute>
|
||||
</define>
|
||||
|
||||
<define name="url-content">
|
||||
<optional><attribute name="priv">
|
||||
|
32
debian/control
vendored
@@ -1,27 +1,17 @@
|
||||
Source: gramps
|
||||
Section: gnome
|
||||
Maintainer: Gramps Development Team
|
||||
Section: python
|
||||
Priority: optional
|
||||
Maintainer: Stéphane Charette <stephanecharette@gmail.com>
|
||||
Build-Depends-Indep: libxml-parser-perl, python-gtk2, gettext, python-central (>= 0.5.6), python, intltool
|
||||
Build-Depends: debhelper (>= 7)
|
||||
Standards-Version: 3.8.3
|
||||
Build-Depends-Indep: libxml-parser-perl, gettext, intltool
|
||||
Build-Depends: python-all (>= 2.7.0), debhelper (>= 7.4.3)
|
||||
Standards-Version: 3.9.1
|
||||
Homepage: http://www.gramps-project.org/
|
||||
XS-Python-Version: >=2.5
|
||||
|
||||
Package: gramps
|
||||
Architecture: all
|
||||
Depends: ${python:Depends}, librsvg2-common, python-gtk2, python-pyexiv2, xdg-utils, graphviz, python-osmgpsmap ${misc:Depends}
|
||||
Replaces: gramps-manual, gramps-extending-doc
|
||||
Conflicts: gramps-manual, gramps-extending-doc, gramps-common, python-gtk-1.2
|
||||
Recommends:
|
||||
Suggests: ttf-freefont, python-enchant, python-gtkspell
|
||||
Description: Genealogical research program
|
||||
GRAMPS is an Open Source genealogy program written in Python, using
|
||||
the GTK/GNOME interface. It is an extremely flexible program fitting
|
||||
the needs for both the amateur genealogist and serious genealogical
|
||||
researcher.
|
||||
GRAMPS has the ability to import GEDCOM files exported from many
|
||||
proprietary genealogy programs and can produce a large number of
|
||||
reports in many popular formats.
|
||||
XB-Python-Version: ${python:Versions}
|
||||
|
||||
Depends: ${misc:Depends}, ${python:Depends}, python-gobject (>= 3.3.2), librsvg2-2
|
||||
Recommends: python-pyicu, python-osmgpsmap, graphviz, xdg-utils
|
||||
Suggests: ttf-freefont, python-gtkspell, libgexiv2-1, rcs, python-imaging, python-pygoocanvas
|
||||
Description: Gramps (Genealogical Research and Analysis Management
|
||||
Programming System) is a full featured genealogy program supporting
|
||||
a Python based plugin system.
|
||||
|
2
debian/gramps.manpages
vendored
@@ -1 +1 @@
|
||||
data/man/gramps.1
|
||||
data/man/gramps.1.in
|
||||
|
72
debian/rules
vendored
@@ -1,73 +1,9 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
build: build-stamp
|
||||
build-stamp:
|
||||
dh_testdir
|
||||
# This file was automatically generated by stdeb 0.6.0+git at
|
||||
# Sun, 31 Mar 2013 16:54:38 +0200
|
||||
|
||||
#./autogen.sh --prefix=/usr --mandir=\$${prefix}/share/man --sysconfdir=/etc
|
||||
./configure --enable-packager-mode --prefix=/usr --mandir=\$${prefix}/share/man --sysconfdir=/etc
|
||||
# ./configure --prefix=`pwd`/debian/tmp/usr --mandir=\$${prefix}/share/man
|
||||
$(MAKE)
|
||||
# $(MAKE) html
|
||||
|
||||
touch build-stamp
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
|
||||
# [ ! -f Makefile ] || $(MAKE) distclean
|
||||
# -rm -f src/*.pyo src/*/*.pyo
|
||||
# -rm -f config.status config.log
|
||||
|
||||
dh_auto_clean
|
||||
dh_clean
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_prep
|
||||
dh_installdirs
|
||||
|
||||
# Add here commands to install the package into debian/tmp.
|
||||
# GCONF_DISABLE_MAKEFILE_SCHEMA_INSTALL=1
|
||||
$(MAKE) install DESTDIR=`pwd`/debian/gramps
|
||||
-rm -f debian/gramps/usr/share/gramps/COPYING
|
||||
ln -s /usr/share/common-licenses/GPL-2 debian/gramps/usr/share/gramps/COPYING
|
||||
-rm -rf debian/gramps/usr/var
|
||||
# cp src/data/gramps.xml debian/gramps/usr/share/mime/packages
|
||||
-find debian/gramps/usr/share/ -name "*.pyo" -exec rm -f '{}' ';'
|
||||
|
||||
cp debian/gramps.xpm debian/gramps/usr/share/pixmaps/
|
||||
# cp src/gramps.xpm debian/tmp/usr/share/pixmaps/
|
||||
# cp src/images/gramps.svg debian/gramps/usr/share/pixmaps/
|
||||
# chmod 644 debian/gramps/usr/share/pixmaps/gramps.svg
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installdocs FAQ
|
||||
dh_installmenu
|
||||
# dh_installman
|
||||
dh_installmime -i
|
||||
# dh_installchangelogs ChangeLog
|
||||
dh_installchangelogs
|
||||
dh_icons
|
||||
# dh_movefiles -i
|
||||
# dh_gconf -i
|
||||
dh_link -i
|
||||
dh_compress -i
|
||||
dh_fixperms -i
|
||||
dh_pycentral -i
|
||||
dh_installdeb -i
|
||||
dh_gencontrol -i
|
||||
dh_md5sums -i
|
||||
dh_builddeb -i
|
||||
%:
|
||||
dh $@ --with python2 --buildsystem=python_distutils
|
||||
|
||||
|
||||
# Build architecture-dependent files here.
|
||||
binary-arch: build install
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install
|
||||
|
@@ -1,13 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.5.0//EN"
|
||||
"http://gramps-project.org/xml/1.5.0/grampsxml.dtd">
|
||||
<database xmlns="http://gramps-project.org/xml/1.5.0/">
|
||||
<!DOCTYPE database PUBLIC "-//Gramps//DTD Gramps XML 1.6.0//EN"
|
||||
"http://gramps-project.org/xml/1.6.0/grampsxml.dtd">
|
||||
<database xmlns="http://gramps-project.org/xml/1.6.0/">
|
||||
<header>
|
||||
<created date="2013-01-13" version="4.1.0-r21095M"/>
|
||||
<created date="2013-06-02" version="4.1.0-r22453"/>
|
||||
<researcher>
|
||||
<resname>Alex Roitman,,,</resname>
|
||||
</researcher>
|
||||
</header>
|
||||
<tags>
|
||||
<tag handle="_c7642d9389b54417e8b" change="1370206720" name="tag1" color="#000000000000" priority="0"/>
|
||||
</tags>
|
||||
<events>
|
||||
<event handle="_a701e8fd8ea27f99704" change="1198197326" id="E0000">
|
||||
<type>Birth</type>
|
||||
@@ -528,6 +531,158 @@
|
||||
<place hlink="_67MT6DB6KWOVMBAXSY"/>
|
||||
<description>Marriage of Lloyd Smith and Janis Elaine Green</description>
|
||||
</event>
|
||||
<event handle="_bd750cc852945743320" change="1301940145" id="E0121">
|
||||
<type>Birth</type>
|
||||
<dateval val="1902-06-28"/>
|
||||
</event>
|
||||
<event handle="_bd750d46bfe3f54dc37" change="1301940197" id="E0122">
|
||||
<type>Death</type>
|
||||
<dateval val="1987-11-16"/>
|
||||
<place hlink="_7JMT6DN2LOF54KXHTU"/>
|
||||
</event>
|
||||
<event handle="_bd750e2c5051f9f9596" change="1301940291" id="E0123">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1920-05-14"/>
|
||||
</event>
|
||||
<event handle="_bd750f87f8f5f85ed92" change="1301940433" id="E0124">
|
||||
<type>Birth</type>
|
||||
<dateval val="1920-12-22"/>
|
||||
</event>
|
||||
<event handle="_bd7510938ee530f327e" change="1301940543" id="E0125">
|
||||
<type>Birth</type>
|
||||
<dateval val="1923-06-24"/>
|
||||
<place hlink="_7JMT6DN2LOF54KXHTU"/>
|
||||
</event>
|
||||
<event handle="_bd7511b78ec7588ba8f" change="1301940662" id="E0126">
|
||||
<type>Birth</type>
|
||||
<dateval val="1917-06-21"/>
|
||||
</event>
|
||||
<event handle="_bd7511dbb250640b8f9" change="1301940699" id="E0127">
|
||||
<type>Death</type>
|
||||
<dateval val="1990-02-22"/>
|
||||
</event>
|
||||
<event handle="_bd751294da3419c6b05" change="1301940753" id="E0128">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1940-04-06"/>
|
||||
<place hlink="_7JMT6DN2LOF54KXHTU"/>
|
||||
</event>
|
||||
<event handle="_bd75138019e3dd26210" change="1301940935" id="E0129">
|
||||
<type>Divorce</type>
|
||||
<dateval val="1946-07" type="about"/>
|
||||
</event>
|
||||
<event handle="_bd7515393b61e665f22" change="1301941030" id="E0130">
|
||||
<type>Birth</type>
|
||||
<dateval val="1914-09-14"/>
|
||||
</event>
|
||||
<event handle="_bd7515bd20a397d6227" change="1301941084" id="E0131">
|
||||
<type>Death</type>
|
||||
<dateval val="1970-11-17"/>
|
||||
<place hlink="_67MT6DB6KWOVMBAXSY"/>
|
||||
</event>
|
||||
<event handle="_bd7516712945a2e2e52" change="1301941158" id="E0132">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1948-01-16"/>
|
||||
<place hlink="_67MT6DB6KWOVMBAXSY"/>
|
||||
</event>
|
||||
<event handle="_bd7517e297e15825efe" change="1301942055" id="E0133">
|
||||
<type>Birth</type>
|
||||
<dateval val="1941-08-21"/>
|
||||
<place hlink="_7JMT6DN2LOF54KXHTU"/>
|
||||
</event>
|
||||
<event handle="_bd751aaa22c47103f8a" change="1301941601" id="E0135">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1939-03-04"/>
|
||||
</event>
|
||||
<event handle="_bd751b1f55021ba97f1" change="1301941649" id="E0136">
|
||||
<type>Divorce</type>
|
||||
<dateval val="1941-04-16"/>
|
||||
</event>
|
||||
<event handle="_bd751cd71503c392a91" change="1301942076" id="E0138">
|
||||
<type>Birth</type>
|
||||
<dateval val="1945-04-29" type="about"/>
|
||||
</event>
|
||||
<event handle="_bd751d8bc6a607a0cab" change="1301943728" id="E0139">
|
||||
<type>Birth</type>
|
||||
<dateval val="1950-02-06"/>
|
||||
<place hlink="_67MT6DB6KWOVMBAXSY"/>
|
||||
</event>
|
||||
<event handle="_bd7523717d51778b278" change="1301942521" id="E0140">
|
||||
<type>Birth</type>
|
||||
<dateval val="1920-07-07"/>
|
||||
</event>
|
||||
<event handle="_bd7523d45e118a51684" change="1301942562" id="E0141">
|
||||
<type>Death</type>
|
||||
<dateval val="1993-07-12"/>
|
||||
</event>
|
||||
<event handle="_bd75248d701148dc3f9" change="1301942637" id="E0142">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1945-08-13"/>
|
||||
</event>
|
||||
<event handle="_bd75256710a193d1afe" change="1301942727" id="E0143">
|
||||
<type>Birth</type>
|
||||
<dateval val="1947-09-14"/>
|
||||
</event>
|
||||
<event handle="_bd7525e3f6345befa12" change="1301942778" id="E0144">
|
||||
<type>Birth</type>
|
||||
<dateval val="1949-07-03"/>
|
||||
</event>
|
||||
<event handle="_bd75268080337b77a4a" change="1301942842" id="E0145">
|
||||
<type>Birth</type>
|
||||
<dateval val="1952-09-23"/>
|
||||
</event>
|
||||
<event handle="_bd7527243eb2adcc2d6" change="1301942909" id="E0146">
|
||||
<type>Divorce</type>
|
||||
<dateval val="1955"/>
|
||||
</event>
|
||||
<event handle="_bd7528efed86c148120" change="1301943097" id="E0148">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1956-03-15"/>
|
||||
</event>
|
||||
<event handle="_bd752e8e30e23af6f38" change="1301943686" id="E0150">
|
||||
<type>Death</type>
|
||||
<dateval val="2002-06-21"/>
|
||||
</event>
|
||||
<event handle="_bd7532a79dc7cebeaa8" change="1301944152" id="E0151">
|
||||
<type>Birth</type>
|
||||
<dateval val="1925-09-12"/>
|
||||
<place hlink="_7JMT6DN2LOF54KXHTU"/>
|
||||
</event>
|
||||
<event handle="_bd75336b8f42dc72cbc" change="1301944196" id="E0152">
|
||||
<type>Death</type>
|
||||
<dateval val="2000-01-25"/>
|
||||
</event>
|
||||
<event handle="_bd75349209b0f2e5654" change="1301944317" id="E0153">
|
||||
<type>Birth</type>
|
||||
<dateval val="1925-09-26"/>
|
||||
</event>
|
||||
<event handle="_bd753552afc540398d0" change="1301944396" id="E0154">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1946"/>
|
||||
</event>
|
||||
<event handle="_bd7535d4ca162cb2dce" change="1301944449" id="E0155">
|
||||
<type>Divorce</type>
|
||||
<dateval val="1949-06" type="about"/>
|
||||
</event>
|
||||
<event handle="_bd7536f6d067fc0893f" change="1301944568" id="E0156">
|
||||
<type>Birth</type>
|
||||
<dateval val="1927-02-17"/>
|
||||
</event>
|
||||
<event handle="_bd75376da8616d3bb96" change="1301944617" id="E0157">
|
||||
<type>Marriage</type>
|
||||
<dateval val="1950-01-30"/>
|
||||
</event>
|
||||
<event handle="_bd753af24e41dd1fb68" change="1301944986" id="E0158">
|
||||
<type>Birth</type>
|
||||
<dateval val="1947-11-15"/>
|
||||
</event>
|
||||
<event handle="_bd753b663797a1e1d18" change="1301945033" id="E0159">
|
||||
<type>Birth</type>
|
||||
<dateval val="1949-01-05"/>
|
||||
</event>
|
||||
<event handle="_bd753c56f195aeb8f24" change="1301945159" id="E0160">
|
||||
<type>Birth</type>
|
||||
<dateval val="1950-07-27"/>
|
||||
</event>
|
||||
</events>
|
||||
<people home="_PSNT6D0DDHJOBCFJWX">
|
||||
<person handle="_0ONT6DJS5KD5W6EA1P" change="1198197326" id="I0004">
|
||||
@@ -705,6 +860,7 @@
|
||||
<eventref hlink="_a701e8fde5d0cc6484e" role="Primary"/>
|
||||
<eventref hlink="_a701e8fde75723d0c85" role="Primary"/>
|
||||
<childof hlink="_KKMT6D5KWF1VP03K4B"/>
|
||||
<parentin hlink="_bd750af3e934b6d3934"/>
|
||||
</person>
|
||||
<person handle="_NDNT6D8O7D3QRKP07N" change="1198197326" id="I0017">
|
||||
<gender>F</gender>
|
||||
@@ -737,7 +893,7 @@
|
||||
<objref hlink="_HHNT6D73QPKC0KWK2Y"/>
|
||||
<childof hlink="_S7MT6D1JSGX9PZO27F"/>
|
||||
</person>
|
||||
<person handle="_PSNT6D0DDHJOBCFJWX" change="1198197326" id="I0037">
|
||||
<person handle="_PSNT6D0DDHJOBCFJWX" change="1370206720" id="I0037">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Edwin Michael</first>
|
||||
@@ -753,6 +909,7 @@
|
||||
<objref hlink="_CVNT6DHG5ICZ1UGUO9"/>
|
||||
<childof hlink="_1HMT6DNWTSPXIL2FDM"/>
|
||||
<parentin hlink="_CGNT6DV02D0CQTGBAO"/>
|
||||
<tagref hlink="_c7642d9389b54417e8b"/>
|
||||
</person>
|
||||
<person handle="_RDMT6D6113RO3X299I" change="1198197326" id="I0019">
|
||||
<gender>M</gender>
|
||||
@@ -968,6 +1125,185 @@
|
||||
<eventref hlink="_a701e8fdb0a2faa54b5" role="Primary"/>
|
||||
<parentin hlink="_MMMT6D6NGNO5YERSLM"/>
|
||||
</person>
|
||||
<person handle="_bd750d5cc7f5a094950" change="1301940319" id="I0056">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Alvera C.</first>
|
||||
<surname>Erickson</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd750cc852945743320" role="Primary"/>
|
||||
<eventref hlink="_bd750d46bfe3f54dc37" role="Primary"/>
|
||||
<parentin hlink="_bd750af3e934b6d3934"/>
|
||||
</person>
|
||||
<person handle="_bd750fae3bf5fb52f41" change="1301943705" id="I0057">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Anna Louise</first>
|
||||
<surname>Smith</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd750f87f8f5f85ed92" role="Primary"/>
|
||||
<eventref hlink="_bd752e8e30e23af6f38" role="Primary"/>
|
||||
<childof hlink="_bd750af3e934b6d3934"/>
|
||||
<parentin hlink="_bd75111820230015633"/>
|
||||
<parentin hlink="_bd7514750de3e09296e"/>
|
||||
</person>
|
||||
<person handle="_bd7510a06e063c4ebee" change="1301942652" id="I0058">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Elaine Marie</first>
|
||||
<surname>Smith</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7510938ee530f327e" role="Primary"/>
|
||||
<childof hlink="_bd750af3e934b6d3934"/>
|
||||
<parentin hlink="_bd75229b5c86a3f4e0e"/>
|
||||
</person>
|
||||
<person handle="_bd751223f4c4504b316" change="1301940875" id="I0059">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Eli Harry</first>
|
||||
<surname>Jones</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7511b78ec7588ba8f" role="Primary"/>
|
||||
<eventref hlink="_bd7511dbb250640b8f9" role="Primary"/>
|
||||
<parentin hlink="_bd75111820230015633"/>
|
||||
</person>
|
||||
<person handle="_bd7515d66246e2e88dc" change="1301941735" id="I0060">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Leroy Verl</first>
|
||||
<surname>Morgan</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7515393b61e665f22" role="Primary"/>
|
||||
<eventref hlink="_bd7515bd20a397d6227" role="Primary"/>
|
||||
<parentin hlink="_bd7514750de3e09296e"/>
|
||||
<parentin hlink="_bd7518a961d20ca9037"/>
|
||||
</person>
|
||||
<person handle="_bd7517fd3fe2e5a5e14" change="1301943794" id="I0061">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Roberta Michele</first>
|
||||
<surname>Jones</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7517e297e15825efe" role="Primary"/>
|
||||
<childof hlink="_bd75111820230015633"/>
|
||||
<childof hlink="_bd7514750de3e09296e"/>
|
||||
</person>
|
||||
<person handle="_bd751ce66f940ce1e90" change="1301943794" id="I0063">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Frank Albert</first>
|
||||
<surname>Jones</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd751cd71503c392a91" role="Primary"/>
|
||||
<childof hlink="_bd75111820230015633"/>
|
||||
<childof hlink="_bd7514750de3e09296e"/>
|
||||
</person>
|
||||
<person handle="_bd751d970186c7c7b7c" change="1301943733" id="I0064">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Margaret Ann</first>
|
||||
<surname>Morgan</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd751d8bc6a607a0cab" role="Primary"/>
|
||||
<childof hlink="_bd7514750de3e09296e"/>
|
||||
</person>
|
||||
<person handle="_bd7523ecb0767f5ad53" change="1301943100" id="I0065">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Robert Alfred</first>
|
||||
<surname>Shannon</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7523717d51778b278" role="Primary"/>
|
||||
<eventref hlink="_bd7523d45e118a51684" role="Primary"/>
|
||||
<parentin hlink="_bd75229b5c86a3f4e0e"/>
|
||||
<parentin hlink="_bd752761a3e4fd23f2b"/>
|
||||
</person>
|
||||
<person handle="_bd752570e6e5592b5c0" change="1301942914" id="I0066">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Kelly Christine</first>
|
||||
<surname>Shannon</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd75256710a193d1afe" role="Primary"/>
|
||||
<childof hlink="_bd75229b5c86a3f4e0e"/>
|
||||
</person>
|
||||
<person handle="_bd7525ee5481876d199" change="1301942914" id="I0067">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Lisa Marie</first>
|
||||
<surname>Shannon</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7525e3f6345befa12" role="Primary"/>
|
||||
<childof hlink="_bd75229b5c86a3f4e0e"/>
|
||||
</person>
|
||||
<person handle="_bd752686b30645aeaaf" change="1301942914" id="I0068">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Matthew John</first>
|
||||
<surname>Shannon</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd75268080337b77a4a" role="Primary"/>
|
||||
<childof hlink="_bd75229b5c86a3f4e0e"/>
|
||||
</person>
|
||||
<person handle="_bd7532b94e33af612c6" change="1301944619" id="I0071">
|
||||
<gender>M</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Warren Edward</first>
|
||||
<surname>Smith</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7532a79dc7cebeaa8" role="Primary"/>
|
||||
<eventref hlink="_bd75336b8f42dc72cbc" role="Primary"/>
|
||||
<childof hlink="_bd750af3e934b6d3934"/>
|
||||
<parentin hlink="_bd7533c1ed4114b0896"/>
|
||||
<parentin hlink="_bd7536046944b843a26"/>
|
||||
</person>
|
||||
<person handle="_bd7534a49f013482f95" change="1301944405" id="I0072">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Alice Hannah</first>
|
||||
<surname>Iverson</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd75349209b0f2e5654" role="Primary"/>
|
||||
<parentin hlink="_bd7533c1ed4114b0896"/>
|
||||
</person>
|
||||
<person handle="_bd75371353304125b3f" change="1301944619" id="I0073">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Evelyn Lucille</first>
|
||||
<surname>Watson</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd7536f6d067fc0893f" role="Primary"/>
|
||||
<parentin hlink="_bd7536046944b843a26"/>
|
||||
</person>
|
||||
<person handle="_bd7539fc2292e24045e" change="1301945256" id="I0076">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Marie Astri</first>
|
||||
<surname>Smith</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd753af24e41dd1fb68" role="Primary"/>
|
||||
<childof hlink="_bd7533c1ed4114b0896"/>
|
||||
<childof hlink="_bd7536046944b843a26"/>
|
||||
</person>
|
||||
<person handle="_bd753a6f5280a3a7985" change="1301945256" id="I0077">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Susan Elizabeth</first>
|
||||
<surname>Smith</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd753b663797a1e1d18" role="Primary"/>
|
||||
<childof hlink="_bd7533c1ed4114b0896"/>
|
||||
<childof hlink="_bd7536046944b843a26"/>
|
||||
</person>
|
||||
<person handle="_bd753c5922c1912e3b9" change="1301945256" id="I0078">
|
||||
<gender>F</gender>
|
||||
<name type="Birth Name">
|
||||
<first>Karen Christine</first>
|
||||
<surname>Smith</surname>
|
||||
</name>
|
||||
<eventref hlink="_bd753c56f195aeb8f24" role="Primary"/>
|
||||
<childof hlink="_bd7536046944b843a26"/>
|
||||
</person>
|
||||
</people>
|
||||
<families>
|
||||
<family handle="_1HMT6DNWTSPXIL2FDM" change="1198197326" id="F0012">
|
||||
@@ -1086,6 +1422,72 @@
|
||||
<mother hlink="_NQMT6DX5NIOGMEGJA3"/>
|
||||
<eventref hlink="_a701e8ff0514bd46d08" role="Family"/>
|
||||
</family>
|
||||
<family handle="_bd750af3e934b6d3934" change="1301944124" id="F0015">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_K3NT6DMBYAXNTXOO3F"/>
|
||||
<mother hlink="_bd750d5cc7f5a094950"/>
|
||||
<eventref hlink="_bd750e2c5051f9f9596" role="Family"/>
|
||||
<childref hlink="_bd750fae3bf5fb52f41"/>
|
||||
<childref hlink="_bd7510a06e063c4ebee"/>
|
||||
<childref hlink="_bd7532b94e33af612c6"/>
|
||||
</family>
|
||||
<family handle="_bd75111820230015633" change="1301943794" id="F0016">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd751223f4c4504b316"/>
|
||||
<mother hlink="_bd750fae3bf5fb52f41"/>
|
||||
<eventref hlink="_bd751294da3419c6b05" role="Family"/>
|
||||
<eventref hlink="_bd75138019e3dd26210" role="Family"/>
|
||||
<childref hlink="_bd7517fd3fe2e5a5e14"/>
|
||||
<childref hlink="_bd751ce66f940ce1e90"/>
|
||||
</family>
|
||||
<family handle="_bd7514750de3e09296e" change="1301942036" id="F0017">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd7515d66246e2e88dc"/>
|
||||
<mother hlink="_bd750fae3bf5fb52f41"/>
|
||||
<eventref hlink="_bd7516712945a2e2e52" role="Family"/>
|
||||
<childref hlink="_bd7517fd3fe2e5a5e14" frel="Stepchild"/>
|
||||
<childref hlink="_bd751ce66f940ce1e90" frel="Stepchild"/>
|
||||
<childref hlink="_bd751d970186c7c7b7c"/>
|
||||
</family>
|
||||
<family handle="_bd7518a961d20ca9037" change="1301941725" id="F0018">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd7515d66246e2e88dc"/>
|
||||
<eventref hlink="_bd751aaa22c47103f8a" role="Family"/>
|
||||
<eventref hlink="_bd751b1f55021ba97f1" role="Family"/>
|
||||
</family>
|
||||
<family handle="_bd75229b5c86a3f4e0e" change="1301942914" id="F0019">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd7523ecb0767f5ad53"/>
|
||||
<mother hlink="_bd7510a06e063c4ebee"/>
|
||||
<eventref hlink="_bd75248d701148dc3f9" role="Family"/>
|
||||
<eventref hlink="_bd7527243eb2adcc2d6" role="Family"/>
|
||||
<childref hlink="_bd752570e6e5592b5c0"/>
|
||||
<childref hlink="_bd7525ee5481876d199"/>
|
||||
<childref hlink="_bd752686b30645aeaaf"/>
|
||||
</family>
|
||||
<family handle="_bd752761a3e4fd23f2b" change="1301943296" id="F0020">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd7523ecb0767f5ad53"/>
|
||||
<eventref hlink="_bd7528efed86c148120" role="Family"/>
|
||||
</family>
|
||||
<family handle="_bd7533c1ed4114b0896" change="1301944940" id="F0021">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd7532b94e33af612c6"/>
|
||||
<mother hlink="_bd7534a49f013482f95"/>
|
||||
<eventref hlink="_bd753552afc540398d0" role="Family"/>
|
||||
<eventref hlink="_bd7535d4ca162cb2dce" role="Family"/>
|
||||
<childref hlink="_bd7539fc2292e24045e"/>
|
||||
<childref hlink="_bd753a6f5280a3a7985"/>
|
||||
</family>
|
||||
<family handle="_bd7536046944b843a26" change="1301945256" id="F0022">
|
||||
<rel type="Married"/>
|
||||
<father hlink="_bd7532b94e33af612c6"/>
|
||||
<mother hlink="_bd75371353304125b3f"/>
|
||||
<eventref hlink="_bd75376da8616d3bb96" role="Family"/>
|
||||
<childref hlink="_bd7539fc2292e24045e" mrel="Stepchild"/>
|
||||
<childref hlink="_bd753a6f5280a3a7985" mrel="Stepchild"/>
|
||||
<childref hlink="_bd753c5922c1912e3b9"/>
|
||||
</family>
|
||||
</families>
|
||||
<citations>
|
||||
<citation handle="_c5a0f183598786f5e46249885bc" change="1358093983" id="C0000">
|
||||
|
@@ -8,7 +8,7 @@
|
||||
# Copyright (C) 2008 Brian G. Matherly
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2012 Doug Blank
|
||||
# Copyright (C) 2012 Paul Franklin
|
||||
# Copyright (C) 2012-2013 Paul Franklin
|
||||
#
|
||||
# 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
|
||||
@@ -39,8 +39,6 @@ Module responsible for handling the command line arguments for GRAMPS.
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import sys
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -57,6 +55,8 @@ from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.plug.report import CATEGORY_BOOK, CATEGORY_CODE, BookList
|
||||
from .plug import cl_report, cl_book
|
||||
from .user import User
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -166,6 +166,7 @@ class ArgHandler(object):
|
||||
self.actions = parser.actions
|
||||
self.list = parser.list
|
||||
self.list_more = parser.list_more
|
||||
self.list_table = parser.list_table
|
||||
self.open_gui = parser.open_gui
|
||||
self.imp_db_path = None
|
||||
self.dbman = CLIDbManager(self.dbstate)
|
||||
@@ -184,11 +185,9 @@ class ArgHandler(object):
|
||||
if self.errorfunc:
|
||||
self.errorfunc(msg1)
|
||||
else:
|
||||
# Need to convert to system file encoding before printing
|
||||
# For non latin characters in path/file/user names
|
||||
print(msg1.encode(sys.stdout.encoding, 'backslashreplace'), file=sys.stderr)
|
||||
print(msg1, file=sys.stderr)
|
||||
if msg2 is not None:
|
||||
print(msg2.encode(sys.stdout.encoding, 'backslashreplace'), file=sys.stderr)
|
||||
print(msg2, file=sys.stderr)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Argument parser: sorts out given arguments
|
||||
@@ -219,7 +218,7 @@ class ArgHandler(object):
|
||||
if not self.check_db(db_path, self.force_unlock):
|
||||
sys.exit(0)
|
||||
if create:
|
||||
self.__error( _("Error: Family tree '%s' already exists.\n"
|
||||
self.__error( _("Error: Family Tree '%s' already exists.\n"
|
||||
"The '-C' option cannot be used.") % value)
|
||||
sys.exit(0)
|
||||
return db_path
|
||||
@@ -228,9 +227,9 @@ class ArgHandler(object):
|
||||
db_path, title = self.dbman.create_new_db_cli(title=value)
|
||||
return db_path
|
||||
else:
|
||||
self.__error( _('Error: Input family tree "%s" does not exist.\n'
|
||||
self.__error( _('Error: Input Family Tree "%s" does not exist.\n'
|
||||
"If GEDCOM, Gramps-xml or grdb, use the -i option "
|
||||
"to import into a family tree instead.") % value)
|
||||
"to import into a Family Tree instead.") % value)
|
||||
sys.exit(0)
|
||||
|
||||
def __handle_import_option(self, value, family_tree_format):
|
||||
@@ -287,24 +286,20 @@ class ArgHandler(object):
|
||||
self.__error(_("WARNING: Output file already exists!\n"
|
||||
"WARNING: It will be overwritten:\n %s") %
|
||||
fullpath)
|
||||
answer = None
|
||||
while not answer:
|
||||
try:
|
||||
if sys.version_info[0] < 3:
|
||||
ask = raw_input
|
||||
else:
|
||||
ask = input
|
||||
ans = ask(_('OK to overwrite? (yes/no) ') \
|
||||
.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
except EOFError:
|
||||
print()
|
||||
sys.exit(0)
|
||||
if ans.upper() in ('Y', 'YES', _('YES').upper()):
|
||||
self.__error( _("Will overwrite the existing file: %s")
|
||||
% fullpath)
|
||||
answer = "ok"
|
||||
try:
|
||||
if sys.version_info[0] < 3:
|
||||
ask = raw_input
|
||||
else:
|
||||
sys.exit(0)
|
||||
ask = input
|
||||
answer = ask(_('OK to overwrite? (yes/no) '))
|
||||
except EOFError:
|
||||
print()
|
||||
sys.exit(0)
|
||||
if answer.upper() in ('Y', 'YES', _('YES').upper()):
|
||||
self.__error(_("Will overwrite the existing file: %s")
|
||||
% fullpath)
|
||||
else:
|
||||
sys.exit(0)
|
||||
|
||||
if family_tree_format is None:
|
||||
# Guess the file format based on the file extension.
|
||||
@@ -378,12 +373,8 @@ class ArgHandler(object):
|
||||
if not self.check_db(db_path, self.force_unlock):
|
||||
sys.exit(0)
|
||||
# Add the file to the recent items
|
||||
path = os.path.join(db_path, "name.txt")
|
||||
try:
|
||||
ifile = open(path)
|
||||
title = ifile.readline().strip()
|
||||
ifile.close()
|
||||
except:
|
||||
title = self.dbstate.db.get_dbname()
|
||||
if not title:
|
||||
title = db_path
|
||||
recent_files(db_path, title)
|
||||
self.open = db_path
|
||||
@@ -408,47 +399,59 @@ class ArgHandler(object):
|
||||
"""
|
||||
|
||||
if self.list:
|
||||
print(_('List of known family trees in your database path\n').\
|
||||
encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(_('List of known Family Trees in your database path\n'))
|
||||
|
||||
for name, dirname in sorted(self.dbman.family_tree_list(),
|
||||
key=lambda pair: pair[0].lower()):
|
||||
|
||||
print((_("%(full_DB_path)s with name \"%(f_t_name)s\"") % \
|
||||
{'full_DB_path' : dirname,
|
||||
'f_t_name' : name}).encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
|
||||
print(_("%(full_DB_path)s with name \"%(f_t_name)s\"")
|
||||
% {'full_DB_path' : dirname, 'f_t_name' : name})
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if self.list_more:
|
||||
print(_('Gramps Family Trees:').encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(_('Gramps Family Trees:'))
|
||||
summary_list = self.dbman.family_tree_summary()
|
||||
for summary in sorted(summary_list,
|
||||
key=lambda sum: sum["Family tree"].lower()):
|
||||
print(_("Family Tree \"%s\":").\
|
||||
encode(sys.stdout.encoding, 'backslashreplace') % summary["Family tree"])
|
||||
key=lambda sum: sum[_("Family Tree")].lower()):
|
||||
print(_("Family Tree \"%s\":") % summary[_("Family Tree")])
|
||||
for item in sorted(summary):
|
||||
if item != "Family tree":
|
||||
print((" %s: %s" % (item, summary[item])).\
|
||||
encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
if item != "Family Tree":
|
||||
print(" %s: %s" % (item, summary[item]))
|
||||
sys.exit(0)
|
||||
|
||||
if self.list_table:
|
||||
print(_('Gramps Family Trees:'))
|
||||
summary_list = self.dbman.family_tree_summary()
|
||||
print(_("Family Tree"), end="")
|
||||
for key in sorted(summary_list[0]):
|
||||
if key != "Family Tree":
|
||||
print("\t ", end="")
|
||||
print(key, end="")
|
||||
print()
|
||||
for summary in sorted(summary_list,
|
||||
key=lambda sum: sum[_("Family Tree")].lower()):
|
||||
print('"%s"' % summary[_("Family Tree")], end="")
|
||||
for item in sorted(summary):
|
||||
if item != _("Family Tree"):
|
||||
print("\t ", end="")
|
||||
print('"%s"' % summary[item], end="")
|
||||
print()
|
||||
sys.exit(0)
|
||||
|
||||
self.__open_action()
|
||||
self.__import_action()
|
||||
|
||||
for (action, op_string) in self.actions:
|
||||
print(_("Performing action: %s.") % action, file=sys.stderr)
|
||||
if op_string:
|
||||
print(_("Using options string: %s") % op_string, file=sys.stderr)
|
||||
print(_("Using options string: %s")
|
||||
% op_string, file=sys.stderr)
|
||||
self.cl_action(action, op_string)
|
||||
|
||||
for expt in self.exports:
|
||||
# Need to convert path/filename to str before printing
|
||||
# For non latin characters in Windows path/file/user names
|
||||
fn = expt[0].encode(sys.stdout.encoding, 'backslashreplace')
|
||||
fmt = str(expt[1])
|
||||
print(_("Exporting: file %(filename)s, "
|
||||
"format %(format)s.") % \
|
||||
{'filename' : fn,
|
||||
'format' : fmt}, file=sys.stderr)
|
||||
print(_("Exporting: file %(filename)s, format %(format)s.")
|
||||
% {'filename' : expt[0],
|
||||
'format' : expt[1]}, file=sys.stderr)
|
||||
self.cl_export(expt[0], expt[1])
|
||||
|
||||
if cleanup:
|
||||
@@ -480,14 +483,13 @@ class ArgHandler(object):
|
||||
if self.gui:
|
||||
self.imp_db_path, title = self.dbman.create_new_db_cli()
|
||||
else:
|
||||
self.imp_db_path = get_empty_tempdir("import_dbdir") \
|
||||
.encode(sys.stdout.encoding, 'backslashreplace')
|
||||
self.imp_db_path = get_empty_tempdir("import_dbdir")
|
||||
newdb = DbBsddb()
|
||||
newdb.write_version(self.imp_db_path)
|
||||
|
||||
try:
|
||||
self.sm.open_activate(self.imp_db_path)
|
||||
msg = _("Created empty family tree successfully")
|
||||
msg = _("Created empty Family Tree successfully")
|
||||
print(msg, file=sys.stderr)
|
||||
except:
|
||||
print(_("Error opening the file."), file=sys.stderr)
|
||||
@@ -495,10 +497,8 @@ class ArgHandler(object):
|
||||
sys.exit(0)
|
||||
|
||||
for imp in self.imports:
|
||||
fn = imp[0].encode(sys.stdout.encoding, 'backslashreplace')
|
||||
fmt = str(imp[1])
|
||||
msg = _("Importing: file %(filename)s, format %(format)s.") % \
|
||||
{'filename' : fn, 'format' : fmt}
|
||||
{'filename' : imp[0], 'format' : imp[1]}
|
||||
print(msg, file=sys.stderr)
|
||||
self.cl_import(imp[0], imp[1])
|
||||
|
||||
@@ -590,7 +590,8 @@ class ArgHandler(object):
|
||||
options_str_dict = _split_options(options_str)
|
||||
except:
|
||||
options_str_dict = {}
|
||||
print(_("Ignoring invalid options string."), file=sys.stderr)
|
||||
print(_("Ignoring invalid options string."),
|
||||
file=sys.stderr)
|
||||
|
||||
name = options_str_dict.pop('name', None)
|
||||
_cl_list = pmgr.get_reg_reports(gui=False)
|
||||
@@ -618,16 +619,17 @@ class ArgHandler(object):
|
||||
msg = _("Report name not given. "
|
||||
"Please use one of %(donottranslate)s=reportname") % \
|
||||
{'donottranslate' : '[-p|--options] name'}
|
||||
|
||||
|
||||
print(_("%s\n Available names are:") % msg, file=sys.stderr)
|
||||
for pdata in sorted(_cl_list, key= lambda pdata: pdata.id.lower()):
|
||||
# Print cli report name ([item[0]), GUI report name (item[4])
|
||||
if len(pdata.id) <= 25:
|
||||
print(" %s%s- %s" % ( pdata.id, " " * (26 - len(pdata.id)),
|
||||
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
|
||||
print(" %s%s- %s"
|
||||
% ( pdata.id, " " * (26 - len(pdata.id)),
|
||||
pdata.name), file=sys.stderr)
|
||||
else:
|
||||
print(" %s\t- %s" % (pdata.id,
|
||||
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
|
||||
print(" %s\t- %s"
|
||||
% (pdata.id, pdata.name), file=sys.stderr)
|
||||
|
||||
elif action == "tool":
|
||||
from gramps.gui.plug import tool
|
||||
@@ -636,7 +638,8 @@ class ArgHandler(object):
|
||||
chunk in options_str.split(',') ] )
|
||||
except:
|
||||
options_str_dict = {}
|
||||
print(_("Ignoring invalid options string."), file=sys.stderr)
|
||||
print(_("Ignoring invalid options string."),
|
||||
file=sys.stderr)
|
||||
|
||||
name = options_str_dict.pop('name', None)
|
||||
_cli_tool_list = pmgr.get_reg_tools(gui=False)
|
||||
@@ -658,24 +661,26 @@ class ArgHandler(object):
|
||||
msg = _("Tool name not given. "
|
||||
"Please use one of %(donottranslate)s=toolname.") % \
|
||||
{'donottranslate' : '[-p|--options] name'}
|
||||
|
||||
|
||||
print(_("%s\n Available names are:") % msg, file=sys.stderr)
|
||||
for pdata in sorted(_cli_tool_list,
|
||||
key=lambda pdata: pdata.id.lower()):
|
||||
# Print cli report name ([item[0]), GUI report name (item[4])
|
||||
if len(pdata.id) <= 25:
|
||||
print(" %s%s- %s" % ( pdata.id, " " * (26 - len(pdata.id)),
|
||||
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
|
||||
print(" %s%s- %s"
|
||||
% ( pdata.id, " " * (26 - len(pdata.id)),
|
||||
pdata.name), file=sys.stderr)
|
||||
else:
|
||||
print(" %s\t- %s" % (pdata.id,
|
||||
pdata.name.encode(sys.stdout.encoding, 'backslashreplace')), file=sys.stderr)
|
||||
print(" %s\t- %s"
|
||||
% (pdata.id, pdata.name), file=sys.stderr)
|
||||
|
||||
elif action == "book":
|
||||
try:
|
||||
options_str_dict = _split_options(options_str)
|
||||
except:
|
||||
options_str_dict = {}
|
||||
print(_("Ignoring invalid options string."), file=sys.stderr)
|
||||
print(_("Ignoring invalid options string."),
|
||||
file=sys.stderr)
|
||||
|
||||
name = options_str_dict.pop('name', None)
|
||||
book_list = BookList('books.xml', self.dbstate.db)
|
||||
|
@@ -39,8 +39,6 @@ Module responsible for handling the command line arguments for GRAMPS.
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import getopt
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
import logging
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -52,6 +50,8 @@ from gramps.gen.const import LONGOPTS, SHORTOPTS
|
||||
from gramps.gen.config import config
|
||||
from gramps.gen.utils.configmanager import safe_eval
|
||||
from gramps.gen.utils.file import get_unicode_path_from_env_var
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
# Note: Make sure to edit const.py.in POPT_TABLE too!
|
||||
_HELP = _("""
|
||||
@@ -63,17 +63,18 @@ Help options
|
||||
--usage Display brief usage message
|
||||
|
||||
Application options
|
||||
-O, --open=FAMILY_TREE Open family tree
|
||||
-C, --create=FAMILY_TREE Create on open if new family tree
|
||||
-O, --open=FAMILY_TREE Open Family Tree
|
||||
-C, --create=FAMILY_TREE Create on open if new Family Tree
|
||||
-i, --import=FILENAME Import file
|
||||
-e, --export=FILENAME Export file
|
||||
-f, --format=FORMAT Specify family tree format
|
||||
-f, --format=FORMAT Specify Family Tree format
|
||||
-a, --action=ACTION Specify action
|
||||
-p, --options=OPTIONS_STRING Specify options
|
||||
-d, --debug=LOGGER_NAME Enable debug logs
|
||||
-l List Family Trees
|
||||
-L List Family Trees in Detail
|
||||
-u, --force-unlock Force unlock of family tree
|
||||
-t List Family Trees, tab delimited
|
||||
-u, --force-unlock Force unlock of Family Tree
|
||||
-s, --show Show config settings
|
||||
-c, --config=[config.setting[:value]] Set config setting(s) and start Gramps
|
||||
-v, --version Show versions
|
||||
@@ -111,7 +112,7 @@ Use the name=timeline,show=all to find out about all available options for the t
|
||||
To find out details of a particular option, use show=option_name , e.g. name=timeline,show=off string.
|
||||
To learn about available report names, use name=show string.
|
||||
|
||||
9. To convert a family tree on the fly to a .gramps xml file:
|
||||
9. To convert a Family Tree on the fly to a .gramps xml file:
|
||||
gramps -O 'Family Tree 1' -e output.gramps -f gramps-xml
|
||||
|
||||
10. To generate a web site into an other locale (in german):
|
||||
@@ -176,6 +177,7 @@ class ArgParser(object):
|
||||
self.imp_db_path = None
|
||||
self.list = False
|
||||
self.list_more = False
|
||||
self.list_table = False
|
||||
self.help = False
|
||||
self.usage = False
|
||||
self.force_unlock = False
|
||||
@@ -242,7 +244,8 @@ class ArgParser(object):
|
||||
# if there were an argument without option,
|
||||
# use it as a file to open and return
|
||||
self.open_gui = leftargs[0]
|
||||
print ("Trying to open: %s ..." % leftargs[0], file=sys.stderr)
|
||||
print(_("Trying to open: %s ...") % leftargs[0],
|
||||
file=sys.stderr)
|
||||
#see if force open is on
|
||||
for opt_ix in range(len(options)):
|
||||
option, value = options[opt_ix]
|
||||
@@ -275,7 +278,8 @@ class ArgParser(object):
|
||||
elif option in ( '-a', '--action' ):
|
||||
action = value
|
||||
if action not in ('report', 'tool', 'book'):
|
||||
print ("Unknown action: %s. Ignoring." % action, file=sys.stderr)
|
||||
print(_("Unknown action: %s. Ignoring.") % action,
|
||||
file=sys.stderr)
|
||||
continue
|
||||
options_str = ""
|
||||
if opt_ix < len(options)-1 \
|
||||
@@ -283,7 +287,7 @@ class ArgParser(object):
|
||||
options_str = options[opt_ix+1][1]
|
||||
self.actions.append((action, options_str))
|
||||
elif option in ('-d', '--debug'):
|
||||
print ('setup debugging', value, file=sys.stderr)
|
||||
print(_('setup debugging'), value, file=sys.stderr)
|
||||
logger = logging.getLogger(value)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
cleandbg += [opt_ix]
|
||||
@@ -291,15 +295,17 @@ class ArgParser(object):
|
||||
self.list = True
|
||||
elif option in ('-L'):
|
||||
self.list_more = True
|
||||
elif option in ('-t'):
|
||||
self.list_table = True
|
||||
elif option in ('-s','--show'):
|
||||
print ("Gramps config settings from %s:" % \
|
||||
config.filename.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(_("Gramps config settings from %s:")
|
||||
% config.filename)
|
||||
for section in config.data:
|
||||
for setting in config.data[section]:
|
||||
print ("%s.%s=%s" % (
|
||||
section, setting,
|
||||
repr(config.data[section][setting])))
|
||||
print ('')
|
||||
print("%s.%s=%s"
|
||||
% (section, setting,
|
||||
repr(config.data[section][setting])))
|
||||
print()
|
||||
sys.exit(0)
|
||||
elif option in ('-c', '--config'):
|
||||
setting_name = value
|
||||
@@ -310,24 +316,24 @@ class ArgParser(object):
|
||||
set_value = True
|
||||
if config.has_default(setting_name):
|
||||
setting_value = config.get(setting_name)
|
||||
print ("Current Gramps config setting: " \
|
||||
"%s:%s" % (setting_name, repr(setting_value)), file=sys.stderr)
|
||||
print(_("Current Gramps config setting: %s:%s")
|
||||
% (setting_name, repr(setting_value)),
|
||||
file=sys.stderr)
|
||||
if set_value:
|
||||
if new_value == "DEFAULT":
|
||||
new_value = config.get_default(setting_name)
|
||||
else:
|
||||
new_value = safe_eval(new_value)
|
||||
config.set(setting_name, new_value)
|
||||
print (" New Gramps config " \
|
||||
"setting: %s:%s" % (
|
||||
setting_name,
|
||||
repr(config.get(setting_name))
|
||||
), file=sys.stderr)
|
||||
print(_(" New Gramps config setting: %s:%s")
|
||||
% (setting_name,
|
||||
repr(config.get(setting_name))),
|
||||
file=sys.stderr)
|
||||
else:
|
||||
need_to_quit = True
|
||||
else:
|
||||
print ("Gramps: no such config setting:" \
|
||||
" '%s'" % setting_name, file=sys.stderr)
|
||||
print(_("Gramps: no such config setting: '%s'")
|
||||
% setting_name, file=sys.stderr)
|
||||
need_to_quit = True
|
||||
cleandbg += [opt_ix]
|
||||
elif option in ('-h', '-?', '--help'):
|
||||
@@ -345,7 +351,8 @@ class ArgParser(object):
|
||||
del options[ind]
|
||||
|
||||
if len(options) > 0 and self.open is None and self.imports == [] \
|
||||
and not (self.list or self.list_more or self.help or self.runqml):
|
||||
and not (self.list or self.list_more or self.list_table or
|
||||
self.help or self.runqml):
|
||||
# Extract and convert to unicode the arguments in the list.
|
||||
# The % operator replaces the list elements with repr() of
|
||||
# the list elements, which is OK for latin characters
|
||||
@@ -372,7 +379,7 @@ class ArgParser(object):
|
||||
#errors in argument parsing ==> give cli error, no gui needed
|
||||
return False
|
||||
|
||||
if self.list or self.list_more or self.help:
|
||||
if self.list or self.list_more or self.list_table or self.help:
|
||||
return False
|
||||
|
||||
if self.open_gui:
|
||||
@@ -402,15 +409,13 @@ class ArgParser(object):
|
||||
If the user gives the --help or -h option, print the output to terminal.
|
||||
"""
|
||||
if self.help:
|
||||
# Convert Help messages to file system encoding before printing
|
||||
print (_HELP.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(_HELP)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def print_usage(self):
|
||||
"""
|
||||
If the user gives the --usage print the output to terminal.
|
||||
"""
|
||||
if self.usage:
|
||||
# Convert Help messages to file system encoding before printing
|
||||
print (_USAGE.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(_USAGE)
|
||||
sys.exit(0)
|
||||
|
@@ -51,6 +51,8 @@ import tempfile
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
LOG = logging.getLogger(".clidbman")
|
||||
from gramps.gen.db.dbconst import DBLOGNAME
|
||||
_LOG = logging.getLogger(DBLOGNAME)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -58,7 +60,7 @@ LOG = logging.getLogger(".clidbman")
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.db import DbBsddb
|
||||
from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.config import config
|
||||
@@ -136,71 +138,94 @@ class CLIDbManager(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_dbdir_summary(self, file_name):
|
||||
def get_dbdir_summary(self, dirpath, name):
|
||||
"""
|
||||
Returns (people_count, version_number) of current DB.
|
||||
Returns ("Unknown", "Unknown") if invalid DB or other error.
|
||||
Returns (people_count, bsddb_version, schema_version) of
|
||||
current DB.
|
||||
Returns ("Unknown", "Unknown", "Unknown") if invalid DB or other error.
|
||||
"""
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
from bsddb3 import dbshelve, db
|
||||
else:
|
||||
from bsddb import dbshelve, db
|
||||
|
||||
from gramps.gen.db import META, PERSON_TBL
|
||||
from gramps.gen.db.dbconst import BDBVERSFN
|
||||
|
||||
bdbversion_file = os.path.join(dirpath, BDBVERSFN)
|
||||
if os.path.isfile(bdbversion_file):
|
||||
vers_file = open(bdbversion_file)
|
||||
bsddb_version = vers_file.readline().strip()
|
||||
else:
|
||||
return "Unknown", "Unknown", "Unknown"
|
||||
|
||||
current_bsddb_version = str(db.version())
|
||||
if bsddb_version != current_bsddb_version:
|
||||
return "Unknown", bsddb_version, "Unknown"
|
||||
|
||||
env = db.DBEnv()
|
||||
flags = db.DB_CREATE | db.DB_PRIVATE |\
|
||||
db.DB_INIT_MPOOL | db.DB_INIT_LOCK |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN | db.DB_THREAD
|
||||
db.DB_INIT_MPOOL |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN
|
||||
try:
|
||||
env.open(file_name, flags)
|
||||
except:
|
||||
return "Unknown", "Unknown"
|
||||
env.open(dirpath, flags)
|
||||
except Exception as msg:
|
||||
LOG.warning("Error opening db environment for '%s': %s" %
|
||||
(name, str(msg)))
|
||||
try:
|
||||
env.close()
|
||||
except Exception as msg:
|
||||
LOG.warning("Error closing db environment for '%s': %s" %
|
||||
(name, str(msg)))
|
||||
return "Unknown", bsddb_version, "Unknown"
|
||||
dbmap1 = dbshelve.DBShelf(env)
|
||||
fname = os.path.join(file_name, META + ".db")
|
||||
fname = os.path.join(dirpath, META + ".db")
|
||||
try:
|
||||
dbmap1.open(fname, META, db.DB_HASH, db.DB_RDONLY)
|
||||
except:
|
||||
env.close()
|
||||
return "Unknown", "Unknown"
|
||||
version = dbmap1.get('version', default=None)
|
||||
return "Unknown", bsddb_version, "Unknown"
|
||||
schema_version = dbmap1.get(b'version', default=None)
|
||||
dbmap1.close()
|
||||
dbmap2 = dbshelve.DBShelf(env)
|
||||
fname = os.path.join(file_name, PERSON_TBL + ".db")
|
||||
fname = os.path.join(dirpath, PERSON_TBL + ".db")
|
||||
try:
|
||||
dbmap2.open(fname, PERSON_TBL, db.DB_HASH, db.DB_RDONLY)
|
||||
except:
|
||||
env.close()
|
||||
return "Unknown", "Unknown"
|
||||
return "Unknown", bsddb_version, schema_version
|
||||
count = len(dbmap2)
|
||||
dbmap2.close()
|
||||
env.close()
|
||||
return (count, version)
|
||||
return (count, bsddb_version, schema_version)
|
||||
|
||||
def family_tree_summary(self):
|
||||
"""
|
||||
Return a list of dictionaries of the known family trees.
|
||||
"""
|
||||
# make the default directory if it does not exist
|
||||
list = []
|
||||
summary_list = []
|
||||
for item in self.current_names:
|
||||
(name, dirpath, path_name, last,
|
||||
tval, enable, stock_id) = item
|
||||
count, version = self.get_dbdir_summary(dirpath)
|
||||
count, bsddb_version, schema_version = self.get_dbdir_summary(dirpath, name)
|
||||
retval = {}
|
||||
retval["Number of people"] = count
|
||||
retval[_("Number of people")] = count
|
||||
if enable:
|
||||
retval["Locked?"] = "yes"
|
||||
retval[_("Locked?")] = _("yes")
|
||||
else:
|
||||
retval["Locked?"] = "no"
|
||||
retval["DB version"] = version
|
||||
retval[_("Locked?")] = _("no")
|
||||
retval[_("Bsddb version")] = bsddb_version
|
||||
retval[_("Schema version")] = schema_version
|
||||
if sys.version_info[0] < 3:
|
||||
retval["Family tree"] = name.encode(glocale.getfilesystemencoding())
|
||||
retval[_("Family Tree")] = name.encode(glocale.getfilesystemencoding())
|
||||
else:
|
||||
retval["Family tree"] = name
|
||||
retval["Path"] = dirpath
|
||||
retval["Last accessed"] = time.strftime('%x %X',
|
||||
retval[_("Family Tree")] = name
|
||||
retval[_("Path")] = dirpath
|
||||
retval[_("Last accessed")] = time.strftime('%x %X',
|
||||
time.localtime(tval))
|
||||
list.append( retval )
|
||||
return list
|
||||
summary_list.append( retval )
|
||||
return summary_list
|
||||
|
||||
def _populate_cli(self):
|
||||
""" Get the list of current names in the database dir
|
||||
@@ -327,6 +352,11 @@ class CLIDbManager(object):
|
||||
# write locally:
|
||||
temp_fp.write(data)
|
||||
url_fp.close()
|
||||
from gen.db.dbconst import BDBVERSFN
|
||||
versionpath = os.path.join(name, BDBVERSFN)
|
||||
_LOG.debug("Write bsddb version %s" % str(dbase.version()))
|
||||
with open(versionpath, "w") as version_file:
|
||||
version_file.write(str(dbase.version()))
|
||||
temp_fp.close()
|
||||
|
||||
(name, ext) = os.path.splitext(os.path.basename(filename))
|
||||
@@ -382,7 +412,7 @@ class CLIDbManager(object):
|
||||
name_file.write(new_text)
|
||||
name_file.close()
|
||||
except (OSError, IOError) as msg:
|
||||
CLIDbManager.ERROR(_("Could not rename family tree"),
|
||||
CLIDbManager.ERROR(_("Could not rename Family Tree"),
|
||||
str(msg))
|
||||
return None, None
|
||||
return old_text, new_text
|
||||
|
@@ -36,7 +36,7 @@ Provides also two small base classes: CLIDbLoader, CLIManager
|
||||
from __future__ import print_function
|
||||
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -55,7 +55,13 @@ from gramps.gen.errors import DbError
|
||||
from gramps.gen.dbstate import DbState
|
||||
from gramps.gen.db import DbBsddb
|
||||
from gramps.gen.db.exceptions import (DbUpgradeRequiredError,
|
||||
DbVersionError)
|
||||
BsddbDowngradeError,
|
||||
DbVersionError,
|
||||
DbEnvironmentError,
|
||||
BsddbUpgradeRequiredError,
|
||||
BsddbDowngradeRequiredError,
|
||||
PythonUpgradeRequiredError,
|
||||
PythonDowngradeError)
|
||||
from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.utils.config import get_researcher
|
||||
from gramps.gen.recentfiles import recent_files
|
||||
@@ -77,14 +83,14 @@ class CLIDbLoader(object):
|
||||
"""
|
||||
Issue a warning message. Inherit for GUI action
|
||||
"""
|
||||
print(_('WARNING: %s') % warnmessage)
|
||||
print(_('WARNING: %s') % warnmessage, file=sys.stderr)
|
||||
|
||||
def _errordialog(self, title, errormessage):
|
||||
"""
|
||||
Show the error. A title for the error and an errormessage
|
||||
Inherit for GUI action
|
||||
"""
|
||||
print(_('ERROR: %s') % errormessage)
|
||||
print(_('ERROR: %s') % errormessage, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def _dberrordialog(self, msg):
|
||||
@@ -158,17 +164,35 @@ class CLIDbLoader(object):
|
||||
try:
|
||||
self.dbstate.db.load(filename, self._pulse_progress, mode)
|
||||
self.dbstate.db.set_save_path(filename)
|
||||
except gen.db.exceptions.DbUpgradeRequiredError as msg:
|
||||
except DbEnvironmentError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except gen.db.exceptions.DbVersionError as msg:
|
||||
except BsddbUpgradeRequiredError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except BsddbDowngradeRequiredError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except BsddbDowngradeError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except DbUpgradeRequiredError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except PythonDowngradeError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except PythonUpgradeRequiredError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except DbVersionError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog( _("Cannot open database"), str(msg))
|
||||
except OSError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._errordialog(
|
||||
_("Could not open file: %s") % filename, str(msg))
|
||||
except Errors.DbError as msg:
|
||||
except DbError as msg:
|
||||
self.dbstate.no_database()
|
||||
self._dberrordialog(msg)
|
||||
except Exception:
|
||||
@@ -197,7 +221,7 @@ class CLIManager(object):
|
||||
self.db_loader = None
|
||||
self.file_loaded = False
|
||||
self._pmgr = BasePluginManager.get_instance()
|
||||
|
||||
|
||||
def open_activate(self, path):
|
||||
"""
|
||||
Open and make a family tree active
|
||||
@@ -208,7 +232,7 @@ class CLIManager(object):
|
||||
"""
|
||||
Show the error. A title for the error and an errormessage
|
||||
"""
|
||||
print(_('ERROR: %s') % errormessage)
|
||||
print(_('ERROR: %s') % errormessage, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def _read_recent_file(self, filename):
|
||||
@@ -295,24 +319,18 @@ def startcli(errors, argparser):
|
||||
"""
|
||||
if errors:
|
||||
#already errors encountered. Show first one on terminal and exit
|
||||
# Convert error message to file system encoding before print
|
||||
errmsg = _('Error encountered: %s') % errors[0][0]
|
||||
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
|
||||
print(errmsg)
|
||||
print(errmsg, file=sys.stderr)
|
||||
errmsg = _(' Details: %s') % errors[0][1]
|
||||
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
|
||||
print(errmsg)
|
||||
print(errmsg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if argparser.errors:
|
||||
# Convert error message to file system encoding before print
|
||||
errmsg = _('Error encountered in argument parsing: %s') \
|
||||
% argparser.errors[0][0]
|
||||
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
|
||||
print(errmsg)
|
||||
print(errmsg, file=sys.stderr)
|
||||
errmsg = _(' Details: %s') % argparser.errors[0][1]
|
||||
errmsg = errmsg.encode(sys.stdout.encoding, 'backslashreplace')
|
||||
print(errmsg)
|
||||
print(errmsg, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
#we need to keep track of the db state
|
||||
|
@@ -6,7 +6,7 @@
|
||||
# Copyright (C) 2008 Raphael Ackermann
|
||||
# Copyright (C) 2008-2011 Brian G. Matherly
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2011-2012 Paul Franklin
|
||||
# Copyright (C) 2011-2013 Paul Franklin
|
||||
#
|
||||
# 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
|
||||
@@ -34,9 +34,6 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import print_function
|
||||
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
import traceback
|
||||
import os
|
||||
import sys
|
||||
@@ -60,13 +57,15 @@ from gramps.gen.display.name import displayer as name_displayer
|
||||
from gramps.gen.errors import ReportError, FilterError
|
||||
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
||||
CATEGORY_GRAPHVIZ, CATEGORY_CODE,
|
||||
ReportOptions, create_style_sheet)
|
||||
ReportOptions, append_styles)
|
||||
from gramps.gen.plug.report._paper import paper_sizes
|
||||
from gramps.gen.const import USER_HOME
|
||||
from gramps.gen.dbstate import DbState
|
||||
from gramps.gen.constfunc import STRTYPE, conv_to_unicode_direct
|
||||
from ..grampscli import CLIManager
|
||||
from ..user import User
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@@ -169,7 +168,8 @@ def _validate_options(options, dbase):
|
||||
phandle = None
|
||||
person = dbase.get_person_from_handle(phandle)
|
||||
if not person:
|
||||
print(_("ERROR: Please specify a person"))
|
||||
print(_("ERROR: Please specify a person"),
|
||||
file=sys.stderr)
|
||||
if person:
|
||||
option.set_value(person.get_gramps_id())
|
||||
|
||||
@@ -193,7 +193,7 @@ def _validate_options(options, dbase):
|
||||
family = dbase.get_family_from_handle(family_handle)
|
||||
option.set_value(family.get_gramps_id())
|
||||
else:
|
||||
print(_("ERROR: Please specify a family"))
|
||||
print(_("ERROR: Please specify a family"), file=sys.stderr)
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@@ -265,17 +265,21 @@ class CommandLineReport(object):
|
||||
}
|
||||
|
||||
self.options_help = {
|
||||
'of' : ["=filename", "Output file name. MANDATORY", ""],
|
||||
'off' : ["=format", "Output file format.", []],
|
||||
'style' : ["=name", "Style name.", ""],
|
||||
'papers' : ["=name", "Paper size name.", ""],
|
||||
'papero' : ["=num", "Paper orientation number.", ""],
|
||||
'paperml' : ["=num", "Left paper margin", "Size in cm"],
|
||||
'papermr' : ["=num", "Right paper margin", "Size in cm"],
|
||||
'papermt' : ["=num", "Top paper margin", "Size in cm"],
|
||||
'papermb' : ["=num", "Bottom paper margin", "Size in cm"],
|
||||
'css' : ["=css filename", "CSS filename to use, html format"
|
||||
" only", ""],
|
||||
'of' : [_("=filename"), _("Output file name. MANDATORY"),""],
|
||||
'off' : [_("=format"), _("Output file format."), []],
|
||||
'style' : [_("=name"), _("Style name."), ""],
|
||||
'papers' : [_("=name"), _("Paper size name."), ""],
|
||||
'papero' : [_("=number"), _("Paper orientation number."), ""],
|
||||
'paperml' : [_("=number"), _("Left paper margin"),
|
||||
_("Size in cm")],
|
||||
'papermr' : [_("=number"), _("Right paper margin"),
|
||||
_("Size in cm")],
|
||||
'papermt' : [_("=number"), _("Top paper margin"),
|
||||
_("Size in cm")],
|
||||
'papermb' : [_("=number"), _("Bottom paper margin"),
|
||||
_("Size in cm")],
|
||||
'css' : [_("=css filename"), _("CSS filename to use, "
|
||||
"html format only"), ""],
|
||||
}
|
||||
|
||||
if noopt:
|
||||
@@ -299,7 +303,7 @@ class CommandLineReport(object):
|
||||
elif self.category == CATEGORY_GRAPHVIZ:
|
||||
for graph_format in graphdoc.FORMATS:
|
||||
self.options_help['off'][2].append(
|
||||
graph_format["ext"] + "\t" + graph_format["descr"] )
|
||||
graph_format["type"] + "\t" + graph_format["descr"] )
|
||||
else:
|
||||
self.options_help['off'][2] = "NA"
|
||||
|
||||
@@ -417,12 +421,14 @@ class CommandLineReport(object):
|
||||
elif isinstance(option, Option):
|
||||
self.options_help[name].append(option.get_help())
|
||||
else:
|
||||
print(_("Unknown option: %s") % option)
|
||||
print(_(" Valid options are:"),
|
||||
", ".join(list(self.options_dict.keys())))
|
||||
print((_(" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values") %
|
||||
{'donottranslate' : "show=option"}))
|
||||
print(_("Unknown option: %s") % option, file=sys.stderr)
|
||||
print(_(" Valid options are:") +
|
||||
", ".join(list(self.options_dict.keys())),
|
||||
file=sys.stderr)
|
||||
print(_(" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values")
|
||||
% {'donottranslate' : "show=option"},
|
||||
file=sys.stderr)
|
||||
|
||||
def parse_options(self):
|
||||
"""
|
||||
@@ -462,23 +468,24 @@ class CommandLineReport(object):
|
||||
_chosen_format = plugin.get_extension()
|
||||
elif self.category == CATEGORY_GRAPHVIZ:
|
||||
for graph_format in graphdoc.FORMATS:
|
||||
if graph_format['ext'] == self.options_dict['off']:
|
||||
if graph_format['type'] == self.options_dict['off']:
|
||||
if not self.format: # choose the first one, not the last
|
||||
self.format = graph_format["class"]
|
||||
if self.format is None:
|
||||
# Pick the first one as the default.
|
||||
self.format = graphdoc.FORMATS[0]["class"]
|
||||
_chosen_format = graphdoc.FORMATS[0]["ext"]
|
||||
_chosen_format = graphdoc.FORMATS[0]["type"]
|
||||
else:
|
||||
self.format = None
|
||||
if _chosen_format and _format_str:
|
||||
print((_("Ignoring '%(notranslate1)s=%(notranslate2)s' "
|
||||
"and using '%(notranslate1)s=%(notranslate3)s'.") %
|
||||
{'notranslate1' : "off",
|
||||
'notranslate2' : self.options_dict['off'],
|
||||
'notranslate3' : _chosen_format}))
|
||||
print((_("Use '%(notranslate)s' to see valid values.") %
|
||||
{'notranslate' : "show=off"}))
|
||||
print(_("Ignoring '%(notranslate1)s=%(notranslate2)s' "
|
||||
"and using '%(notranslate1)s=%(notranslate3)s'.")
|
||||
% {'notranslate1' : "off",
|
||||
'notranslate2' : self.options_dict['off'],
|
||||
'notranslate3' : _chosen_format},
|
||||
file=sys.stderr)
|
||||
print(_("Use '%(notranslate)s' to see valid values.")
|
||||
% {'notranslate' : "show=off"}, file=sys.stderr)
|
||||
|
||||
self.do_doc_options()
|
||||
|
||||
@@ -490,21 +497,23 @@ class CommandLineReport(object):
|
||||
|
||||
self.option_class.handler.options_dict[opt] = \
|
||||
self.options_dict[opt]
|
||||
|
||||
|
||||
if menu and opt in menu_opt_names:
|
||||
option = menu.get_option_by_name(opt)
|
||||
option.set_value(self.options_dict[opt])
|
||||
|
||||
else:
|
||||
print(_("Ignoring unknown option: %s") % opt )
|
||||
print(_("Ignoring unknown option: %s") % opt, file=sys.stderr)
|
||||
print(_(" Valid options are:"),
|
||||
", ".join(list(self.options_dict.keys())))
|
||||
", ".join(list(self.options_dict.keys())),
|
||||
file=sys.stderr)
|
||||
print(_(" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values") %
|
||||
{'donottranslate' : "show=option"})
|
||||
{'donottranslate' : "show=option"}, file=sys.stderr)
|
||||
|
||||
self.option_class.handler.output = self.options_dict['of']
|
||||
|
||||
self.paper = paper_sizes[0] # make sure one exists
|
||||
for paper in paper_sizes:
|
||||
if paper.get_name() == self.options_dict['papers']:
|
||||
self.paper = paper
|
||||
@@ -571,14 +580,13 @@ class CommandLineReport(object):
|
||||
# Make the output nicer to read, assume a tab has 8 spaces
|
||||
tabs = '\t\t' if len(key) < 10 else '\t'
|
||||
optmsg = " %s%s%s (%s)" % (key, tabs, opt[1], opt[0])
|
||||
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
else:
|
||||
optmsg = " %s%s%s" % (key, tabs,
|
||||
_('(no help available)'))
|
||||
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print((_(" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values") %
|
||||
{'donottranslate' : "show=option"}))
|
||||
print(optmsg)
|
||||
print(_(" Use '%(donottranslate)s' to see description "
|
||||
"and acceptable values")
|
||||
% {'donottranslate' : "show=option"})
|
||||
elif self.show in self.options_help:
|
||||
opt = self.options_help[self.show]
|
||||
tabs = '\t\t' if len(self.show) < 10 else '\t'
|
||||
@@ -587,17 +595,17 @@ class CommandLineReport(object):
|
||||
vals = opt[2]
|
||||
if isinstance(vals, (list, tuple)):
|
||||
for val in vals:
|
||||
optmsg = " %s" % val
|
||||
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(" %s" % val)
|
||||
else:
|
||||
optmsg = " %s" % opt[2]
|
||||
print(optmsg.encode(sys.stdout.encoding, 'backslashreplace'))
|
||||
print(" %s" % opt[2])
|
||||
|
||||
else:
|
||||
#there was a show option given, but the option is invalid
|
||||
print((_("option '%(optionname)s' not valid. "
|
||||
"Use '%(donottranslate)s' to see all valid options.") %
|
||||
{'optionname' : self.show, 'donottranslate' : "show=all"}))
|
||||
print(_("option '%(optionname)s' not valid. "
|
||||
"Use '%(donottranslate)s' to see all valid options.")
|
||||
% {'optionname' : self.show,
|
||||
'donottranslate' : "show=all"},
|
||||
file=sys.stderr)
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@@ -645,10 +653,10 @@ def cl_report(database, name, category, report_class, options_class,
|
||||
return clr
|
||||
except ReportError as msg:
|
||||
(m1, m2) = msg.messages()
|
||||
print(err_msg)
|
||||
print(m1)
|
||||
print(err_msg, file=sys.stderr)
|
||||
print(m1, file=sys.stderr)
|
||||
if m2:
|
||||
print(m2)
|
||||
print(m2, file=sys.stderr)
|
||||
except:
|
||||
if len(log.handlers) > 0:
|
||||
log.error(err_msg, exc_info=True)
|
||||
@@ -727,7 +735,7 @@ def cl_book(database, name, book, options_str_dict):
|
||||
clr.marginr, clr.margint, clr.marginb))
|
||||
user = User()
|
||||
rptlist = []
|
||||
global_style = None
|
||||
selected_style = StyleSheet()
|
||||
for item in book.get_item_list():
|
||||
|
||||
# The option values were loaded magically by the book parser.
|
||||
@@ -743,27 +751,20 @@ def cl_book(database, name, book, options_str_dict):
|
||||
report_class = item.get_write_item()
|
||||
obj = write_book_item(database,
|
||||
report_class, item.option_class, user)
|
||||
style_sheet = create_style_sheet(item)
|
||||
rptlist.append((obj, style_sheet))
|
||||
if ( item.name == 'table_of_contents' or
|
||||
item.name == 'alphabetical_index' ): # ugly hack: FIXME
|
||||
if global_style is None:
|
||||
global_style = style_sheet
|
||||
else:
|
||||
global_style = create_style_sheet(item, global_style)
|
||||
if obj:
|
||||
append_styles(selected_style, item)
|
||||
rptlist.append(obj)
|
||||
|
||||
doc.set_style_sheet(selected_style)
|
||||
doc.open(clr.option_class.get_output())
|
||||
doc.init()
|
||||
newpage = 0
|
||||
for rpt, style_sheet in rptlist:
|
||||
doc.set_style_sheet(style_sheet)
|
||||
for rpt in rptlist:
|
||||
if newpage:
|
||||
doc.page_break()
|
||||
newpage = 1
|
||||
rpt.begin_report()
|
||||
rpt.write_report()
|
||||
if global_style:
|
||||
doc.set_style_sheet(global_style)
|
||||
doc.close()
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
@@ -778,10 +779,10 @@ def write_book_item(database, report_class, options, user):
|
||||
return report_class(database, options, user)
|
||||
except ReportError as msg:
|
||||
(m1, m2) = msg.messages()
|
||||
print("ReportError", m1, m2)
|
||||
print("ReportError", m1, m2, file=sys.stderr)
|
||||
except FilterError as msg:
|
||||
(m1, m2) = msg.messages()
|
||||
print("FilterError", m1, m2)
|
||||
print("FilterError", m1, m2, file=sys.stderr)
|
||||
except:
|
||||
log.error("Failed to write book item.", exc_info=True)
|
||||
return None
|
||||
|
@@ -39,7 +39,7 @@ import sys
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.user import User
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
|
@@ -42,7 +42,7 @@ import logging
|
||||
#
|
||||
#---------------------------------------------------------------
|
||||
from .const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
from .const import HOME_DIR, USER_HOME, VERSION_DIR
|
||||
from .utils.configmanager import ConfigManager
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#
|
||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
||||
# Copyright (C) 2012 Doug Blank
|
||||
# Copyright (C) 2013 John Ralls <jralls@ceridwen.us>
|
||||
#
|
||||
# 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
|
||||
@@ -50,21 +51,7 @@ from .svn_revision import get_svn_revision
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
PROGRAM_NAME = "Gramps"
|
||||
VERSION = "@VERSIONSTRING@"
|
||||
if VERSION == "@" + "VERSIONSTRING" + "@":
|
||||
raise Exception("Please run 'python setup.py build'")
|
||||
def get_version_tuple(v):
|
||||
""" Get the numeric-dotted part of version number"""
|
||||
retval = ""
|
||||
for c in v:
|
||||
if c.isdigit() or (c == "." and retval.count(".") <= 1):
|
||||
retval += c
|
||||
else:
|
||||
break
|
||||
return tuple(map(int, retval.split(".")))
|
||||
VERSION_TUPLE = get_version_tuple(VERSION)
|
||||
major_version = "%s.%s" % (VERSION_TUPLE[0], VERSION_TUPLE[1])
|
||||
|
||||
from ..version import VERSION, VERSION_TUPLE, major_version
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard GRAMPS Websites
|
||||
@@ -93,17 +80,6 @@ APP_GRAMPS_PKG = "application/x-gramps-package"
|
||||
APP_GENEWEB = "application/x-geneweb"
|
||||
APP_VCARD = ["text/x-vcard", "text/x-vcalendar"]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Platforms
|
||||
# Never test on LINUX, handle Linux in the else statement as default
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
LINUX = ["Linux", "linux", "linux2"]
|
||||
MACOS = ["Darwin", "darwin"]
|
||||
WINDOWS = ["Windows", "win32"]
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Determine the home directory. According to Wikipedia, most UNIX like
|
||||
@@ -184,12 +160,10 @@ RULE_GLADE = os.path.join(GLADE_DIR, "rule.glade")
|
||||
|
||||
PLUGINS_DIR = os.path.join(ROOT_DIR, "plugins")
|
||||
WEB_DIR = os.path.join(ROOT_DIR, 'webapp')
|
||||
WEBSTUFF_DIR = os.path.join(PLUGINS_DIR, "webstuff")
|
||||
WEBSTUFF_IMAGE_DIR = os.path.join(WEBSTUFF_DIR, "images")
|
||||
|
||||
USE_TIPS = False
|
||||
|
||||
if os.sys.platform in WINDOWS:
|
||||
if sys.platform == 'win32':
|
||||
USE_THUMBNAILER = False
|
||||
else:
|
||||
USE_THUMBNAILER = True
|
||||
@@ -199,10 +173,10 @@ else:
|
||||
# Paths to data files.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
LOCALE_DIR = "@LOCALE_DIR@"
|
||||
DATA_DIR = "@DATA_DIR@"
|
||||
IMAGE_DIR = "@IMAGE_DIR@"
|
||||
DOC_DIR = "@DOC_DIR@"
|
||||
from gramps.gen.utils.resourcepath import ResourcePath
|
||||
_resources = ResourcePath()
|
||||
DATA_DIR = _resources.data_dir
|
||||
IMAGE_DIR = _resources.image_dir
|
||||
|
||||
TIP_DATA = os.path.join(DATA_DIR, "tips.xml")
|
||||
PAPERSIZE = os.path.join(DATA_DIR, "papersize.xml")
|
||||
@@ -211,15 +185,15 @@ ICON = os.path.join(IMAGE_DIR, "gramps.png")
|
||||
LOGO = os.path.join(IMAGE_DIR, "logo.png")
|
||||
SPLASH = os.path.join(IMAGE_DIR, "splash.jpg")
|
||||
|
||||
LICENSE_FILE = os.path.join(DOC_DIR, 'COPYING')
|
||||
LICENSE_FILE = os.path.join(_resources.doc_dir, 'COPYING')
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Init Localization
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .utils.grampslocale import GrampsLocale
|
||||
GRAMPS_LOCALE = GrampsLocale()
|
||||
_ = GRAMPS_LOCALE.get_translation().sgettext
|
||||
from gramps.gen.utils.grampslocale import GrampsLocale
|
||||
GRAMPS_LOCALE = GrampsLocale(localedir=_resources.locale_dir)
|
||||
_ = GRAMPS_LOCALE.translation.sgettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -238,9 +212,10 @@ AUTHORS = [
|
||||
"Donald A. Peterson",
|
||||
"Donald N. Allingham",
|
||||
"David Hampton",
|
||||
"Martin Hawlisch",
|
||||
"Martin Hawlisch",
|
||||
"Richard Taylor",
|
||||
"Tim Waugh",
|
||||
"Tim Waugh",
|
||||
"John Ralls"
|
||||
]
|
||||
|
||||
AUTHORS_FILE = os.path.join(DATA_DIR, "authors.xml")
|
||||
@@ -329,32 +304,6 @@ LONGOPTS = [
|
||||
"qml",
|
||||
]
|
||||
|
||||
SHORTOPTS = "O:C:i:e:f:a:p:d:c:lLhuv?s"
|
||||
SHORTOPTS = "O:C:i:e:f:a:p:d:c:lLthuv?s"
|
||||
|
||||
GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')
|
||||
|
||||
def need_to_update_const():
|
||||
""" Check to see if this file is older than
|
||||
setup.py or const.py.in """
|
||||
this_file = os.path.join(ROOT_DIR, "gen", "const.py")
|
||||
in_file = os.path.join(ROOT_DIR, "gen", "const.py.in")
|
||||
setup_file = os.path.join(ROOT_DIR, "..", "setup.py")
|
||||
|
||||
if (os.path.exists(this_file) and
|
||||
os.path.exists(in_file) and
|
||||
os.path.exists(setup_file)):
|
||||
|
||||
this_file_time = os.path.getmtime(this_file)
|
||||
in_file_time = os.path.getmtime(in_file)
|
||||
setup_file_time = os.path.getmtime(setup_file)
|
||||
|
||||
# Is this file older than others? If so,
|
||||
# need to run setup
|
||||
return (this_file_time < in_file_time or
|
||||
this_file_time < setup_file_time)
|
||||
else:
|
||||
# Can't tell because can't find the files
|
||||
return False
|
||||
|
||||
if need_to_update_const():
|
||||
print("Outdated gramps.gen.const; please run 'python setup.py build'")
|
@@ -37,10 +37,21 @@ import sys
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .const import WINDOWS, MACOS, LINUX
|
||||
import warnings
|
||||
import functools
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Platforms
|
||||
# Never test on LINUX, handle Linux in the else statement as default
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
LINUX = ["Linux", "linux", "linux2"]
|
||||
MACOS = ["Darwin", "darwin"]
|
||||
WINDOWS = ["Windows", "win32"]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -156,3 +167,33 @@ def mod_key():
|
||||
return "<ctrl>"
|
||||
|
||||
return "<alt>"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DECORATORS
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
def deprecated(func):
|
||||
'''This is a decorator which can be used to mark functions
|
||||
as deprecated. It will result in a warning being emitted
|
||||
when the function is used.'''
|
||||
|
||||
@functools.wraps(func)
|
||||
def new_func(*args, **kwargs):
|
||||
if sys.version_info[0] <3:
|
||||
warnings.warn_explicit(
|
||||
"Call to deprecated function {}.".format(func.__name__),
|
||||
category=DeprecationWarning,
|
||||
filename=func.func_code.co_filename,
|
||||
lineno=func.func_code.co_firstlineno + 1
|
||||
)
|
||||
else:
|
||||
warnings.warn_explicit(
|
||||
"Call to deprecated function {}.".format(func.__name__),
|
||||
category=DeprecationWarning,
|
||||
filename=func.__code__.co_filename,
|
||||
lineno=func.__code__.co_firstlineno + 1
|
||||
)
|
||||
return func(*args, **kwargs)
|
||||
return new_func
|
||||
|
@@ -24,8 +24,15 @@
|
||||
Class handling language-specific selection for date parser and displayer.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.sgettext
|
||||
# import prerequisites for localized handlers
|
||||
from ._datehandler import (LANG, LANG_SHORT, LANG_TO_PARSER, LANG_TO_DISPLAY,
|
||||
register_datehandler)
|
||||
@@ -51,6 +58,7 @@ from . import _date_sk
|
||||
from . import _date_sl
|
||||
from . import _date_sr
|
||||
from . import _date_sv
|
||||
from . import _date_uk
|
||||
|
||||
# Initialize global parser
|
||||
try:
|
||||
@@ -59,7 +67,7 @@ try:
|
||||
else:
|
||||
parser = LANG_TO_PARSER[LANG_SHORT]()
|
||||
except:
|
||||
print("Date parser for", LANG, "not available, using default")
|
||||
logging.warning(_("Date parser for '%s' not available, using default") % LANG)
|
||||
parser = LANG_TO_PARSER["C"]()
|
||||
|
||||
# Initialize global displayer
|
||||
@@ -75,7 +83,7 @@ try:
|
||||
else:
|
||||
displayer = LANG_TO_DISPLAY[LANG_SHORT](val)
|
||||
except:
|
||||
print("Date displayer for", LANG, "not available, using default")
|
||||
logging.warning(_("Date displayer for '%s' not available, using default") % LANG)
|
||||
displayer = LANG_TO_DISPLAY["C"](val)
|
||||
|
||||
|
||||
|
364
gramps/gen/datehandler/_date_uk.py
Normal file
@@ -0,0 +1,364 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2004-2006 Donald N. Allingham
|
||||
# Copyright (C) 2013 Fedir Zinchuk <fedikw[at]gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
|
||||
"""
|
||||
Ukrainian-specific classes for parsing and displaying dates.
|
||||
"""
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from __future__ import unicode_literals
|
||||
import re
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GRAMPS modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
from ..lib.date import Date
|
||||
from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay
|
||||
from ._datehandler import register_datehandler
|
||||
from . import _grampslocale
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Ukrainian parser
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateParserUK(DateParser):
|
||||
"""
|
||||
Convert a text string into a Date object. If the date cannot be
|
||||
converted, the text string is assigned.
|
||||
"""
|
||||
|
||||
month_to_int = DateParser.month_to_int
|
||||
|
||||
# the genitive
|
||||
month_to_int["січня"] = 1
|
||||
month_to_int["лютого"] = 2
|
||||
month_to_int["березня"] = 3
|
||||
month_to_int["квітня"] = 4
|
||||
month_to_int["травня"] = 5
|
||||
month_to_int["червня"] = 6
|
||||
month_to_int["липня"] = 7
|
||||
month_to_int["серпня"] = 8
|
||||
month_to_int["вересня"] = 9
|
||||
month_to_int["жовтня"] = 10
|
||||
month_to_int["листопада"] = 11
|
||||
month_to_int["грудня"] = 12
|
||||
|
||||
# some short variants of the months
|
||||
month_to_int["січ."] = 1
|
||||
month_to_int["січ"] = 1
|
||||
month_to_int["лют."] = 2
|
||||
month_to_int["лют"] = 2
|
||||
month_to_int["бер."] = 3
|
||||
month_to_int["бер"] = 3
|
||||
month_to_int["квіт."] = 4
|
||||
month_to_int["квіт"] = 4
|
||||
month_to_int["трав."] = 5
|
||||
month_to_int["трав"] = 5
|
||||
month_to_int["черв."] = 6
|
||||
month_to_int["черв"] = 6
|
||||
month_to_int["лип."] = 7
|
||||
month_to_int["лип"] = 7
|
||||
month_to_int["серп."] = 8
|
||||
month_to_int["серп"] = 8
|
||||
month_to_int["вер."] = 9
|
||||
month_to_int["вер"] = 9
|
||||
month_to_int["жовт."] = 10
|
||||
month_to_int["жовт"] = 10
|
||||
month_to_int["лист."] = 11
|
||||
month_to_int["лист"] = 11
|
||||
month_to_int["груд."] = 12
|
||||
month_to_int["груд"] = 12
|
||||
|
||||
|
||||
# modifiers before the date
|
||||
modifier_to_int = {
|
||||
'перед' : Date.MOD_BEFORE,
|
||||
'до' : Date.MOD_BEFORE,
|
||||
'раніше' : Date.MOD_BEFORE,
|
||||
|
||||
'після' : Date.MOD_AFTER,
|
||||
'п.' : Date.MOD_AFTER,
|
||||
'за' : Date.MOD_AFTER,
|
||||
|
||||
'приблизно': Date.MOD_ABOUT,
|
||||
'прибл.' : Date.MOD_ABOUT,
|
||||
'приб.' : Date.MOD_ABOUT,
|
||||
'близько' : Date.MOD_ABOUT,
|
||||
'бл.' : Date.MOD_ABOUT,
|
||||
'біля' : Date.MOD_ABOUT,
|
||||
}
|
||||
|
||||
hebrew_to_int = {
|
||||
"тішрі" : 1, "хешвен" : 2, "кіслев" : 3,
|
||||
"тевет" : 4, "шват" : 5, "адар" : 6,
|
||||
"адара" : 7, "нісан" : 8, "іяр" : 9,
|
||||
"сиван" : 10, "таммуз" : 11, "ав" : 12,
|
||||
"елул" : 13,
|
||||
#alternative spelling
|
||||
"мархешван": 2, "ве адар" : 7,
|
||||
#GEDCOM months
|
||||
"tsh" : 1, "csh": 5, "ksl": 3, "tvt": 4, "shv": 5, "adr": 6,
|
||||
"ads" : 7, "nsn": 8, "iyr": 9, "svn":10, "tmz":11, "aav":12,
|
||||
"ell":13,
|
||||
}
|
||||
|
||||
french_to_int = {
|
||||
'вандем’єр' : 1, 'брюмер' : 2,
|
||||
'фрімер' : 3, 'нівоз' : 4,
|
||||
'плювіоз' : 5, 'вентоз' : 6,
|
||||
'жерміналь' : 7, 'флореаль' : 8,
|
||||
'преріаль' : 9, 'мессідор' : 10,
|
||||
'термідор' : 11, 'фрюктідор': 12,
|
||||
'додатковий' : 13,
|
||||
#short
|
||||
'ванд' : 1, 'брюм' : 2,
|
||||
'фрім' : 3, 'нів' : 4,
|
||||
'плюв' : 5, 'вент' : 6,
|
||||
'жерм' : 7, 'флор' : 8,
|
||||
'прер' : 9, 'месс' : 10,
|
||||
'терм' : 11, 'фрюкт': 12,
|
||||
'дод' : 13,
|
||||
#GEDCOM months
|
||||
'vend' : 1, 'brum' : 2,
|
||||
'frim' : 3, 'nivo' : 4,
|
||||
'pluv' : 5, 'vent' : 6,
|
||||
'germ' : 7, 'flor' : 8,
|
||||
'prai' : 9, 'mess' : 10,
|
||||
'ther' : 11, 'fruc' : 12,
|
||||
'comp' : 13,
|
||||
}
|
||||
|
||||
islamic_to_int = {
|
||||
"мухаррам" : 1, "мухаррем" : 1,
|
||||
"сафар" : 2, "рабі-аль-авваль" : 3,
|
||||
"рабі-ассані" : 4,
|
||||
"джумада-аль-уля" : 5, "джумада-аль-авваль" : 5,
|
||||
"джумада-аль-ахіра" : 6, "джумада-ас-сані" : 6,
|
||||
"раджаб" : 7, "шаабан" : 8,
|
||||
"рамадан" : 9, "рамазан" : 9,
|
||||
"шавваль" : 10, "зуль-каада" : 11,
|
||||
"зуль-хіджжа" : 12,
|
||||
}
|
||||
|
||||
persian_to_int = {
|
||||
"фарвардін" : 1, "ордібехешт" : 2,
|
||||
"хордад" : 3, "тир" : 4,
|
||||
"мордад" : 5, "шахрівар" : 6,
|
||||
"мехр" : 7, "абан" : 8,
|
||||
"азар" : 9, "дей" : 10,
|
||||
"бахман" : 11, "есфанд" : 12,
|
||||
}
|
||||
|
||||
bce = ['до нашої ери', 'до н. е.', 'до н.е.']
|
||||
|
||||
calendar_to_int = {
|
||||
'григоріанський' : Date.CAL_GREGORIAN,
|
||||
'г' : Date.CAL_GREGORIAN,
|
||||
'юліанський' : Date.CAL_JULIAN,
|
||||
'ю' : Date.CAL_JULIAN,
|
||||
'єврейський' : Date.CAL_HEBREW,
|
||||
'є' : Date.CAL_HEBREW,
|
||||
'ісламський' : Date.CAL_ISLAMIC,
|
||||
'і' : Date.CAL_ISLAMIC,
|
||||
'французький' : Date.CAL_FRENCH,
|
||||
'французький республіканський': Date.CAL_FRENCH,
|
||||
'французький революційний' : Date.CAL_FRENCH,
|
||||
'ф' : Date.CAL_FRENCH,
|
||||
'іранський' : Date.CAL_PERSIAN,
|
||||
'перський' : Date.CAL_PERSIAN,
|
||||
'п' : Date.CAL_PERSIAN,
|
||||
'шведський' : Date.CAL_SWEDISH,
|
||||
'ш' : Date.CAL_SWEDISH,
|
||||
}
|
||||
|
||||
quality_to_int = {
|
||||
'за оцінкою' : Date.QUAL_ESTIMATED,
|
||||
'за оц.' : Date.QUAL_ESTIMATED,
|
||||
'оцінено' : Date.QUAL_ESTIMATED,
|
||||
'орієнтовно' : Date.QUAL_ESTIMATED,
|
||||
'приблизно' : Date.QUAL_ESTIMATED,
|
||||
'прибл.' : Date.QUAL_ESTIMATED,
|
||||
'підраховано' : Date.QUAL_CALCULATED,
|
||||
'підрах.' : Date.QUAL_CALCULATED,
|
||||
'розраховано' : Date.QUAL_CALCULATED,
|
||||
'розрахунково' : Date.QUAL_CALCULATED,
|
||||
'розрах.' : Date.QUAL_CALCULATED,
|
||||
}
|
||||
|
||||
def init_strings(self):
|
||||
"""
|
||||
This method compiles regular expression strings for matching dates.
|
||||
|
||||
See DateParser.init_strings()
|
||||
"""
|
||||
DateParser.init_strings(self)
|
||||
|
||||
_span_1 = ['з', 'від']
|
||||
# b.c.e. pattern also have "до" so skip "до н."
|
||||
_span_2 = ['по', 'до?!\sн\.']
|
||||
self._span = re.compile("(%s)\s+(?P<start>.+)\s+(%s)\s+(?P<stop>.+)" %
|
||||
('|'.join(_span_1), '|'.join(_span_2)),
|
||||
re.IGNORECASE)
|
||||
_range_1 = ['між']
|
||||
_range_2 = ['і', 'та']
|
||||
self._range = re.compile("(%s)\s+(?P<start>.+)\s+(%s)\s+(?P<stop>.+)" %
|
||||
('|'.join(_range_1), '|'.join(_range_2)),
|
||||
re.IGNORECASE)
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Ukrainian displayer
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DateDisplayUK(DateDisplay):
|
||||
"""
|
||||
Ukrainian language date display class.
|
||||
"""
|
||||
|
||||
# the months as the noun or as the genitive???
|
||||
|
||||
# as the genitive:
|
||||
long_months = (
|
||||
"", "січня", "лютого", "березня", "квітня",
|
||||
"травня", "червня", "липня", "серпня",
|
||||
"вересня", "жовтня", "листопада", "грудня"
|
||||
)
|
||||
|
||||
# as the noun:
|
||||
# long_months = (
|
||||
# "", "січень", "лютий", "березень", "квітень",
|
||||
# "травень", "червень", "липень", "серпень",
|
||||
# "вересень", "жовтень", "листопад", "грудень"
|
||||
# )
|
||||
|
||||
short_months = (
|
||||
"", "січ.", "лют.", "бер.", "квіт.", "трав.", "черв.",
|
||||
"лип.", "серп.", "вер.", "жовт.", "лист.", "груд."
|
||||
)
|
||||
|
||||
hebrew = (
|
||||
"", "тішрі", "хешвен", "кіслев", "тевет", "шват",
|
||||
"адар", "адара", "нісан", "іяр", "сиван", "таммуз",
|
||||
"ав", "елул"
|
||||
)
|
||||
|
||||
french = (
|
||||
'', 'вандем’єр', 'брюмер', 'фрімер', 'нівоз',
|
||||
'плювіоз', 'вентоз', 'жерміналь', 'флореаль',
|
||||
'преріаль', 'мессідор', 'термідор', 'фрюктідор',
|
||||
'додатковий'
|
||||
)
|
||||
|
||||
persian = (
|
||||
"", "фарвардін", "ордібехешт", "хордад", "тир",
|
||||
"мордад", "шахрівар", "мехр", "абан",
|
||||
"азар", "дей", "бахман", "есфанд"
|
||||
)
|
||||
|
||||
islamic = (
|
||||
"", "мухаррам", "сафар", "рабі-аль-авваль",
|
||||
"рабі-ассані", "джумада-аль-уля", "джумада-аль-ахіра",
|
||||
"раджаб", "шаабан", "рамадан", "шавваль", "зуль-каада",
|
||||
"зуль-хіджжа",
|
||||
)
|
||||
|
||||
# Replace the previous "Numerical" by a string which
|
||||
# do have an explicit meaning: "System default (format)"
|
||||
_locale_tformat = _grampslocale.tformat
|
||||
_locale_tformat = _locale_tformat.replace('%d', "д")
|
||||
_locale_tformat = _locale_tformat.replace('%m', "м")
|
||||
_locale_tformat = _locale_tformat.replace('%Y', "р")
|
||||
|
||||
formats = (
|
||||
"рррр-мм-дд (ISO)", #0
|
||||
"стандартний для системи (" + _locale_tformat + ")", #1
|
||||
"місяць день, рік", #2
|
||||
"міс. дд, рррр", #3
|
||||
"день місяць рік", #4
|
||||
"дд міс. рррр" #5
|
||||
)
|
||||
|
||||
calendar = (
|
||||
"", "юліанський", "єврейський", "французький республіканський",
|
||||
"іранський", "ісламський", "шведський"
|
||||
)
|
||||
|
||||
_mod_str = ("", "до ", "після ", "близько ", "", "", "")
|
||||
|
||||
_qual_str = ("", "орієнтовно ", "розрахунково ")
|
||||
|
||||
_bce_str = "%s до н.е."
|
||||
|
||||
def display(self, date):
|
||||
"""
|
||||
Return a text string representing the date.
|
||||
"""
|
||||
mod = date.get_modifier()
|
||||
cal = date.get_calendar()
|
||||
qual = date.get_quality()
|
||||
start = date.get_start_date()
|
||||
newyear = date.get_new_year()
|
||||
|
||||
qual_str = self._qual_str[qual]
|
||||
|
||||
if mod == Date.MOD_TEXTONLY:
|
||||
return date.get_text()
|
||||
elif start == Date.EMPTY:
|
||||
return ""
|
||||
elif mod == Date.MOD_SPAN:
|
||||
d1 = self.display_cal[cal](start)
|
||||
d2 = self.display_cal[cal](date.get_stop_date())
|
||||
scal = self.format_extras(cal, newyear)
|
||||
return "%sз %s %s %s%s" % (qual_str, d1, 'по', d2,
|
||||
scal)
|
||||
elif mod == Date.MOD_RANGE:
|
||||
d1 = self.display_cal[cal](start)
|
||||
d2 = self.display_cal[cal](date.get_stop_date())
|
||||
scal = self.format_extras(cal, newyear)
|
||||
return "%s%s %s %s %s%s" % (qual_str, 'між', d1, 'та',
|
||||
d2, scal)
|
||||
else:
|
||||
text = self.display_cal[date.get_calendar()](start)
|
||||
scal = self.format_extras(cal, newyear)
|
||||
return "%s%s%s%s" % (qual_str, self._mod_str[mod],
|
||||
text, scal)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Register classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
register_datehandler(('uk_UA', 'uk', 'ukrainian', 'Ukrainian'),
|
||||
DateParserUK, DateDisplayUK)
|
@@ -30,7 +30,6 @@ from __future__ import unicode_literals
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import locale
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -49,16 +48,13 @@ log = logging.getLogger(".gen.datehandler")
|
||||
from ._dateparser import DateParser
|
||||
from ._datedisplay import DateDisplay, DateDisplayEn
|
||||
from ..constfunc import win, cuni
|
||||
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
if not win():
|
||||
LANG = locale.getlocale(locale.LC_TIME)[0]
|
||||
else:
|
||||
LANG = locale.getdefaultlocale(locale.LC_TIME)[0]
|
||||
LANG = glocale.calendar
|
||||
|
||||
# If LANG contains ".UTF-8" use only the part to the left of "."
|
||||
# Otherwise some date handler will not load.
|
||||
@@ -86,6 +82,7 @@ LANG_TO_PARSER = {
|
||||
LANG_TO_DISPLAY = {
|
||||
'C' : DateDisplayEn,
|
||||
'en' : DateDisplayEn,
|
||||
'en_GB' : DateDisplayEn,
|
||||
'English_United States' : DateDisplayEn,
|
||||
'zh_CN' : DateDisplay,
|
||||
'zh_TW' : DateDisplay,
|
||||
|
@@ -42,10 +42,7 @@ if sys.version_info[0] < 3:
|
||||
else:
|
||||
#locale returns unicode in python 3
|
||||
to_uni = lambda x, y: x
|
||||
try:
|
||||
codeset = glocale.get_translation().info()["charset"]
|
||||
except KeyError:
|
||||
codeset = "UTF-8"
|
||||
codeset = glocale.encoding
|
||||
|
||||
try:
|
||||
|
||||
@@ -238,7 +235,7 @@ except:
|
||||
# of the format '20/2/2009', '20/02/2009', '20.2.2009', '20.02.2009',
|
||||
# '20-2-2009', '20-02-2009', '2009/02/20', '2009.02.20', '2009-02-20',
|
||||
# '09-02-20' hence to reduce the possible values to test, make sure month
|
||||
# is double digit also day should be double digit, prefebably greater than
|
||||
# is double digit also day should be double digit, preferably greater than
|
||||
# 12 for human readablity
|
||||
|
||||
timestr = time.strftime('%x',(2005,10,25,1,1,1,1,1,1))
|
||||
|
@@ -67,9 +67,8 @@ else:
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from .exceptions import DbException
|
||||
from .write import (FAMILY_TBL, PLACES_TBL, LOCATION_TBL, SOURCES_TBL,
|
||||
MEDIA_TBL, EVENTS_TBL, PERSON_TBL, REPO_TBL, NOTE_TBL,
|
||||
TAG_TBL, META, CITATIONS_TBL)
|
||||
from .write import FAMILY_TBL, PLACES_TBL, SOURCES_TBL, MEDIA_TBL, \
|
||||
EVENTS_TBL, PERSON_TBL, REPO_TBL, NOTE_TBL, TAG_TBL, META, CITATIONS_TBL
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@@ -216,6 +215,5 @@ def __build_tbl_map(database):
|
||||
( MEDIA_TBL, database.media_map.db),
|
||||
( EVENTS_TBL, database.event_map.db),
|
||||
( TAG_TBL, database.tag_map.db),
|
||||
( LOCATION_TBL, database.location_map.db),
|
||||
( META, database.metadata.db),
|
||||
]
|
||||
|
@@ -33,7 +33,7 @@ from this class.
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -322,27 +322,6 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_location_cursor(self):
|
||||
"""
|
||||
Return a reference to a cursor over Location objects
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_location_from_handle(self, handle):
|
||||
"""
|
||||
Find a Location in the database from the passed handle.
|
||||
|
||||
If no such Location exists, None is returned.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_location_handles(self):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Location in
|
||||
the database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_media_attribute_types(self):
|
||||
"""
|
||||
Return a list of all Attribute types associated with Media and MediaRef
|
||||
@@ -458,12 +437,6 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_number_of_locations(self):
|
||||
"""
|
||||
Return the number of locations currently in the database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_number_of_media_objects(self):
|
||||
"""
|
||||
Return the number of media objects currently in the database.
|
||||
@@ -569,6 +542,13 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_source_attribute_types(self):
|
||||
"""
|
||||
Return a list of all Attribute types associated with Source/Citation
|
||||
instances in the database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_place_bookmarks(self):
|
||||
"""
|
||||
Return the list of Place handles in the bookmarks.
|
||||
@@ -619,12 +599,6 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_raw_location_data(self, handle):
|
||||
"""
|
||||
Return raw (serialized and pickled) Location object from handle
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_raw_note_data(self, handle):
|
||||
"""
|
||||
Return raw (serialized and pickled) Note object from handle
|
||||
@@ -901,12 +875,6 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def has_location_handle(self, handle):
|
||||
"""
|
||||
Return True if the handle exists in the current Location database.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def has_name_group_key(self, name):
|
||||
"""
|
||||
Return if a key exists in the name_group table.
|
||||
@@ -985,18 +953,6 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iter_location_handles(self):
|
||||
"""
|
||||
Return an iterator over handles for Locations in the database
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iter_locations(self):
|
||||
"""
|
||||
Return an iterator over objects for Locations in the database
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iter_media_object_handles(self):
|
||||
"""
|
||||
Return an iterator over handles for Media in the database
|
||||
@@ -1081,7 +1037,8 @@ class DbReadBase(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def load(self, name, callback, mode=None, upgrade=False):
|
||||
def load(self, name, callback, mode=None, force_schema_upgrade=False,
|
||||
force_bsddb_upgrade=False):
|
||||
"""
|
||||
Open the specified database.
|
||||
"""
|
||||
@@ -1287,13 +1244,6 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def add_location(self, location, transaction):
|
||||
"""
|
||||
Add a Location to the database, assigning a handle if it has not already
|
||||
been defined.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def add_note(self, obj, transaction, set_gid=True):
|
||||
"""
|
||||
Add a Note to the database, assigning internal IDs if they have
|
||||
@@ -1402,13 +1352,6 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def commit_location(self, location, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified Location to the database, storing the changes as
|
||||
part of the transaction.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def commit_media_object(self, obj, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified MediaObject to the database, storing the changes
|
||||
@@ -1480,7 +1423,7 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def need_upgrade(self):
|
||||
def need_schema_upgrade(self):
|
||||
"""
|
||||
Return True if database needs to be upgraded
|
||||
"""
|
||||
@@ -1526,15 +1469,6 @@ class DbWriteBase(DbReadBase):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def remove_location(self, handle, transaction):
|
||||
"""
|
||||
Remove the Location specified by the database handle from the
|
||||
database, preserving the change in the passed transaction.
|
||||
|
||||
This method must be overridden in the derived class.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def remove_note(self, handle, transaction):
|
||||
"""
|
||||
Remove the Note specified by the database handle from the
|
||||
|
@@ -198,8 +198,8 @@ if __name__ == "__main__":
|
||||
x = db.DBEnv()
|
||||
print("3")
|
||||
x.open('/tmp', db.DB_CREATE | db.DB_PRIVATE |\
|
||||
db.DB_INIT_MPOOL | db.DB_INIT_LOCK |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN | db.DB_THREAD)
|
||||
db.DB_INIT_MPOOL |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN)
|
||||
print("4")
|
||||
d = dbshelve.DBShelf(x)
|
||||
print("5")
|
||||
|
@@ -111,7 +111,11 @@ class BsddbBaseCursor(object):
|
||||
_flags | flags | (db.DB_RMW if self._update else 0),
|
||||
**kwargs)
|
||||
|
||||
return (data[0], loads(data[1])) if data else None
|
||||
try:
|
||||
return (data[0], loads(data[1])) if data else None
|
||||
except UnicodeDecodeError:
|
||||
#we need to assume we opened data in python3 saved in python2
|
||||
return (data[0], loads(data[1], encoding='utf-8')) if data else None
|
||||
|
||||
return get
|
||||
|
||||
|
@@ -45,8 +45,8 @@ __all__ = (
|
||||
) +
|
||||
|
||||
('PERSON_KEY', 'FAMILY_KEY', 'SOURCE_KEY', 'CITATION_KEY',
|
||||
'EVENT_KEY', 'MEDIA_KEY', 'PLACE_KEY', 'LOCATION_KEY',
|
||||
'REPOSITORY_KEY', 'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY'
|
||||
'EVENT_KEY', 'MEDIA_KEY', 'PLACE_KEY', 'REPOSITORY_KEY',
|
||||
'NOTE_KEY', 'REFERENCE_KEY', 'TAG_KEY', 'TEMPLATE_KEY'
|
||||
) +
|
||||
|
||||
('TXNADD', 'TXNUPD', 'TXNDEL')
|
||||
@@ -87,6 +87,6 @@ REFERENCE_KEY = 7
|
||||
NOTE_KEY = 8
|
||||
TAG_KEY = 9
|
||||
CITATION_KEY = 10
|
||||
LOCATION_KEY = 11
|
||||
TEMPLATE_KEY = 11
|
||||
|
||||
TXNADD, TXNUPD, TXNDEL = 0, 1, 2
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
class DbException(Exception):
|
||||
@@ -72,13 +72,23 @@ class DbVersionError(Exception):
|
||||
Error used to report that a file could not be read because it is written
|
||||
in an unsupported version of the file format.
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, tree_vers, min_vers, max_vers):
|
||||
Exception.__init__(self)
|
||||
self.tree_vers = tree_vers
|
||||
self.min_vers = min_vers
|
||||
self.max_vers = max_vers
|
||||
|
||||
def __str__(self):
|
||||
return _("The database version is not supported by this version of "
|
||||
"Gramps.\nPlease upgrade to the corresponding version or use "
|
||||
"XML for porting data between different database versions.")
|
||||
return _('The schema version is not supported by this version of '
|
||||
'Gramps.\n\n'
|
||||
'This Family Tree is schema version %(tree_vers)s, and this '
|
||||
'version of Gramps supports versions %(min_vers)s to '
|
||||
'%(max_vers)s\n\n'
|
||||
'Please upgrade to the corresponding version or use '
|
||||
'XML for porting data between different schema versions.') %\
|
||||
{'tree_vers': self.tree_vers,
|
||||
'min_vers': self.min_vers,
|
||||
'max_vers': self.max_vers}
|
||||
|
||||
class BsddbDowngradeError(Exception):
|
||||
"""
|
||||
@@ -91,19 +101,70 @@ class BsddbDowngradeError(Exception):
|
||||
self.bdb_version = str(bdb_version)
|
||||
|
||||
def __str__(self):
|
||||
return _('Gramps stores its data in a Berkeley Database. '
|
||||
'The family tree you try to load was created with version '
|
||||
'%(env_version)s of the Berkeley DB. However, the Gramps '
|
||||
'version in use right now employs version %(bdb_version)s '
|
||||
'of the Berkeley DB. So you are trying to load data created '
|
||||
'in a newer format into an older program; this is bound to '
|
||||
'fail. The right approach in this case is to use XML export '
|
||||
'and import. So try to open the family tree on that computer '
|
||||
'with that software that created the family tree, export it '
|
||||
'to XML and load that XML into the version of Gramps you '
|
||||
'intend to use.') % {'env_version': self.env_version,
|
||||
return _('The Family Tree you are trying to load is in the Bsddb '
|
||||
'version %(env_version)s format. This version of Gramps uses '
|
||||
'Bsddb version %(bdb_version)s. So you are trying to load '
|
||||
'data created in a newer format into an older program, and '
|
||||
'this is bound to fail.\n\n'
|
||||
'You should start your <b>newer</b> version of Gramps and '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=How_to_make_a_backup">'
|
||||
'make a backup</a> of your Family Tree. You can then import '
|
||||
'this backup into this version of Gramps.') % \
|
||||
{'env_version': self.env_version,
|
||||
'bdb_version': self.bdb_version}
|
||||
|
||||
class BsddbDowngradeRequiredError(Exception):
|
||||
"""
|
||||
Error used to report that the Berkeley database used to create the family
|
||||
tree is of a version that is newer than the current version, but it may be
|
||||
possible to open the tree, because the difference is only a point upgrade
|
||||
(i.e. a difference in the last digit of the version tuple).
|
||||
"""
|
||||
def __init__(self, env_version, bdb_version):
|
||||
Exception.__init__(self)
|
||||
self.env_version = str(env_version)
|
||||
self.bdb_version = str(bdb_version)
|
||||
|
||||
def __str__(self):
|
||||
return _('The Family Tree you are trying to load is in the Bsddb '
|
||||
'version %(env_version)s format. This version of Gramps uses '
|
||||
'Bsddb version %(bdb_version)s. So you are trying to load '
|
||||
'data created in a newer format into an older program. In '
|
||||
'this particular case, the difference is very small, so it '
|
||||
'may work.\n\n'
|
||||
'If you have not already made a backup of your Family Tree, '
|
||||
'then you should start your <b>newer</b> version of Gramps and '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=How_to_make_a_backup">'
|
||||
'make a backup</a> of your Family Tree.') % \
|
||||
{'env_version': self.env_version,
|
||||
'bdb_version': self.bdb_version}
|
||||
|
||||
class BsddbUpgradeRequiredError(Exception):
|
||||
"""
|
||||
Error used to report that the Berkeley database used to create the family
|
||||
tree is of a version that is too new to be supported by the current version.
|
||||
"""
|
||||
def __init__(self, env_version, bsddb_version):
|
||||
Exception.__init__(self)
|
||||
self.env_version = str(env_version)
|
||||
self.bsddb_version = str(bsddb_version)
|
||||
|
||||
def __str__(self):
|
||||
return _('The Family Tree you are trying to load is in the Bsddb '
|
||||
'version %(env_version)s format. This version of Gramps uses '
|
||||
'Bsddb version %(bdb_version)s. Therefore you cannot load '
|
||||
'this Family Tree without upgrading the Bsddb version of the '
|
||||
'Family Tree.\n\n'
|
||||
'Opening the Family Tree with this version of Gramps might '
|
||||
'irretrievably corrupt your Family Tree. You are strongly '
|
||||
'advised to backup your Family Tree.\n\n'
|
||||
'If you have not already made a backup of your Family Tree, '
|
||||
'then you should start your <b>old</b> version of Gramps and '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=How_to_make_a_backup">'
|
||||
'make a backup</a> of your Family Tree.') % \
|
||||
{'env_version': self.env_version,
|
||||
'bdb_version': self.bsddb_version}
|
||||
|
||||
class DbEnvironmentError(Exception):
|
||||
"""
|
||||
Error used to report that the database 'environment' could not be opened.
|
||||
@@ -133,11 +194,83 @@ class DbUpgradeRequiredError(Exception):
|
||||
Error used to report that a database needs to be upgraded before it can be
|
||||
used.
|
||||
"""
|
||||
def __init__(self):
|
||||
def __init__(self, oldschema, newschema):
|
||||
Exception.__init__(self)
|
||||
self.oldschema = oldschema
|
||||
self.newschema = newschema
|
||||
|
||||
def __str__(self):
|
||||
return _("You cannot open this database without upgrading it.\n"
|
||||
"If you upgrade then you won't be able to use previous "
|
||||
"versions of Gramps.\n"
|
||||
"You might want to make a backup copy first.")
|
||||
return _('The Family Tree you are trying to load is in the schema '
|
||||
'version %(oldschema)s format. This version of Gramps uses '
|
||||
'schema version %(newschema)s. Therefore you cannot load this '
|
||||
'Family Tree without upgrading the schema version of the '
|
||||
'Family Tree.\n\n'
|
||||
'If you upgrade then you won\'t be able to use the previous '
|
||||
'version of Gramps, even if you subsequently '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_Manage_Family_Trees#Backing_up_a_Family_Tree">backup</a> '
|
||||
'or <a href="http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_Manage_Family_Trees#Export_into_Gramps_formats">export</a> '
|
||||
'your upgraded Family Tree.\n\n'
|
||||
'Upgrading is a difficult task which could irretrievably '
|
||||
'corrupt your Family Tree if it is interrupted or fails.\n\n'
|
||||
'If you have not already made a backup of your Family Tree, '
|
||||
'then you should start your <b>old</b> version of Gramps and '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=How_to_make_a_backup">make a backup</a> '
|
||||
'of your Family Tree.') % \
|
||||
{'oldschema': self.oldschema,
|
||||
'newschema': self.newschema}
|
||||
|
||||
class PythonDowngradeError(Exception):
|
||||
"""
|
||||
Error used to report that the Python version used to create the family tree
|
||||
(i.e. Python3) is of a version that is newer than the current version
|
||||
(i.e.Python2), so the Family Tree cannot be opened
|
||||
"""
|
||||
def __init__(self, db_python_version, current_python_version):
|
||||
Exception.__init__(self)
|
||||
self.db_python_version = str(db_python_version)
|
||||
self.current_python_version = str(current_python_version)
|
||||
|
||||
def __str__(self):
|
||||
return _('The Family Tree you are trying to load was created with '
|
||||
'Python version %(db_python_version)s. This version of Gramps '
|
||||
'uses Python version %(current_python_version)s. So you are '
|
||||
'trying to load '
|
||||
'data created in a newer format into an older program, and '
|
||||
'this is bound to fail.\n\n'
|
||||
'You should start your <b>newer</b> version of Gramps and '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=How_to_make_a_backup">'
|
||||
'make a backup</a> of your Family Tree. You can then import '
|
||||
'this backup into this version of Gramps.') % \
|
||||
{'db_python_version': self.db_python_version,
|
||||
'current_python_version': self.current_python_version}
|
||||
|
||||
class PythonUpgradeRequiredError(Exception):
|
||||
"""
|
||||
Error used to report that the Python version used to create the family tree
|
||||
(i.e. Python2) is earlier than the current Python version (i.e. Python3), so
|
||||
the Family Tree needs to be upgraded..
|
||||
"""
|
||||
def __init__(self, db_python_version, current_python_version):
|
||||
Exception.__init__(self)
|
||||
self.db_python_version = str(db_python_version)
|
||||
self.current_python_version = str(current_python_version)
|
||||
|
||||
def __str__(self):
|
||||
return _('The Family Tree you are trying to load is in the Python '
|
||||
'version %(db_python_version)s format. This version of Gramps '
|
||||
'uses Python version %(current_python_version)s. Therefore '
|
||||
'you cannot load this Family Tree without upgrading the '
|
||||
'Python version of the Family Tree.\n\n'
|
||||
'If you upgrade then you won\'t be able to use the previous '
|
||||
'version of Gramps, even if you subsequently '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_Manage_Family_Trees#Backing_up_a_Family_Tree">backup</a> '
|
||||
'or <a href="http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_Manage_Family_Trees#Export_into_Gramps_formats">export</a> '
|
||||
'your upgraded Family Tree.\n\n'
|
||||
'Upgrading is a difficult task which could irretrievably '
|
||||
'corrupt your Family Tree if it is interrupted or fails.\n\n'
|
||||
'If you have not already made a backup of your Family Tree, '
|
||||
'then you should start your <b>old</b> version of Gramps and '
|
||||
'<a href="http://www.gramps-project.org/wiki/index.php?title=How_to_make_a_backup">make a backup</a> '
|
||||
'of your Family Tree.') % \
|
||||
{'db_python_version': self.db_python_version,
|
||||
'current_python_version': self.current_python_version}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# Copyright (C) 2000-2007 Donald N. Allingham
|
||||
# Copyright (C) 2010 Nick Hall
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2011-2013 Tim G L Lyons
|
||||
#
|
||||
# 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
|
||||
@@ -49,7 +49,7 @@ if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
else:
|
||||
from bsddb import db
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
import re
|
||||
|
||||
import logging
|
||||
@@ -66,10 +66,10 @@ from ..lib.src import Source
|
||||
from ..lib.citation import Citation
|
||||
from ..lib.event import Event
|
||||
from ..lib.place import Place
|
||||
from ..lib.location import Location
|
||||
from ..lib.repo import Repository
|
||||
from ..lib.note import Note
|
||||
from ..lib.tag import Tag
|
||||
from ..lib.srctemplate import SrcTemplate
|
||||
from ..lib.genderstats import GenderStats
|
||||
from ..lib.researcher import Researcher
|
||||
from ..lib.nameorigintype import NameOriginType
|
||||
@@ -80,7 +80,7 @@ from ..utils.cast import conv_dbstr_to_unicode
|
||||
from . import (BsddbBaseCursor, DbReadBase)
|
||||
from ..utils.id import create_id
|
||||
from ..errors import DbError
|
||||
from ..constfunc import UNITYPE, STRTYPE, cuni
|
||||
from ..constfunc import UNITYPE, STRTYPE, cuni, handle2internal
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
|
||||
LOG = logging.getLogger(DBLOGNAME)
|
||||
@@ -93,8 +93,8 @@ LOG = logging.getLogger(".citation")
|
||||
from .dbconst import *
|
||||
|
||||
_SIGBASE = ('person', 'family', 'source', 'citation',
|
||||
'event', 'media', 'place', 'location', 'repository',
|
||||
'reference', 'note', 'tag')
|
||||
'event', 'media', 'place', 'repository',
|
||||
'reference', 'note', 'tag', 'srctemplate')
|
||||
|
||||
DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
|
||||
db.DBPageNotFoundError, db.DBInvalidArgError)
|
||||
@@ -191,32 +191,6 @@ class DbReadCursor(BsddbBaseCursor):
|
||||
self.cursor = source.db.cursor(txn)
|
||||
self.source = source
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# DbBsddbTreeCursor
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class DbBsddbTreeCursor(BsddbBaseCursor):
|
||||
|
||||
def __init__(self, source, txn=None, **kwargs):
|
||||
BsddbBaseCursor.__init__(self, txn=txn, **kwargs)
|
||||
self.cursor = source.cursor(txn)
|
||||
self.source = source
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Iterator
|
||||
"""
|
||||
to_do = [None]
|
||||
while to_do:
|
||||
data = self.set(str(to_do.pop()))
|
||||
_n = self.next_dup
|
||||
while data:
|
||||
payload = pickle.loads(data[1])
|
||||
yield (payload[0], payload)
|
||||
to_do.append(payload[0])
|
||||
data = _n()
|
||||
|
||||
class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Read class for the GRAMPS databases. Implements methods necessary to read
|
||||
@@ -366,12 +340,13 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"cursor_func": self.get_tag_cursor,
|
||||
"handles_func": self.get_tag_handles,
|
||||
},
|
||||
'Location':
|
||||
'SrcTemplate':
|
||||
{
|
||||
"handle_func": self.get_location_from_handle,
|
||||
"handle_func": self.get_template_from_handle,
|
||||
"gramps_id_func": None,
|
||||
"class_func": Location,
|
||||
"cursor_func": self.get_location_cursor,
|
||||
"class_func": SrcTemplate,
|
||||
"cursor_func": self.get_template_cursor,
|
||||
"handles_func": self.get_template_handles,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -402,6 +377,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
self.individual_event_names = set()
|
||||
self.individual_attributes = set()
|
||||
self.family_attributes = set()
|
||||
self.source_attributes = set()
|
||||
self.child_ref_types = set()
|
||||
self.family_rel_types = set()
|
||||
self.event_role_names = set()
|
||||
@@ -427,7 +403,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
self.nid_trans = {}
|
||||
self.eid_trans = {}
|
||||
self.tag_trans = {}
|
||||
self.loc_trans = {}
|
||||
self.template_trans = {}
|
||||
self.env = None
|
||||
self.person_map = {}
|
||||
self.family_map = {}
|
||||
@@ -438,6 +414,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
self.note_map = {}
|
||||
self.media_map = {}
|
||||
self.event_map = {}
|
||||
self.template_map = {}
|
||||
self.metadata = {}
|
||||
self.name_group = {}
|
||||
self.undo_callback = None
|
||||
@@ -531,8 +508,8 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
def get_tag_cursor(self, *args, **kwargs):
|
||||
return self.get_cursor(self.tag_map, *args, **kwargs)
|
||||
|
||||
def get_location_cursor(self, *args, **kwargs):
|
||||
return DbBsddbTreeCursor(self.parents, self.txn)
|
||||
def get_template_cursor(self, *args, **kwargs):
|
||||
return self.get_cursor(self.template_map, *args, **kwargs)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
@@ -582,7 +559,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
self.emit('repository-rebuild')
|
||||
self.emit('note-rebuild')
|
||||
self.emit('tag-rebuild')
|
||||
self.emit('location-rebuild')
|
||||
self.emit('template-rebuild')
|
||||
|
||||
def __find_next_gramps_id(self, prefix, map_index, trans):
|
||||
"""
|
||||
@@ -798,13 +775,13 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return self.get_from_handle(handle, Tag, self.tag_map)
|
||||
|
||||
def get_location_from_handle(self, handle):
|
||||
def get_template_from_handle(self, handle):
|
||||
"""
|
||||
Find a Location in the database from the passed handle.
|
||||
Find a Tag in the database from the passed handle.
|
||||
|
||||
If no such Location exists, None is returned.
|
||||
If no such Tag exists, None is returned.
|
||||
"""
|
||||
return self.get_from_handle(handle, Location, self.location_map)
|
||||
return self.get_from_handle(handle, SrcTemplate, self.template_map)
|
||||
|
||||
def __get_obj_from_gramps_id(self, val, tbl, class_, prim_tbl):
|
||||
if isinstance(tbl, dict):
|
||||
@@ -1014,13 +991,18 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return self.get_number_of_records(self.tag_map)
|
||||
|
||||
def get_number_of_locations(self):
|
||||
def get_number_of_templates(self):
|
||||
"""
|
||||
Return the number of locations currently in the database.
|
||||
Return the number of tags currently in the database.
|
||||
"""
|
||||
return self.get_number_of_records(self.location_map)
|
||||
return self.get_number_of_records(self.template_map)
|
||||
|
||||
def all_handles(self, table):
|
||||
""" return all the keys of a database table
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
return table.keys(txn=self.txn)
|
||||
|
||||
def get_person_handles(self, sort_handles=False):
|
||||
@@ -1029,6 +1011,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by surnames.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
handle_list = self.all_handles(self.person_map)
|
||||
@@ -1043,6 +1029,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by Place title.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
|
||||
if self.db_is_open:
|
||||
@@ -1057,7 +1047,11 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
Return a list of database handles, one handle for each Source in
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by Source title.
|
||||
If sort_handles is True, the list is sorted by Source title.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
handle_list = self.all_handles(self.source_map)
|
||||
@@ -1071,7 +1065,11 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
Return a list of database handles, one handle for each Citation in
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by Citation Volume/Page.
|
||||
If sort_handles is True, the list is sorted by Citation Volume/Page.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
handle_list = self.all_handles(self.citation_map)
|
||||
@@ -1086,6 +1084,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by title.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
handle_list = self.all_handles(self.media_map)
|
||||
@@ -1098,6 +1100,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Event in the
|
||||
database.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
return self.all_handles(self.event_map)
|
||||
@@ -1107,6 +1113,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Family in
|
||||
the database.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
return self.all_handles(self.family_map)
|
||||
@@ -1116,6 +1126,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Repository in
|
||||
the database.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
return self.all_handles(self.repository_map)
|
||||
@@ -1125,6 +1139,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Note in the
|
||||
database.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
return self.all_handles(self.note_map)
|
||||
@@ -1135,7 +1153,11 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
Return a list of database handles, one handle for each Tag in
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by Tag name.
|
||||
If sort_handles is True, the list is sorted by Tag name.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
handle_list = self.all_handles(self.tag_map)
|
||||
@@ -1144,13 +1166,22 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
return handle_list
|
||||
return []
|
||||
|
||||
def get_location_handles(self):
|
||||
def get_template_handles(self, sort_handles=False):
|
||||
"""
|
||||
Return a list of database handles, one handle for each Location in the
|
||||
database.
|
||||
Return a list of database handles, one handle for each Tag in
|
||||
the database.
|
||||
|
||||
If sort_handles is True, the list is sorted by Tag name.
|
||||
|
||||
CAREFUL: For speed the keys are directly returned, so on python3
|
||||
bytestrings are returned! Use constfunc.py handle2internal
|
||||
on this result!
|
||||
"""
|
||||
if self.db_is_open:
|
||||
return self.all_handles(self.location_map)
|
||||
handle_list = self.all_handles(self.template_map)
|
||||
if sort_handles:
|
||||
handle_list.sort(key=self.__sortbytemplate_key)
|
||||
return handle_list
|
||||
return []
|
||||
|
||||
def _f(curs_):
|
||||
@@ -1160,7 +1191,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
def g(self):
|
||||
with curs_(self) as cursor:
|
||||
for key, data in cursor:
|
||||
yield key
|
||||
yield handle2internal(key)
|
||||
return g
|
||||
|
||||
# Use closure to define iterators for each primary object type
|
||||
@@ -1175,7 +1206,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
iter_repository_handles = _f(get_repository_cursor)
|
||||
iter_note_handles = _f(get_note_cursor)
|
||||
iter_tag_handles = _f(get_tag_cursor)
|
||||
iter_location_handles = _f(get_location_cursor)
|
||||
iter_template_handles = _f(get_template_cursor)
|
||||
del _f
|
||||
|
||||
def _f(curs_, obj_):
|
||||
@@ -1202,7 +1233,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
iter_repositories = _f(get_repository_cursor, Repository)
|
||||
iter_notes = _f(get_note_cursor, Note)
|
||||
iter_tags = _f(get_tag_cursor, Tag)
|
||||
iter_locations = _f(get_location_cursor, Location)
|
||||
iter_templates = _f(get_template_cursor, SrcTemplate)
|
||||
del _f
|
||||
|
||||
def get_gramps_ids(self, obj_key):
|
||||
@@ -1481,6 +1512,12 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
return self.metadata.get(b'default')
|
||||
return None
|
||||
|
||||
def get_GEDCOM_template_handle(self):
|
||||
"""Return the handle of the GEDCOM template of the database."""
|
||||
if self.metadata is not None:
|
||||
return self.metadata.get(b'gedcom_template')
|
||||
return None
|
||||
|
||||
def get_save_path(self):
|
||||
"""Return the save path of the file, or "" if one does not exist."""
|
||||
return self.path
|
||||
@@ -1573,6 +1610,13 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return list(self.note_types)
|
||||
|
||||
def get_source_attribute_types(self):
|
||||
"""
|
||||
Return a list of all Attribute types assocated with Source/Citation
|
||||
instances in the database.
|
||||
"""
|
||||
return list(self.source_attributes)
|
||||
|
||||
def get_source_media_types(self):
|
||||
"""
|
||||
Return a list of all custom source media types assocated with Source
|
||||
@@ -1600,6 +1644,10 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
handle = handle.encode('utf-8')
|
||||
try:
|
||||
return table.get(handle, txn=self.txn)
|
||||
except UnicodeDecodeError:
|
||||
#we need to assume we opened data in python3 saved in python2
|
||||
raw = table.db.get(handle, txn=self.txn)
|
||||
return pickle.loads(raw, encoding='utf-8')
|
||||
except DBERRS as msg:
|
||||
self.__log_error()
|
||||
raise DbError(msg)
|
||||
@@ -1634,8 +1682,8 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
def get_raw_tag_data(self, handle):
|
||||
return self.__get_raw_data(self.tag_map, handle)
|
||||
|
||||
def get_raw_location_data(self, handle):
|
||||
return self.__get_raw_data(self.location_map, handle)
|
||||
def get_raw_template_data(self, handle):
|
||||
return self.__get_raw_data(self.template_map, handle)
|
||||
|
||||
def __has_handle(self, table, handle):
|
||||
"""
|
||||
@@ -1709,11 +1757,11 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
"""
|
||||
return self.__has_handle(self.tag_map, handle)
|
||||
|
||||
def has_location_handle(self, handle):
|
||||
def has_template_handle(self, handle):
|
||||
"""
|
||||
Return True if the handle exists in the current Location database.
|
||||
Return True if the handle exists in the current Tag database.
|
||||
"""
|
||||
return self.__has_handle(self.location_map, handle)
|
||||
return self.__has_handle(self.template_map, handle)
|
||||
|
||||
def __sortbyperson_key(self, handle):
|
||||
if isinstance(handle, UNITYPE):
|
||||
@@ -1794,6 +1842,12 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
tag = self.tag_map[key][1]
|
||||
return glocale.sort_key(tag)
|
||||
|
||||
def __sortbytemplate_key(self, key):
|
||||
if isinstance(key, UNITYPE):
|
||||
key = key.encode('utf-8')
|
||||
template = self.template_map[key][1]
|
||||
return glocale.sort_key(template)
|
||||
|
||||
def set_mediapath(self, path):
|
||||
"""Set the default media path for database, path should be utf-8."""
|
||||
if (self.metadata is not None) and (not self.readonly):
|
||||
@@ -1805,6 +1859,11 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
return self.metadata.get(b'mediapath', None)
|
||||
return None
|
||||
|
||||
def set_GEDCOM_template_handle(self, handle):
|
||||
"""Set the default GEDCOM template handle for database"""
|
||||
if (self.metadata is not None) and (not self.readonly):
|
||||
self.metadata[b'gedcom_template'] = handle
|
||||
|
||||
def find_backlink_handles(self, handle, include_classes=None):
|
||||
"""
|
||||
Find all objects that hold a reference to the object handle.
|
||||
@@ -1871,9 +1930,9 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
'cursor_func': self.get_tag_cursor,
|
||||
'class_func': Tag,
|
||||
},
|
||||
'Location': {
|
||||
'cursor_func': self.get_location_cursor,
|
||||
'class_func': Location,
|
||||
'Template': {
|
||||
'cursor_func': self.get_template_cursor,
|
||||
'class_func': SrcTemplate,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1928,7 +1987,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
filepath = os.path.join(self.path, "name.txt")
|
||||
try:
|
||||
name_file = open(filepath, "r")
|
||||
name = name_file.read()
|
||||
name = name_file.readline().strip()
|
||||
name_file.close()
|
||||
except (OSError, IOError) as msg:
|
||||
self.__log_error()
|
||||
|
@@ -120,6 +120,7 @@ class DbTest(object):
|
||||
"get_repository_types",
|
||||
"get_researcher",
|
||||
"get_save_path",
|
||||
"get_source_attribute_types",
|
||||
"get_source_bookmarks",
|
||||
"get_source_cursor",
|
||||
"get_source_from_gramps_id",
|
||||
@@ -213,7 +214,7 @@ class DbTest(object):
|
||||
"commit_source",
|
||||
"commit_tag",
|
||||
"delete_primary_from_reference_map",
|
||||
"need_upgrade",
|
||||
"need_schema_upgrade",
|
||||
"rebuild_secondary",
|
||||
"reindex_reference_map",
|
||||
"remove_event",
|
||||
|
@@ -47,7 +47,7 @@ if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
else:
|
||||
from bsddb import db
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -67,8 +67,8 @@ from ..errors import DbError
|
||||
DBERRS = (db.DBRunRecoveryError, db.DBAccessError,
|
||||
db.DBPageNotFoundError, db.DBInvalidArgError)
|
||||
|
||||
_SIGBASE = ('person', 'family', 'source', 'event', 'media', 'place',
|
||||
'location', 'repository', 'reference', 'note', 'tag', 'citation')
|
||||
_SIGBASE = ('person', 'family', 'source', 'event', 'media',
|
||||
'place', 'repository', 'reference', 'note', 'tag', 'citation')
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -107,7 +107,6 @@ class DbUndo(object):
|
||||
self.db.note_map,
|
||||
self.db.tag_map,
|
||||
self.db.citation_map,
|
||||
self.db.location_map,
|
||||
)
|
||||
|
||||
def clear(self):
|
||||
@@ -483,7 +482,6 @@ def testundo():
|
||||
self.place_map = {}
|
||||
self.note_map = {}
|
||||
self.tag_map = {}
|
||||
self.location_map = {}
|
||||
self.repository_map = {}
|
||||
self.reference_map = {}
|
||||
|
||||
|
@@ -31,7 +31,7 @@ import logging
|
||||
LOG = logging.getLogger(".citation")
|
||||
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
from ..constfunc import cuni
|
||||
|
||||
"""
|
||||
@@ -46,78 +46,18 @@ from . import BSDDBTxn
|
||||
from ..constfunc import UNITYPE
|
||||
from ..lib.nameorigintype import NameOriginType
|
||||
from .write import _mkname, SURNAMES
|
||||
from .dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY, MEDIA_KEY, PLACE_KEY,
|
||||
LOCATION_KEY, REPOSITORY_KEY)
|
||||
from .dbconst import (PERSON_KEY, FAMILY_KEY, EVENT_KEY,
|
||||
MEDIA_KEY, PLACE_KEY, REPOSITORY_KEY)
|
||||
from gramps.gui.dialog import (InfoDialog)
|
||||
|
||||
def gramps_upgrade_18(self):
|
||||
self.set_total(len(self.place_map))
|
||||
self.children = {None: []}
|
||||
for handle in self.place_map.keys():
|
||||
place = self.place_map[handle]
|
||||
new_place = list(place)
|
||||
lat_long = (new_place[4], new_place[3])
|
||||
if new_place[5] is not None:
|
||||
new_place[5] = process_location(self, new_place[5], lat_long)
|
||||
else:
|
||||
new_place[5] = process_location(self, None, lat_long)
|
||||
add_reference(self, handle, new_place[5])
|
||||
alt_locs = []
|
||||
for alt_loc in new_place[6]:
|
||||
ref_handle = process_location(self, alt_loc, lat_long)
|
||||
add_reference(self, handle, ref_handle)
|
||||
alt_locs.append(ref_handle)
|
||||
new_place[6] = alt_locs
|
||||
new_place = tuple(new_place[:3] + new_place[5:])
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
txn.put(str(handle), new_place)
|
||||
self.update()
|
||||
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'version', 18)
|
||||
|
||||
def add_reference(self, pri_handle, ref_handle):
|
||||
key = (PLACE_KEY, pri_handle)
|
||||
data = ((PLACE_KEY, pri_handle), (LOCATION_KEY, ref_handle))
|
||||
with BSDDBTxn(self.env, self.reference_map) as txn:
|
||||
txn.put(str(key), data)
|
||||
|
||||
def process_location(self, loc, lat_long):
|
||||
if loc is None:
|
||||
location = ['Unknown']
|
||||
else:
|
||||
# (street, locality, parish, city, county, state, country)
|
||||
# We need to think about where to put ZIP code and Phone number
|
||||
location = loc[0][:2] + (loc[1],) + loc[0][2:6]
|
||||
location = list(location)
|
||||
location.reverse()
|
||||
items = [x for x in enumerate(location) if x[1]]
|
||||
parent = None
|
||||
for item in items:
|
||||
parent = match_location(self, parent, item, lat_long)
|
||||
return parent
|
||||
|
||||
def match_location(self, parent, item, lat_long):
|
||||
for handle in self.children[parent]:
|
||||
if self.location_map[handle][2] == item[1]:
|
||||
return handle
|
||||
handle = self.create_id()
|
||||
self.children[handle] = []
|
||||
self.children[parent].append(handle)
|
||||
new_location = (handle,
|
||||
str(parent),
|
||||
item[1], # Name
|
||||
item[0]+1, # Type
|
||||
lat_long[0],
|
||||
lat_long[1],
|
||||
int(time.time()))
|
||||
with BSDDBTxn(self.env, self.location_map) as txn:
|
||||
txn.put(str(handle), new_location)
|
||||
return handle
|
||||
|
||||
def gramps_upgrade_17(self):
|
||||
"""Upgrade database from version 16 to 17. This upgrade adds tags to
|
||||
event, place, repository, source and citation objects.
|
||||
"""Upgrade database from version 16 to 17.
|
||||
1. This upgrade adds tags to event, place, repository, source and
|
||||
citation objects.
|
||||
2. Data of Source becomes SourceAttributes Secondary Object
|
||||
3. Citation page is deprecated and becomes Citation name
|
||||
Source title, author and pubinfo are deprecated. Now there is
|
||||
Source template and name instead.
|
||||
"""
|
||||
length = (len(self.event_map) + len(self.place_map) +
|
||||
len(self.repository_map) + len(self.source_map) +
|
||||
@@ -199,10 +139,91 @@ def gramps_upgrade_17(self):
|
||||
txn.put(handle, new_citation)
|
||||
self.update()
|
||||
|
||||
# -------------------------------------------------------
|
||||
# 1. Upgrade Source and Citation datamap to SrcAttributeBase
|
||||
# 2. Citation page is deprecated and becomes Citation name
|
||||
# Source title, author and pubinfo are deprecated. Now there is
|
||||
# Source template and name instead.
|
||||
# -------------------------------------------------------
|
||||
from ..lib.srcattrtype import SrcAttributeType
|
||||
private = False
|
||||
|
||||
first = True
|
||||
for handle in self.source_map.keys():
|
||||
if first:
|
||||
from gramps.plugins.srctemplates.gedcomtemplate import build_GEDCOM_template
|
||||
template = build_GEDCOM_template()
|
||||
if isinstance(template.handle, UNITYPE):
|
||||
template.handle = template.handle.encode('utf-8')
|
||||
teml_handle = template.handle
|
||||
from gramps.gen.lib.srctemplate import SrcTemplate
|
||||
template = SrcTemplate.serialize(template)
|
||||
with BSDDBTxn(self.env, self.template_map) as txn:
|
||||
txn.put(teml_handle, template)
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'gedcom_template', teml_handle)
|
||||
first = False
|
||||
|
||||
source = self.source_map[handle]
|
||||
(handle, gramps_id, title, author, pubinfo,
|
||||
notelist, medialist, abbrev, change, datamap, reporef_list,
|
||||
taglist, private) = source
|
||||
srcattributelist = upgrade_datamap_17(datamap)
|
||||
if title:
|
||||
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.TITLE)
|
||||
srcattributelist.append((private, the_type, title))
|
||||
if author:
|
||||
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.AUTHOR)
|
||||
srcattributelist.append((private, the_type, author))
|
||||
if pubinfo:
|
||||
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.PUB_INFO)
|
||||
srcattributelist.append((private, the_type, pubinfo))
|
||||
|
||||
name = title
|
||||
new_source = (handle, gramps_id, name, teml_handle,
|
||||
notelist, medialist, abbrev, change, srcattributelist, reporef_list,
|
||||
taglist, private)
|
||||
with BSDDBTxn(self.env, self.source_map) as txn:
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_source)
|
||||
self.update()
|
||||
|
||||
for handle in self.citation_map.keys():
|
||||
citation = self.citation_map[handle]
|
||||
(handle, gramps_id, datelist, page, confidence, source_handle,
|
||||
notelist, medialist, datamap, change, taglist, private) = citation
|
||||
srcattributelist = upgrade_datamap_17(datamap)
|
||||
if page:
|
||||
the_type = (SrcAttributeType.CUSTOM, SrcAttributeType.PAGE)
|
||||
srcattributelist.append((private, the_type, page))
|
||||
|
||||
name = page
|
||||
new_citation = (handle, gramps_id, datelist, name, confidence, source_handle,
|
||||
notelist, medialist, srcattributelist, change, taglist, private)
|
||||
with BSDDBTxn(self.env, self.citation_map) as txn:
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_citation)
|
||||
self.update()
|
||||
|
||||
# Bump up database version. Separate transaction to save metadata.
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'version', 17)
|
||||
|
||||
def upgrade_datamap_17(datamap):
|
||||
"""
|
||||
In version 16 key value pairs are stored in source and citation. These become
|
||||
SrcAttribute
|
||||
"""
|
||||
new_srcattr_list = []
|
||||
private = False
|
||||
from ..lib.srcattrtype import SrcAttributeType
|
||||
for (key, value) in datamap.iteritems():
|
||||
the_type = SrcAttributeType(key).serialize()
|
||||
new_srcattr_list.append((private, the_type, value))
|
||||
return new_srcattr_list
|
||||
|
||||
def gramps_upgrade_16(self):
|
||||
"""Upgrade database from version 15 to 16. This upgrade converts all
|
||||
SourceRef child objects to Citation Primary objects.
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# Copyright (C) 2000-2008 Donald N. Allingham
|
||||
# Copyright (C) 2010 Nick Hall
|
||||
# Copyright (C) 2011 Tim G L Lyons
|
||||
# Copyright (C) 2011-2013 Tim G L Lyons
|
||||
#
|
||||
# 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
|
||||
@@ -43,7 +43,7 @@ import time
|
||||
import bisect
|
||||
from functools import wraps
|
||||
import logging
|
||||
from sys import maxsize
|
||||
from sys import maxsize, getfilesystemencoding, version_info
|
||||
|
||||
from ..config import config
|
||||
if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3:
|
||||
@@ -62,18 +62,19 @@ from ..lib.src import Source
|
||||
from ..lib.citation import Citation
|
||||
from ..lib.event import Event
|
||||
from ..lib.place import Place
|
||||
from ..lib.location import Location
|
||||
from ..lib.repo import Repository
|
||||
from ..lib.mediaobj import MediaObject
|
||||
from ..lib.note import Note
|
||||
from ..lib.tag import Tag
|
||||
from ..lib.srctemplate import SrcTemplate
|
||||
from ..lib.genderstats import GenderStats
|
||||
from ..lib.researcher import Researcher
|
||||
|
||||
from . import (DbBsddbRead, DbWriteBase, BSDDBTxn,
|
||||
DbTxn, BsddbBaseCursor, BsddbDowngradeError, DbVersionError,
|
||||
DbEnvironmentError, DbUpgradeRequiredError, find_surname,
|
||||
find_byte_surname, find_surname_name, DbUndoBSDDB as DbUndo)
|
||||
find_byte_surname, find_surname_name, DbUndoBSDDB as DbUndo,
|
||||
exceptions)
|
||||
from .dbconst import *
|
||||
from ..utils.callback import Callback
|
||||
from ..utils.cast import conv_dbstr_to_unicode
|
||||
@@ -81,12 +82,12 @@ from ..updatecallback import UpdateCallback
|
||||
from ..errors import DbError
|
||||
from ..constfunc import win, conv_to_unicode, cuni, UNITYPE, handle2internal
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
_LOG = logging.getLogger(DBLOGNAME)
|
||||
LOG = logging.getLogger(".citation")
|
||||
_MINVERSION = 9
|
||||
_DBVERSION = 18
|
||||
_DBVERSION = 17
|
||||
|
||||
IDTRANS = "person_id"
|
||||
FIDTRANS = "family_id"
|
||||
@@ -98,8 +99,7 @@ NIDTRANS = "note_id"
|
||||
SIDTRANS = "source_id"
|
||||
CIDTRANS = "citation_id"
|
||||
TAGTRANS = "tag_name"
|
||||
LPARENTS = "location_parent"
|
||||
LNAMES = "location_name"
|
||||
TEMPLATETRANS = "template_name"
|
||||
SURNAMES = "surnames"
|
||||
NAME_GROUP = "name_group"
|
||||
META = "meta_data"
|
||||
@@ -114,7 +114,7 @@ PERSON_TBL = "person"
|
||||
REPO_TBL = "repo"
|
||||
NOTE_TBL = "note"
|
||||
TAG_TBL = "tag"
|
||||
LOCATION_TBL = "location"
|
||||
TEMPLATE_TBL = "template"
|
||||
|
||||
REF_MAP = "reference_map"
|
||||
REF_PRI = "primary_map"
|
||||
@@ -139,7 +139,8 @@ CLASS_TO_KEY_MAP = {Person.__name__: PERSON_KEY,
|
||||
Repository.__name__:REPOSITORY_KEY,
|
||||
Note.__name__: NOTE_KEY,
|
||||
Tag.__name__: TAG_KEY,
|
||||
Location.__name__: LOCATION_KEY}
|
||||
SrcTemplate.__name__: TEMPLATE_KEY,
|
||||
}
|
||||
|
||||
KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__,
|
||||
FAMILY_KEY: Family.__name__,
|
||||
@@ -151,7 +152,8 @@ KEY_TO_CLASS_MAP = {PERSON_KEY: Person.__name__,
|
||||
REPOSITORY_KEY: Repository.__name__,
|
||||
NOTE_KEY: Note.__name__,
|
||||
TAG_KEY: Tag.__name__,
|
||||
LOCATION_KEY: Location.__name__}
|
||||
TEMPLATE_KEY: SrcTemplate.__name__,
|
||||
}
|
||||
|
||||
KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
|
||||
FAMILY_KEY: 'family',
|
||||
@@ -164,7 +166,8 @@ KEY_TO_NAME_MAP = {PERSON_KEY: 'person',
|
||||
#REFERENCE_KEY: 'reference',
|
||||
NOTE_KEY: 'note',
|
||||
TAG_KEY: 'tag',
|
||||
LOCATION_KEY: 'location'}
|
||||
TEMPLATE_KEY: 'template',
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Helper functions
|
||||
@@ -180,20 +183,6 @@ def find_idmap(key, data):
|
||||
val = val.encode('utf-8')
|
||||
return val
|
||||
|
||||
def find_parent(key, data):
|
||||
return str(data[1])
|
||||
val = data[1]
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
return val
|
||||
|
||||
def find_name(key, data):
|
||||
return str(data[2]).upper()
|
||||
val = data[2].upper()
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
return val
|
||||
|
||||
# Secondary database key lookups for reference_map table
|
||||
# reference_map data values are of the form:
|
||||
# ((primary_object_class_name, primary_object_handle),
|
||||
@@ -256,8 +245,9 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# 1. Signals for primary objects
|
||||
__signals__ = dict((obj+'-'+op, signal)
|
||||
for obj in
|
||||
['person', 'family', 'event', 'place', 'location',
|
||||
'source', 'citation', 'media', 'note', 'repository', 'tag']
|
||||
['person', 'family', 'event', 'place',
|
||||
'source', 'citation', 'media', 'note', 'repository', 'tag',
|
||||
'template']
|
||||
for op, signal in zip(
|
||||
['add', 'update', 'delete', 'rebuild'],
|
||||
[(list,), (list,), (list,), None]
|
||||
@@ -290,6 +280,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.has_changed = False
|
||||
self.brief_name = None
|
||||
self.update_env_version = False
|
||||
self.update_python_version = False
|
||||
# Whether SrcTemplates need to be loaded. They need to be loaded on
|
||||
# creating a new database, and on upgrade from schema version 16 to 17.
|
||||
self.load_templates = False
|
||||
|
||||
def catch_db_error(func):
|
||||
"""
|
||||
@@ -384,20 +378,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
return DbBsddbAssocCursor(self.reference_map_referenced_map,
|
||||
self.txn)
|
||||
|
||||
@catch_db_error
|
||||
def get_location_parent_cursor(self):
|
||||
"""
|
||||
Returns a reference to a cursor over the location parents
|
||||
"""
|
||||
return DbBsddbAssocCursor(self.parents, self.txn)
|
||||
|
||||
@catch_db_error
|
||||
def get_location_name_cursor(self):
|
||||
"""
|
||||
Returns a reference to a cursor over the location names
|
||||
"""
|
||||
return DbBsddbAssocCursor(self.names, self.txn)
|
||||
|
||||
# These are overriding the DbBsddbRead's methods of saving metadata
|
||||
# because we now have txn-capable metadata table
|
||||
|
||||
@@ -425,6 +405,17 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
txn.put(b'default', None)
|
||||
return None
|
||||
|
||||
@catch_db_error
|
||||
def set_GEDCOM_template_handle(self, handle):
|
||||
"""Set the handle of the GEDCOM template to the passed instance."""
|
||||
#we store a byte string!
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
if not self.readonly:
|
||||
# Start transaction
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'gedcom_template', handle)
|
||||
|
||||
def set_mediapath(self, path):
|
||||
"""Set the default media path for database, path should be utf-8."""
|
||||
if self.metadata and not self.readonly:
|
||||
@@ -432,37 +423,146 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'mediapath', path)
|
||||
|
||||
def __check_bdb_version(self, name):
|
||||
def __make_zip_backup(self, dirname):
|
||||
import zipfile
|
||||
title = self.get_dbname()
|
||||
|
||||
if not os.access(dirname, os.W_OK):
|
||||
_LOG.warning("Can't write technical DB backup for %s" % title)
|
||||
return
|
||||
(grampsdb_path, db_code) = os.path.split(dirname)
|
||||
dotgramps_path = os.path.dirname(grampsdb_path)
|
||||
zipname = title + time.strftime("_%Y-%m-%d_%H-%M-%S") + ".zip"
|
||||
if sys.version_info[0] < 3:
|
||||
zipname = zipname.encode(glocale.getfilesystemencoding())
|
||||
zippath = os.path.join(dotgramps_path, zipname)
|
||||
myzip = zipfile.ZipFile(zippath, 'w')
|
||||
for filename in os.listdir(dirname):
|
||||
pathname = os.path.join(dirname, filename)
|
||||
myzip.write(pathname, os.path.join(db_code, filename))
|
||||
myzip.close()
|
||||
_LOG.warning("If upgrade and loading the Family Tree works, you can "
|
||||
"delete the zip file at %s" %
|
||||
zippath)
|
||||
|
||||
def __check_bdb_version(self, name, force_bsddb_upgrade=False,
|
||||
force_bsddb_downgrade=False):
|
||||
"""Older version of Berkeley DB can't read data created by a newer
|
||||
version."""
|
||||
bdb_version = db.version()
|
||||
env_version = (0, 0, 0)
|
||||
versionpath = os.path.join(self.path, BDBVERSFN)
|
||||
try:
|
||||
# Compare the current version of the database (bsddb_version) with the
|
||||
# version of the database code (env_version). If it is a downgrade,
|
||||
# raise an exception because we can't do anything. If they are the same,
|
||||
# return. If it is an upgrade, raise an exception unless the user has
|
||||
# already told us we can upgrade.
|
||||
if os.path.isfile(versionpath):
|
||||
with open(versionpath, "r") as version_file:
|
||||
env_version = version_file.read().strip()
|
||||
env_version = tuple(map(int, env_version[1:-1].split(', ')))
|
||||
except:
|
||||
# Just assume that the Berkeley DB version is OK.
|
||||
pass
|
||||
if not env_version:
|
||||
#empty file, assume it is ok to open
|
||||
env_version = (0, 0, 0)
|
||||
if (env_version[0] > bdb_version[0]) or \
|
||||
bsddb_version = version_file.read().strip()
|
||||
env_version = tuple(map(int, bsddb_version[1:-1].split(', ')))
|
||||
else:
|
||||
# bsddb version is unknown
|
||||
bsddb_version = "Unknown"
|
||||
env_version = "Unknown"
|
||||
# _LOG.debug("db version %s, program version %s" % (bsddb_version, bdb_version))
|
||||
|
||||
if env_version == "Unknown" or \
|
||||
(env_version[0] < bdb_version[0]) or \
|
||||
(env_version[0] == bdb_version[0] and
|
||||
env_version[1] < bdb_version[1]) or \
|
||||
(env_version[0] == bdb_version[0] and
|
||||
env_version[1] == bdb_version[1] and
|
||||
env_version[2] < bdb_version[2]):
|
||||
# an upgrade is needed
|
||||
if not force_bsddb_upgrade:
|
||||
_LOG.debug("Bsddb upgrade required from %s to %s" %
|
||||
(bsddb_version, str(bdb_version)))
|
||||
clear_lock_file(name)
|
||||
raise exceptions.BsddbUpgradeRequiredError(bsddb_version,
|
||||
str(bdb_version))
|
||||
if not self.readonly:
|
||||
_LOG.warning("Bsddb upgrade requested from %s to %s" %
|
||||
(bsddb_version, str(bdb_version)))
|
||||
self.update_env_version = True
|
||||
# Make a backup of the database files anyway
|
||||
self.__make_zip_backup(name)
|
||||
elif (env_version[0] > bdb_version[0]) or \
|
||||
(env_version[0] == bdb_version[0] and
|
||||
env_version[1] > bdb_version[1]):
|
||||
clear_lock_file(name)
|
||||
raise BsddbDowngradeError(env_version, bdb_version)
|
||||
elif env_version != bdb_version and not self.readonly:
|
||||
self.update_env_version = True
|
||||
elif (env_version[0] == bdb_version[0] and
|
||||
env_version[1] == bdb_version[1] and
|
||||
env_version[2] > bdb_version[2]):
|
||||
# A down-grade may be possible
|
||||
if not force_bsddb_downgrade:
|
||||
_LOG.debug("Bsddb downgrade required from %s to %s" %
|
||||
(bsddb_version, str(bdb_version)))
|
||||
clear_lock_file(name)
|
||||
raise exceptions.BsddbDowngradeRequiredError(bsddb_version,
|
||||
str(bdb_version))
|
||||
# Try to do a down-grade
|
||||
if not self.readonly:
|
||||
_LOG.warning("Bsddb downgrade requested from %s to %s" %
|
||||
(bsddb_version, str(bdb_version)))
|
||||
self.update_env_version = True
|
||||
# Make a backup of the database files anyway
|
||||
self.__make_zip_backup(name)
|
||||
elif env_version == bdb_version:
|
||||
# Bsddb version is OK
|
||||
pass
|
||||
else:
|
||||
# This can't happen
|
||||
raise "Comparison between Bsddb version failed"
|
||||
|
||||
def __check_python_version(self, name, force_python_upgrade=False):
|
||||
"""
|
||||
The 'pickle' format (may) change with each Python version, see
|
||||
http://docs.python.org/3.2/library/pickle.html#pickle. Code commits
|
||||
21777 and 21778 ensure that when going from python2 to python3, the old
|
||||
format can be read. However, once the data has been written in the
|
||||
python3 format, it will not be possible to go back to pyton2. This check
|
||||
test whether we are changing python versions. If going from 2 to 3 it
|
||||
warns the user, and allows it if he confirms. When going from 3 to 3, an
|
||||
error is raised. Because code for python2 did not write the Python
|
||||
version file, if the file is absent, python2 is assumed.
|
||||
"""
|
||||
current_python_version = version_info[0]
|
||||
versionpath = os.path.join(self.path, "pythonversion.txt")
|
||||
if os.path.isfile(versionpath):
|
||||
with open(versionpath, "r") as version_file:
|
||||
db_python_version = int(version_file.read().strip())
|
||||
else:
|
||||
db_python_version = 2
|
||||
|
||||
if db_python_version == 3 and current_python_version == 2:
|
||||
clear_lock_file(name)
|
||||
raise exceptions.PythonDowngradeError(db_python_version,
|
||||
current_python_version)
|
||||
elif db_python_version == 2 and current_python_version > 2:
|
||||
if not force_python_upgrade:
|
||||
_LOG.debug("Python upgrade required from %s to %s" %
|
||||
(db_python_version, current_python_version))
|
||||
clear_lock_file(name)
|
||||
raise exceptions.PythonUpgradeRequiredError(db_python_version,
|
||||
current_python_version)
|
||||
# Try to do an upgrade
|
||||
if not self.readonly:
|
||||
_LOG.warning("Python upgrade requested from %s to %s" %
|
||||
(db_python_version, current_python_version))
|
||||
self.update_python_version = True
|
||||
# Make a backup of the database files anyway
|
||||
self.__make_zip_backup(name)
|
||||
elif db_python_version == 2 and current_python_version == 2:
|
||||
pass
|
||||
|
||||
@catch_db_error
|
||||
def version_supported(self):
|
||||
dbversion = self.metadata.get(b'version', default=0)
|
||||
return ((dbversion <= _DBVERSION) and (dbversion >= _MINVERSION))
|
||||
|
||||
@catch_db_error
|
||||
def need_upgrade(self):
|
||||
def need_schema_upgrade(self):
|
||||
dbversion = self.metadata.get(b'version', default=0)
|
||||
return not self.readonly and dbversion < _DBVERSION
|
||||
|
||||
@@ -479,7 +579,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# See if we lack write access to any files in the directory
|
||||
for base in [FAMILY_TBL, PLACES_TBL, SOURCES_TBL, CITATIONS_TBL,
|
||||
MEDIA_TBL, EVENTS_TBL, PERSON_TBL, REPO_TBL,
|
||||
NOTE_TBL, TAG_TBL, LOCATION_TBL, REF_MAP, META]:
|
||||
NOTE_TBL, TEMPLATE_TBL, REF_MAP, META]:
|
||||
path = os.path.join(name, base + DBEXT)
|
||||
if os.path.isfile(path) and not os.access(path, os.W_OK):
|
||||
return True
|
||||
@@ -488,7 +588,9 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
return False
|
||||
|
||||
@catch_db_error
|
||||
def load(self, name, callback, mode=DBMODE_W, upgrade=False):
|
||||
def load(self, name, callback, mode=DBMODE_W, force_schema_upgrade=False,
|
||||
force_bsddb_upgrade=False, force_bsddb_downgrade=False,
|
||||
force_python_upgrade=False):
|
||||
|
||||
if self.__check_readonly(name):
|
||||
mode = DBMODE_R
|
||||
@@ -508,7 +610,14 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.path = self.full_name
|
||||
self.brief_name = os.path.basename(name)
|
||||
|
||||
self.__check_bdb_version(name)
|
||||
# If we re-enter load with force_python_upgrade True, then we have
|
||||
# already checked the bsddb version, and then checked python version,
|
||||
# and are agreeing on the upgrade
|
||||
if not force_python_upgrade:
|
||||
self.__check_bdb_version(name, force_bsddb_upgrade,
|
||||
force_bsddb_downgrade)
|
||||
|
||||
self.__check_python_version(name, force_python_upgrade)
|
||||
|
||||
# Set up database environment
|
||||
self.env = db.DBEnv()
|
||||
@@ -530,8 +639,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
# The DB_PRIVATE flag must go if we ever move to multi-user setup
|
||||
env_flags = db.DB_CREATE | db.DB_PRIVATE |\
|
||||
db.DB_INIT_MPOOL | db.DB_INIT_LOCK |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN | db.DB_THREAD
|
||||
db.DB_INIT_MPOOL |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN
|
||||
|
||||
# As opposed to before, we always try recovery on databases
|
||||
env_flags |= db.DB_RECOVER
|
||||
@@ -560,11 +669,13 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# If we cannot work with this DB version,
|
||||
# it makes no sense to go further
|
||||
if not self.version_supported():
|
||||
tree_vers = self.metadata.get(b'version', default=0)
|
||||
self.__close_early()
|
||||
raise DbVersionError()
|
||||
|
||||
raise DbVersionError(tree_vers, _MINVERSION, _DBVERSION)
|
||||
|
||||
self.__load_metadata()
|
||||
gstats = self.metadata.get(b'gender_stats', default=None)
|
||||
self.load_templates = False
|
||||
|
||||
# Ensure version info in metadata
|
||||
if not self.readonly:
|
||||
@@ -574,6 +685,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
# New database. Set up the current version.
|
||||
#self.metadata.put(b'version', _DBVERSION, txn=the_txn)
|
||||
txn.put(b'version', _DBVERSION)
|
||||
self.load_templates = True
|
||||
elif b'version' not in self.metadata:
|
||||
# Not new database, but the version is missing.
|
||||
# Use 0, but it is likely to fail anyway.
|
||||
@@ -593,7 +705,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
("repository_map", REPO_TBL, db.DB_HASH),
|
||||
("note_map", NOTE_TBL, db.DB_HASH),
|
||||
("tag_map", TAG_TBL, db.DB_HASH),
|
||||
("location_map", LOCATION_TBL, db.DB_HASH),
|
||||
("template_map", TEMPLATE_TBL, db.DB_HASH),
|
||||
("reference_map", REF_MAP, db.DB_BTREE),
|
||||
]
|
||||
|
||||
@@ -609,17 +721,44 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.name_group = self.__open_db(self.full_name, NAME_GROUP,
|
||||
db.DB_HASH, db.DB_DUP)
|
||||
|
||||
# We have now successfully opened the database, so if the BSDDB version
|
||||
# has changed, we update the DBSDB version file.
|
||||
|
||||
if self.update_env_version:
|
||||
versionpath = os.path.join(name, BDBVERSFN)
|
||||
with open(versionpath, "w") as version_file:
|
||||
version = str(db.version())
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(version, UNITYPE):
|
||||
version = version.encode('utf-8')
|
||||
version_file.write(version)
|
||||
_LOG.debug("Updated BDBVERSFN file to %s" % str(db.version()))
|
||||
|
||||
if self.update_python_version:
|
||||
versionpath = os.path.join(name, "pythonversion.txt")
|
||||
version = str(version_info[0])
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(version, UNITYPE):
|
||||
version = version.encode('utf-8')
|
||||
_LOG.debug("Updated python version file to %s" % version)
|
||||
with open(versionpath, "w") as version_file:
|
||||
version_file.write(version)
|
||||
|
||||
# Here we take care of any changes in the tables related to new code.
|
||||
# If secondary indices change, then they should removed
|
||||
# or rebuilt by upgrade as well. In any case, the
|
||||
# self.secondary_connected flag should be set accordingly.
|
||||
if self.need_upgrade():
|
||||
if upgrade == True:
|
||||
if self.need_schema_upgrade():
|
||||
oldschema = self.metadata.get(b'version', default=0)
|
||||
newschema = _DBVERSION
|
||||
_LOG.debug("Schema upgrade required from %s to %s" %
|
||||
(oldschema, newschema))
|
||||
if force_schema_upgrade == True:
|
||||
self.gramps_upgrade(callback)
|
||||
else:
|
||||
self.__close_early()
|
||||
clear_lock_file(name)
|
||||
raise DbUpgradeRequiredError()
|
||||
raise DbUpgradeRequiredError(oldschema, newschema)
|
||||
|
||||
if callback:
|
||||
callback(50)
|
||||
@@ -635,6 +774,12 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.__open_undodb()
|
||||
self.db_is_open = True
|
||||
|
||||
if self.load_templates:
|
||||
# FIXME gstat is used as a proxy to say whether the database is new
|
||||
# or not, This is not a very clean approach
|
||||
from gramps.plugins.srctemplates.importcsv import load_srctemplates_data
|
||||
load_srctemplates_data(self)
|
||||
|
||||
if callback:
|
||||
callback(87)
|
||||
|
||||
@@ -684,7 +829,13 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
pass
|
||||
|
||||
# bookmarks
|
||||
meta = lambda meta: self.metadata.get(meta, default=[])
|
||||
def meta(key):
|
||||
try:
|
||||
return self.metadata.get(key, default=[])
|
||||
except UnicodeDecodeError:
|
||||
#we need to assume we opened data in python3 saved in python2
|
||||
raw = self.metadata.db.get(key, default=[])
|
||||
return pickle.loads(raw, encoding='utf-8') if raw else raw
|
||||
|
||||
self.bookmarks.set(meta(b'bookmarks'))
|
||||
self.family_bookmarks.set(meta(b'family_bookmarks'))
|
||||
@@ -701,6 +852,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.individual_event_names = set(meta(b'pevent_names'))
|
||||
self.family_attributes = set(meta(b'fattr_names'))
|
||||
self.individual_attributes = set(meta(b'pattr_names'))
|
||||
self.source_attributes = set(meta(b'sattr_names'))
|
||||
self.marker_names = set(meta(b'marker_names'))
|
||||
self.child_ref_types = set(meta(b'child_refs'))
|
||||
self.family_rel_types = set(meta(b'family_rels'))
|
||||
@@ -742,8 +894,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
("rid_trans", RIDTRANS, db.DB_HASH, 0),
|
||||
("nid_trans", NIDTRANS, db.DB_HASH, 0),
|
||||
("tag_trans", TAGTRANS, db.DB_HASH, 0),
|
||||
("parents", LPARENTS, db.DB_HASH, 0),
|
||||
("names", LNAMES, db.DB_BTREE, db.DB_DUPSORT),
|
||||
("template_trans", TEMPLATETRANS, db.DB_HASH, 0),
|
||||
("reference_map_primary_map", REF_PRI, db.DB_BTREE, 0),
|
||||
("reference_map_referenced_map", REF_REF, db.DB_BTREE, db.DB_DUPSORT),
|
||||
]
|
||||
@@ -767,8 +918,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
(self.repository_map, self.rid_trans, find_idmap),
|
||||
(self.note_map, self.nid_trans, find_idmap),
|
||||
(self.tag_map, self.tag_trans, find_idmap),
|
||||
(self.location_map, self.parents, find_parent),
|
||||
(self.location_map, self.names, find_name),
|
||||
(self.template_map, self.template_trans, find_idmap),
|
||||
(self.reference_map, self.reference_map_primary_map,
|
||||
find_primary_handle),
|
||||
(self.reference_map, self.reference_map_referenced_map,
|
||||
@@ -810,8 +960,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
( self.nid_trans, NIDTRANS ),
|
||||
( self.cid_trans, CIDTRANS ),
|
||||
( self.tag_trans, TAGTRANS ),
|
||||
( self.parents, LPARENTS ),
|
||||
( self.names, LNAMES ),
|
||||
( self.template_trans, TEMPLATETRANS ),
|
||||
( self.reference_map_primary_map, REF_PRI),
|
||||
( self.reference_map_referenced_map, REF_REF),
|
||||
]
|
||||
@@ -838,60 +987,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if callback:
|
||||
callback(12)
|
||||
|
||||
@catch_db_error
|
||||
def find_location_child_handles(self, handle):
|
||||
"""
|
||||
"""
|
||||
handle = str(handle)
|
||||
parent_cur = self.get_location_parent_cursor()
|
||||
|
||||
try:
|
||||
ret = parent_cur.set(handle)
|
||||
except:
|
||||
ret = None
|
||||
|
||||
while (ret is not None):
|
||||
(key, data) = ret
|
||||
|
||||
### FIXME: this is a dirty hack that works without no
|
||||
### sensible explanation. For some reason, for a readonly
|
||||
### database, secondary index returns a primary table key
|
||||
### corresponding to the data, not the data.
|
||||
if self.readonly:
|
||||
data = self.location_map.get(data)
|
||||
else:
|
||||
data = pickle.loads(data)
|
||||
|
||||
yield data[0]
|
||||
ret = parent_cur.next_dup()
|
||||
|
||||
parent_cur.close()
|
||||
|
||||
@catch_db_error
|
||||
def find_location_from_name(self, name):
|
||||
"""
|
||||
"""
|
||||
name = str(name).upper()
|
||||
size = len(name)
|
||||
name_cur = self.get_location_name_cursor()
|
||||
|
||||
try:
|
||||
ret = name_cur.set_range(name)
|
||||
ret = name_cur.current()
|
||||
except:
|
||||
ret = None
|
||||
|
||||
while (ret is not None):
|
||||
(key, data) = ret
|
||||
|
||||
if key[:size] != name:
|
||||
break
|
||||
|
||||
yield data[0]
|
||||
ret = name_cur.next()
|
||||
|
||||
name_cur.close()
|
||||
|
||||
@catch_db_error
|
||||
def find_backlink_handles(self, handle, include_classes=None):
|
||||
"""
|
||||
@@ -1138,6 +1233,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
(self.get_repository_cursor, Repository),
|
||||
(self.get_note_cursor, Note),
|
||||
(self.get_tag_cursor, Tag),
|
||||
(self.get_template_cursor, SrcTemplate),
|
||||
)
|
||||
|
||||
# Now we use the functions and classes defined above
|
||||
@@ -1194,6 +1290,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
txn.put(b'pevent_names', list(self.individual_event_names))
|
||||
txn.put(b'fattr_names', list(self.family_attributes))
|
||||
txn.put(b'pattr_names', list(self.individual_attributes))
|
||||
txn.put(b'sattr_names', list(self.source_attributes))
|
||||
txn.put(b'marker_names', list(self.marker_names))
|
||||
txn.put(b'child_refs', list(self.child_ref_types))
|
||||
txn.put(b'family_rels', list(self.family_rel_types))
|
||||
@@ -1210,7 +1307,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
txn.put(b'surname_list', self.surname_list)
|
||||
|
||||
self.metadata.close()
|
||||
|
||||
|
||||
def __close_early(self):
|
||||
"""
|
||||
Bail out if the incompatible version is discovered:
|
||||
@@ -1231,11 +1328,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.transaction_abort(self.transaction)
|
||||
self.env.txn_checkpoint()
|
||||
|
||||
lockstats = self.env.lock_stat()
|
||||
_LOG.debug("lock occupancy: %d%%, locked object occupancy: %d%%" % (
|
||||
round(lockstats['maxnlocks']*100/lockstats['maxlocks']),
|
||||
round(lockstats['maxnobjects']*100/lockstats['maxobjects'])))
|
||||
|
||||
self.__close_metadata()
|
||||
self.name_group.close()
|
||||
self.surnames.close()
|
||||
@@ -1249,8 +1341,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.cid_trans.close()
|
||||
self.pid_trans.close()
|
||||
self.tag_trans.close()
|
||||
self.parents.close()
|
||||
self.names.close()
|
||||
self.template_trans.close()
|
||||
self.reference_map_primary_map.close()
|
||||
self.reference_map_referenced_map.close()
|
||||
self.reference_map.close()
|
||||
@@ -1268,7 +1359,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.media_map.close()
|
||||
self.event_map.close()
|
||||
self.tag_map.close()
|
||||
self.location_map.close()
|
||||
self.template_map.close()
|
||||
self.env.close()
|
||||
self.__close_undodb()
|
||||
|
||||
@@ -1282,7 +1373,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.media_map = None
|
||||
self.event_map = None
|
||||
self.tag_map = None
|
||||
self.location_map = None
|
||||
self.template_map = None
|
||||
self.surnames = None
|
||||
self.env = None
|
||||
self.metadata = None
|
||||
@@ -1301,7 +1392,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.media_map = None
|
||||
self.event_map = None
|
||||
self.tag_map = None
|
||||
self.location_map = None
|
||||
self.template_map = None
|
||||
self.reference_map_primary_map = None
|
||||
self.reference_map_referenced_map = None
|
||||
self.reference_map = None
|
||||
@@ -1310,20 +1401,6 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.undo_history_callback = None
|
||||
self.undodb = None
|
||||
|
||||
if self.update_env_version:
|
||||
versionpath = os.path.join(self.path, BDBVERSFN)
|
||||
try:
|
||||
with open(versionpath, "w") as version_file:
|
||||
version = str(db.version())
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(version, UNITYPE):
|
||||
version = version.encode('utf-8')
|
||||
version_file.write(version)
|
||||
except:
|
||||
# Storing the version of Berkeley Db is not really vital.
|
||||
print ("Error storing berkeley db version")
|
||||
pass
|
||||
|
||||
try:
|
||||
clear_lock_file(self.get_save_path())
|
||||
except IOError:
|
||||
@@ -1467,12 +1544,12 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
"""
|
||||
return self.__add_object(obj, transaction, None, self.commit_tag)
|
||||
|
||||
def add_location(self, obj, transaction):
|
||||
def add_template(self, obj, transaction):
|
||||
"""
|
||||
Add a Location to the database, assigning a handle if it has not already
|
||||
Add a Template to the database, assigning a handle if it has not already
|
||||
been defined.
|
||||
"""
|
||||
return self.__add_object(obj, transaction, None, self.commit_location)
|
||||
return self.__add_object(obj, transaction, None, self.commit_template)
|
||||
|
||||
def __do_remove(self, handle, transaction, data_map, key):
|
||||
if self.readonly or not handle:
|
||||
@@ -1588,13 +1665,13 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.__do_remove(handle, transaction, self.tag_map,
|
||||
TAG_KEY)
|
||||
|
||||
def remove_location(self, handle, transaction):
|
||||
def remove_template(self, handle, transaction):
|
||||
"""
|
||||
Remove the Location specified by the database handle from the
|
||||
Remove the Template specified by the database handle from the
|
||||
database, preserving the change in the passed transaction.
|
||||
"""
|
||||
self.__do_remove(handle, transaction, self.location_map,
|
||||
LOCATION_KEY)
|
||||
self.__do_remove(handle, transaction, self.template_map,
|
||||
TEMPLATE_KEY)
|
||||
|
||||
@catch_db_error
|
||||
def set_name_group_mapping(self, name, group):
|
||||
@@ -1796,6 +1873,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if attr.type.is_custom() and str(attr.type)]
|
||||
self.media_attributes.update(attr_list)
|
||||
|
||||
self.source_attributes.update(
|
||||
[str(attr.type) for attr in source.attribute_list
|
||||
if attr.type.is_custom() and str(attr.type)])
|
||||
|
||||
def commit_citation(self, citation, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified Citation to the database, storing the changes as
|
||||
@@ -1810,6 +1891,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
if attr.type.is_custom() and str(attr.type)]
|
||||
self.media_attributes.update(attr_list)
|
||||
|
||||
self.source_attributes.update(
|
||||
[str(attr.type) for attr in citation.attribute_list
|
||||
if attr.type.is_custom() and str(attr.type)])
|
||||
|
||||
def commit_place(self, place, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified Place to the database, storing the changes as
|
||||
@@ -1916,12 +2001,12 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.commit_base(tag, self.tag_map, TAG_KEY,
|
||||
transaction, change_time)
|
||||
|
||||
def commit_location(self, location, transaction, change_time=None):
|
||||
def commit_template(self, tag, transaction, change_time=None):
|
||||
"""
|
||||
Commit the specified Location to the database, storing the changes as
|
||||
part of the transaction.
|
||||
Commit the specified Template to the database, storing the changes as part
|
||||
of the transaction.
|
||||
"""
|
||||
self.commit_base(location, self.location_map, LOCATION_KEY,
|
||||
self.commit_base(tag, self.template_map, TEMPLATE_KEY,
|
||||
transaction, change_time)
|
||||
|
||||
def get_from_handle(self, handle, class_type, data_map):
|
||||
@@ -1929,6 +2014,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
handle = handle.encode('utf-8')
|
||||
try:
|
||||
data = data_map.get(handle, txn=self.txn)
|
||||
except UnicodeDecodeError:
|
||||
#we need to assume we opened data in python3 saved in python2
|
||||
raw = data_map.db.get(handle, txn=self.txn)
|
||||
data = pickle.loads(raw, encoding='utf-8')
|
||||
except:
|
||||
data = None
|
||||
# under certain circumstances during a database reload,
|
||||
@@ -2084,7 +2173,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
self.surnames = self.__open_db(self.full_name, SURNAMES,
|
||||
db.DB_BTREE, db.DB_DUP | db.DB_DUPSORT)
|
||||
|
||||
self.person_map.associate(self.surnames, find_surname,
|
||||
self.person_map.associate(self.surnames, find_byte_surname,
|
||||
DBFLAGS_O)
|
||||
|
||||
self.reference_map_referenced_map = self.__open_db(self.full_name,
|
||||
@@ -2130,8 +2219,10 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
upgrade.gramps_upgrade_16(self)
|
||||
if version < 17:
|
||||
upgrade.gramps_upgrade_17(self)
|
||||
if version < 18:
|
||||
upgrade.gramps_upgrade_18(self)
|
||||
# On upgrade from 16 to 17, SrcTemplate is added, so the templates
|
||||
# need to be loaded. In the future, on upgrade from 17, the
|
||||
# templates will already be present and will not need to be loaded
|
||||
self.load_templates = True
|
||||
|
||||
self.reset()
|
||||
self.set_total(6)
|
||||
@@ -2183,8 +2274,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
# The DB_PRIVATE flag must go if we ever move to multi-user setup
|
||||
env_flags = db.DB_CREATE | db.DB_PRIVATE |\
|
||||
db.DB_INIT_MPOOL | db.DB_INIT_LOCK |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN | db.DB_THREAD
|
||||
db.DB_INIT_MPOOL |\
|
||||
db.DB_INIT_LOG | db.DB_INIT_TXN
|
||||
|
||||
# As opposed to before, we always try recovery on databases
|
||||
env_flags |= db.DB_RECOVER
|
||||
@@ -2197,9 +2288,28 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
|
||||
|
||||
self.metadata = self.__open_shelf(full_name, META)
|
||||
|
||||
_LOG.debug("Write schema version %s" % _DBVERSION)
|
||||
with BSDDBTxn(self.env, self.metadata) as txn:
|
||||
txn.put(b'version', _DBVERSION)
|
||||
|
||||
versionpath = os.path.join(name, BDBVERSFN)
|
||||
version = str(db.version())
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(version, UNITYPE):
|
||||
version = version.encode('utf-8')
|
||||
_LOG.debug("Write bsddb version %s" % version)
|
||||
with open(versionpath, "w") as version_file:
|
||||
version_file.write(version)
|
||||
|
||||
versionpath = os.path.join(name, "pythonversion.txt")
|
||||
version = str(version_info[0])
|
||||
if sys.version_info[0] < 3:
|
||||
if isinstance(version, UNITYPE):
|
||||
version = version.encode('utf-8')
|
||||
_LOG.debug("Write python version file to %s" % version)
|
||||
with open(versionpath, "w") as version_file:
|
||||
version_file.write(version)
|
||||
|
||||
self.metadata.close()
|
||||
self.env.close()
|
||||
|
||||
|
@@ -54,7 +54,7 @@ Specific symbols for parts of a name are defined:
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().sgettext
|
||||
_ = glocale.translation.sgettext
|
||||
import re
|
||||
import logging
|
||||
LOG = logging.getLogger(".gramps.gen")
|
||||
@@ -1018,6 +1018,14 @@ class NameDisplay(object):
|
||||
# flag that works in standard python format strings.
|
||||
new_fmt = re.sub("|".join(patterns), "%s", new_fmt)
|
||||
|
||||
# replace special meaning codes we need to have verbatim in output
|
||||
if (len(new_fmt) > 2 and new_fmt[0] == new_fmt[-1] == '"'):
|
||||
new_fmt = new_fmt.replace('\\', r'\\')
|
||||
new_fmt = new_fmt[1:-1].replace('"', r'\"')
|
||||
else:
|
||||
new_fmt = new_fmt.replace('\\', r'\\')
|
||||
new_fmt = new_fmt.replace('"', '\\\"')
|
||||
|
||||
# find each format flag in the original format string
|
||||
# for each one we find the variable name that is needed to
|
||||
# replace it and add this to a list. This list will be used to
|
||||
|
@@ -141,8 +141,8 @@ class FilterList(object):
|
||||
f.write(' comment="%s"' % self.fix(comment))
|
||||
f.write('>\n')
|
||||
for rule in the_filter.get_rules():
|
||||
f.write(' <rule class="%s">\n'
|
||||
% rule.__class__.__name__)
|
||||
f.write(' <rule class="%s" use_regex="%s">\n'
|
||||
% (rule.__class__.__name__, rule.use_regex))
|
||||
for value in list(rule.values()):
|
||||
f.write(' <arg value="%s"/>\n' % self.fix(value))
|
||||
f.write(' </rule>\n')
|
||||
|
@@ -29,7 +29,7 @@ from __future__ import print_function, unicode_literals
|
||||
|
||||
from xml.sax import handler
|
||||
from ..const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -55,6 +55,7 @@ class FilterParser(handler.ContentHandler):
|
||||
self.a = []
|
||||
self.cname = None
|
||||
self.namespace = 'Person'
|
||||
self.use_regex = False
|
||||
|
||||
def setDocumentLocator(self, locator):
|
||||
self.locator = locator
|
||||
@@ -83,6 +84,10 @@ class FilterParser(handler.ContentHandler):
|
||||
self.f.set_comment(attrs['comment'])
|
||||
self.gfilter_list.add(self.namespace, self.f)
|
||||
elif tag == "rule":
|
||||
if 'use_regex' in attrs:
|
||||
self.use_regex = attrs['use_regex'] == 'True'
|
||||
else:
|
||||
self.use_regex = False
|
||||
save_name = attrs['class']
|
||||
if save_name in old_names_2_class:
|
||||
self.r = old_names_2_class[save_name]
|
||||
@@ -116,7 +121,7 @@ class FilterParser(handler.ContentHandler):
|
||||
"Trying to load with subset of arguments.") %\
|
||||
self.f.get_name())
|
||||
nargs = len(self.r.labels)
|
||||
rule = self.r(self.a[0:nargs])
|
||||
rule = self.r(self.a[0:nargs], self.use_regex)
|
||||
self.f.add_rule(rule)
|
||||
else:
|
||||
if len(self.r.labels) > len(self.a):
|
||||
@@ -125,7 +130,7 @@ class FilterParser(handler.ContentHandler):
|
||||
"will be upgraded.") %\
|
||||
self.f.get_name())
|
||||
try:
|
||||
rule = self.r(self.a)
|
||||
rule = self.r(self.a, self.use_regex)
|
||||
except AssertionError as msg:
|
||||
print(msg)
|
||||
print(_("ERROR: filter %s could not be correctly loaded. "
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
import re
|
||||
import time
|
||||
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -48,12 +48,13 @@ class HasCitationBase(Rule):
|
||||
First parameter is [Volume/page, Date, Confidence]
|
||||
"""
|
||||
|
||||
labels = [ _('Volume/Page:'),
|
||||
labels = [ _('Name:'),
|
||||
_('Date:'),
|
||||
_('Confidence:') ]
|
||||
name = _('Citations matching parameters')
|
||||
description = _("Matches citations with particular parameters")
|
||||
category = _('Citation/source filters')
|
||||
allow_regex = True
|
||||
|
||||
def prepare(self, db):
|
||||
self.date = None
|
||||
@@ -71,7 +72,7 @@ class HasCitationBase(Rule):
|
||||
return False
|
||||
|
||||
def _apply(self, db, citation):
|
||||
if not self.match_substring(0, citation.get_page()):
|
||||
if not self.match_substring(0, citation.get_name()):
|
||||
return False
|
||||
|
||||
if self.date:
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -55,6 +55,7 @@ class HasEventBase(Rule):
|
||||
name = 'Events matching parameters'
|
||||
description = "Matches events with particular parameters"
|
||||
category = _('Event filters')
|
||||
allow_regex = True
|
||||
|
||||
def prepare(self, db):
|
||||
self.date = None
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -50,13 +50,13 @@ class HasNoteBase(Rule):
|
||||
description = "Matches objects that have a certain number of notes"
|
||||
category = _('General filters')
|
||||
|
||||
def __init__(self, arg):
|
||||
def __init__(self, arg, use_regex=False):
|
||||
# Upgrade from pre 3.1 HasNote filter, use defaults that correspond
|
||||
# Previous filter had 0 arguments
|
||||
if len(arg) == 0:
|
||||
Rule.__init__(self, ["0", 'greater than'])
|
||||
Rule.__init__(self, ["0", 'greater than'], use_regex)
|
||||
else:
|
||||
Rule.__init__(self, arg)
|
||||
Rule.__init__(self, arg, use_regex)
|
||||
|
||||
def prepare(self, db):
|
||||
# things we want to do just once, not for every handle
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#-------------------------------------------------------------------------
|
||||
import re
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -48,8 +48,8 @@ class HasNoteRegexBase(Rule):
|
||||
"matching a regular expression"
|
||||
category = _('General filters')
|
||||
|
||||
def __init__(self, list):
|
||||
Rule.__init__(self, list)
|
||||
def __init__(self, list, use_regex=False):
|
||||
Rule.__init__(self, list, use_regex)
|
||||
|
||||
try:
|
||||
self.match = re.compile(list[0],re.I|re.U|re.L)
|
||||
@@ -61,6 +61,6 @@ class HasNoteRegexBase(Rule):
|
||||
for notehandle in notelist:
|
||||
note = db.get_note_from_handle(notehandle)
|
||||
n = note.get()
|
||||
if self.match.match(n) is not None:
|
||||
if self.match.search(n) is not None:
|
||||
return True
|
||||
return False
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.get_translation().gettext
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|