Compare commits
67
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d080d15352 | ||
|
|
f3c4314a89 | ||
|
|
2284694530 | ||
|
|
15edee3a26 | ||
|
|
d0e698ffac | ||
|
|
addfaa933f | ||
|
|
e2fc32c4c0 | ||
|
|
46e8d865b1 | ||
|
|
c208b91184 | ||
|
|
ab6342af70 | ||
|
|
715ddbbab3 | ||
|
|
cc936c589b | ||
|
|
f554ffd57d | ||
|
|
46e9edaf59 | ||
|
|
29620a31ef | ||
|
|
ca2fd738d0 | ||
|
|
821caa8a5f | ||
|
|
3a45e70f54 | ||
|
|
89f6c7d83e | ||
|
|
ca73e01512 | ||
|
|
bfcecc646d | ||
|
|
77f9760504 | ||
|
|
3a93d03a4a | ||
|
|
03851db458 | ||
|
|
9f87dfd54b | ||
|
|
711e25e5bb | ||
|
|
f1eecb349d | ||
|
|
04baa6b50f | ||
|
|
c18d73ea8f | ||
|
|
671f64c08c | ||
|
|
b9cd27550f | ||
|
|
8b26f688cb | ||
|
|
e41c6db70d | ||
|
|
fdcc02d1bd | ||
|
|
f4f5104b72 | ||
|
|
0caf61b805 | ||
|
|
c46a66ecd1 | ||
|
|
35d553b4eb | ||
|
|
8bc6d475d9 | ||
|
|
b5fec9d1a3 | ||
|
|
1a5c516179 | ||
|
|
054d29612c | ||
|
|
ad066ba200 | ||
|
|
ffb3b1e232 | ||
|
|
76c896f977 | ||
|
|
5e00312139 | ||
|
|
c7ad3f3295 | ||
|
|
11723ffd8c | ||
|
|
cb9bebee1e | ||
|
|
a9ac56b33c | ||
|
|
19038fab93 | ||
|
|
fd13311aa0 | ||
|
|
ec0b9fb54b | ||
|
|
8b94955772 | ||
|
|
9a229466fd | ||
|
|
647c9cfef5 | ||
|
|
29443339cb | ||
|
|
f4f2747c65 | ||
|
|
ba7913fe3c | ||
|
|
5526f64e1f | ||
|
|
0a17eab461 | ||
|
|
fcce312e0a | ||
|
|
4ed2b0bace | ||
|
|
759075b3e4 | ||
|
|
7f4956dd00 | ||
|
|
e1ab03348e | ||
|
|
2033fd6567 |
@@ -1,3 +1,20 @@
|
||||
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:
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
"UNSTABLE Gramps 4.0.0 Alpha1 release.
|
||||
"UNSTABLE Gramps 4.0.0 Alpha2 release.
|
||||
|
||||
This is a technology preview to allow plugin writers and packagers-installer
|
||||
writers to update their plugins and scripts. This release is not production
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ copyright = u'2012, Gramps project'
|
||||
# The short X.Y version.
|
||||
version = '4.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.0.0'
|
||||
release = '4.0.0-alpha2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
+3
-1
@@ -249,7 +249,9 @@ gramps(1) 3.4.0 gramps(1)
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps*
|
||||
|
||||
|
||||
+7
-4
@@ -1,7 +1,7 @@
|
||||
English
|
||||
=======
|
||||
|
||||
gramps(1) 4.0.0 gramps(1)
|
||||
gramps(1) @VERSION@ gramps(1)
|
||||
|
||||
|
||||
|
||||
@@ -262,11 +262,14 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
**KNOWN BUGS AND LIMITATIONS**
|
||||
**FILES**
|
||||
|
||||
**FILES**
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps*
|
||||
|
||||
@@ -293,4 +296,4 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
|
||||
January 2013 4.0.0 gramps(1)
|
||||
gramps(1) @VERSION@ gramps(1)
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ copyright = u'2012, Gramps project'
|
||||
# The short X.Y version.
|
||||
version = '4.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '4.0.0'
|
||||
release = '4.0.0-alpha2'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
+82
-81
@@ -1,9 +1,7 @@
|
||||
French
|
||||
=======
|
||||
|
||||
|
||||
gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
gramps(1) @VERSION@ gramps(1)
|
||||
|
||||
|
||||
**NOM**
|
||||
@@ -34,33 +32,33 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
**OPTIONS**
|
||||
**gramps** *FICHIER*
|
||||
Si *FICHIER* est désigné (sans autres commandes) comme arbre
|
||||
familial ou comme répertoire d'arbre familial, alors une session
|
||||
interactive est ouverte. Si *FICHIER* est un format de fichier
|
||||
supporté par Gramps, une base vide est créée dont le nom est
|
||||
celui du *FICHIER* et les données y seront importées. Les autres
|
||||
options sont ignorées. Ce type de lancement permet d'utiliser
|
||||
gramps pour manipuler des données comme dans un navigateur web.
|
||||
Les formats natifs de gramps sont acceptés, voir ci-dessous.
|
||||
Si *FICHIER* est désigné (sans autres commandes) comme arbre
|
||||
familial ou comme répertoire d'arbre familial, alors une session
|
||||
interactive est ouverte. Si *FICHIER* est un format de fichier
|
||||
supporté par Gramps, une base vide est créée dont le nom est
|
||||
celui du *FICHIER* et les données y seront importées. Les autres
|
||||
options sont ignorées. Ce type de lancement permet d'utiliser
|
||||
gramps pour manipuler des données comme dans un navigateur web.
|
||||
Les formats natifs de gramps sont acceptés, voir ci-dessous.
|
||||
|
||||
|
||||
**-f** , **--format=** *FORMAT*
|
||||
Le format spécifique du *FICHIER* est précédé par les arguments
|
||||
**-i** , ou **-e** . Si l'option **-f** n'est pas donnée pour le *FICHIER* ,
|
||||
alors le format sera celui de l'extension ou du type-MIME.
|
||||
Le format spécifique du *FICHIER* est précédé par les arguments
|
||||
**-i** , ou **-e** . Si l'option **-f** n'est pas donnée pour le *FICHIER* ,
|
||||
alors le format sera celui de l'extension ou du type-MIME.
|
||||
|
||||
Les formats de sortie disponibles sont **gramps-xml** (deviné si
|
||||
*FICHIER* se termine par **.gramps** ), et **gedcom** (deviné si *FICHIER* se
|
||||
termine par **.ged** ), ou tout autre fichier d'exportation
|
||||
disponible dans le système de plugin Gramps.
|
||||
Les formats de sortie disponibles sont **gramps-xml** (deviné si
|
||||
*FICHIER* se termine par **.gramps** ), et **gedcom** (deviné si *FICHIER* se
|
||||
termine par **.ged** ), ou tout autre fichier d'exportation
|
||||
disponible dans le système de plugin Gramps.
|
||||
|
||||
Les formats disponibles pour l'importation sont **grdb** ,
|
||||
**gramps-xml** , **gedcom** , **gramps-pkg** (deviné si *FICHIER* se termine par
|
||||
**.gpkg** ), et **geneweb** (deviné si *FICHIER* se termine par **.gw** ).
|
||||
Les formats disponibles pour l'importation sont **grdb** ,
|
||||
**gramps-xml** , **gedcom** , **gramps-pkg** (deviné si *FICHIER* se termine par
|
||||
**.gpkg** ), et **geneweb** (deviné si *FICHIER* se termine par **.gw** ).
|
||||
|
||||
Les formats disponibles pour l'exportation sont **gramps-xml** , **ged‐
|
||||
com** , **gramps-pkg** , **wft** (deviné si *FICHIER* se termine par **.wft** ),
|
||||
**geneweb** .
|
||||
Les formats disponibles pour l'exportation sont **gramps-xml** , **ged‐
|
||||
com** , **gramps-pkg** , **wft** (deviné si *FICHIER* se termine par **.wft** ),
|
||||
**geneweb** .
|
||||
|
||||
|
||||
**-l**
|
||||
@@ -68,29 +66,29 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
**-u** , **--force-unlock**
|
||||
Débloquer une base de données verrouillée.
|
||||
Débloquer une base de données verrouillée.
|
||||
|
||||
|
||||
**-O** , **--open=** *BASE_DE_DONNEES*
|
||||
Ouvrir une *BASE_DE_DONNEES* qui doit être une base présente dans
|
||||
le répertoire des bases ou le nom d'un arbre familial existant.
|
||||
Si aucune action n'est définie, les options d'import ou d'export
|
||||
sont données par la ligne de commande puis une session interac‐
|
||||
tive est ouverte, utilisant cette base de données.
|
||||
Ouvrir une *BASE_DE_DONNEES* qui doit être une base présente dans
|
||||
le répertoire des bases ou le nom d'un arbre familial existant.
|
||||
Si aucune action n'est définie, les options d'import ou d'export
|
||||
sont données par la ligne de commande puis une session interactive
|
||||
est ouverte, utilisant cette base de données.
|
||||
|
||||
Seulement une base peut être ouverte. Si vous utilisez plusieurs
|
||||
sources, vous devez utiliser l'option d'import.
|
||||
Seulement une base peut être ouverte. Si vous utilisez plusieurs
|
||||
sources, vous devez utiliser l'option d'import.
|
||||
|
||||
|
||||
**-i** , **--import=** *FICHIER*
|
||||
Importer des données depuis un *FICHIER* . Si vous n'avez pas
|
||||
spécifié de base de données alors une base de données temporaire
|
||||
est utilisée; elle sera effacée quand vous quitterez gramps.
|
||||
Importer des données depuis un *FICHIER* . Si vous n'avez pas
|
||||
spécifié de base de données alors une base de données temporaire
|
||||
est utilisée; elle sera effacée quand vous quitterez gramps.
|
||||
|
||||
Quand plus d'un fichier doit être importé, chacun doit être
|
||||
précédé par la commande **-i** . Ces fichiers sont importés dans le
|
||||
même ordre, i.e. **-i** *FICHIER1* **-i** *FICHIER2* et **-i** *FICHIER2* **-i**
|
||||
*FICHIER1* vont tous les deux produire différents IDs gramps.
|
||||
Quand plus d'un fichier doit être importé, chacun doit être
|
||||
précédé par la commande **-i** . Ces fichiers sont importés dans le
|
||||
même ordre, **-i** *FICHIER1* **-i** *FICHIER2* et **-i** *FICHIER2* **-i**
|
||||
*FICHIER1* vont tous les deux produire différents IDs gramps.
|
||||
|
||||
|
||||
**-e** , **--export=** *FICHIER*
|
||||
@@ -104,38 +102,38 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
**-a** , **--action=** *ACTION*
|
||||
Accomplir une *ACTION* sur les données importées. C'est effectué à
|
||||
la fin de l'importation. Les actions possibles sont **summary**
|
||||
(comme le rapport -> Afficher -> Statistiques sur la base),
|
||||
**check** (comme l'outil -> Réparation de la base -> Vérifier et
|
||||
réparer), **report** (produit un rapport) et **tool** (utilise un
|
||||
outil), ces derniers ont besoin de *OPTION* précédé par la commande -p.
|
||||
Accomplir une *ACTION* sur les données importées. C'est effectué à
|
||||
la fin de l'importation. Les actions possibles sont **summary**
|
||||
(comme le rapport -> Afficher -> Statistiques sur la base),
|
||||
**check** (comme l'outil -> Réparation de la base -> Vérifier et
|
||||
réparer), **report** (produit un rapport) et **tool** (utilise un
|
||||
outil), ces derniers ont besoin de *OPTION* précédé par la commande -p.
|
||||
|
||||
L' *OPTION* doit satisfaire ces conditions:
|
||||
Il ne doit pas y avoir d'espace. Si certains arguments doivent
|
||||
utiliser des espaces, la chaîne doit être encadrée par des
|
||||
guillemets. Les options vont par paire nom et valeur. Une
|
||||
paire est séparée par un signe égal. Différentes paires sont
|
||||
séparées par une virgule.
|
||||
L' *OPTION* doit satisfaire ces conditions:
|
||||
Il ne doit pas y avoir d'espace. Si certains arguments doivent
|
||||
utiliser des espaces, la chaîne doit être encadrée par des
|
||||
guillemets. Les options vont par paire nom et valeur. Une
|
||||
paire est séparée par un signe égal. Différentes paires sont
|
||||
séparées par une virgule.
|
||||
|
||||
La plupart des options sont spécifiques à chaque rapport. Même
|
||||
s'il existe des options communes.
|
||||
La plupart des options sont spécifiques à chaque rapport. Même
|
||||
s'il existe des options communes.
|
||||
|
||||
**name=name**
|
||||
Cette option est obligatoire, elle détermine quel rapport ou
|
||||
outil sera utilisé. Si le name saisi ne correspond à aucun
|
||||
module disponible, un message d'erreur sera ajouté.
|
||||
**name=name**
|
||||
Cette option est obligatoire, elle détermine quel rapport ou
|
||||
outil sera utilisé. Si le name saisi ne correspond à aucun
|
||||
module disponible, un message d'erreur sera ajouté.
|
||||
|
||||
**show=all**
|
||||
Cette option produit une liste avec les noms des options
|
||||
disponibles pour un rapport donné.
|
||||
**show=all**
|
||||
Cette option produit une liste avec les noms des options
|
||||
disponibles pour un rapport donné.
|
||||
|
||||
**show=optionname**
|
||||
Cette option affiche une description de toutes les fonctionnalités
|
||||
proposées par optionname, aussi bien les types que les valeurs pour une option.
|
||||
|
||||
Utiliser les options ci-dessus pour trouver tout sur un rapport
|
||||
choisi.
|
||||
choisi.
|
||||
|
||||
|
||||
Quand plus d'une action doit être effectuée, chacune doit être précédée
|
||||
@@ -144,23 +142,23 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
**-d** , **--debug=** *NOM_LOGGER*
|
||||
Permet les logs de debug pour le développement et les tests.
|
||||
Regarder le code source pour les détails.
|
||||
Permet les logs de debug pour le développement et les tests.
|
||||
Regarder le code source pour les détails.
|
||||
|
||||
**--version**
|
||||
Imprime le numéro de version pour gramps puis quitte.
|
||||
Imprime le numéro de version pour gramps puis quitte.
|
||||
|
||||
|
||||
|
||||
|
||||
**Opération**
|
||||
Si le premie argument de la ligne de commande ne commence pas par un
|
||||
tiret (i.e. pas d'instruction), gramps va essayer d'ouvrir la base de
|
||||
données avec le nom donné par le premier argument et démarrer une ses‐
|
||||
Si le premier argument de la ligne de commande ne commence pas par un
|
||||
tiret (i.e. pas d'instruction), gramps va essayer d'ouvrir la base de
|
||||
données avec le nom donné par le premier argument et démarrer une ses‐
|
||||
sion interactive, en ignorant le reste de la ligne de commande.
|
||||
|
||||
|
||||
Si la commande **-O** est notée, alors gramps va essayer le fichier défini
|
||||
Si la commande **-O** est notée, alors gramps va essayer le fichier défini
|
||||
et va travailler avec ses données, comme pour les autres paramètres de
|
||||
la ligne de commande.
|
||||
|
||||
@@ -183,7 +181,7 @@ gramps(1) 4.0.0 gramps(1)
|
||||
Cette base sera **import_db.grdb** dans le répertoire **~/.gramps/import**.
|
||||
|
||||
|
||||
Les erreurs rencontrées lors d'importation, d'exportation, ou d'action, seront
|
||||
Les erreurs rencontrées lors d'importation, d'exportation, ou d'action, seront
|
||||
mémorisées en *stdout* (si elles sont le fait de la manipulation par
|
||||
gramps) ou en *stderr* (si elles ne sont pas le fait d'une manipulation).
|
||||
Utilisez les shell de redirection de *stdout* et *stderr* pour sauver
|
||||
@@ -191,16 +189,16 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
**EXEMPLES**
|
||||
Pour ouvrir un arbre familial et y importer un fichier XML, on peut
|
||||
Pour ouvrir un arbre familial et y importer un fichier XML, on peut
|
||||
saisir:
|
||||
|
||||
**gramps -O** *'Mon Arbre Familial'* **-i** *~/db3.gramps*
|
||||
**gramps -O** *'Mon Arbre Familial'* **-i** *~/db3.gramps*
|
||||
|
||||
Ceci ouvre un arbre familial, pour faire la même chose, mais importer
|
||||
dans un arbre familial temporaire et démarrer une session interactive,
|
||||
on peut saisir:
|
||||
dans un arbre familial temporaire et démarrer une session interactive,
|
||||
on peut saisir :
|
||||
|
||||
**gramps -i** *'Mon Arbre Familial'* **-i** *~/db3.gramps*
|
||||
**gramps -i** *'Mon Arbre Familial'* **-i** *~/db3.gramps*
|
||||
|
||||
Lecture de quatre bases de données dont les formats peuvent être
|
||||
devinés d'après les noms, puis vérification des données:
|
||||
@@ -225,12 +223,12 @@ gramps(1) 4.0.0 gramps(1)
|
||||
Pour lire trois ensembles de données puis lancer une session
|
||||
interactive de gramps sur le tout :
|
||||
|
||||
**gramps -i** *file1.ged* **-i** *file2.tgz* **-i** *~/db3.gramps*
|
||||
**gramps -i** *file1.ged* **-i** *file2.tgz* **-i** *~/db3.gramps*
|
||||
|
||||
Pour lancer l'outil de vérification de la base de données depuis la
|
||||
ligne de commande et obtenir le résultat :
|
||||
|
||||
**gramps -O** *'My Family Tree'* **-a** *tool* **-p name=** *verify*
|
||||
**gramps -O** *'My Family Tree'* **-a** *tool* **-p name=** *verify*
|
||||
|
||||
Enfin, pour lancer une session interactive normale, entrer :
|
||||
|
||||
@@ -253,21 +251,24 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
**CONCEPTS**
|
||||
Gramps est un système basé sur le support de plugin-python, permettant
|
||||
d'importer et d'exporter, la saisie, générer des rapports, des outils,
|
||||
et afficher des filtres pouvant être ajoutés sans modifier le programme.
|
||||
d'importer et d'exporter, la saisie, générer des rapports, des outils,
|
||||
et afficher des filtres pouvant être ajoutés sans modifier le programme.
|
||||
|
||||
Par ailleurs, gramps permet la génération directe : impression, rap‐
|
||||
ports avec sortie vers d'autres formats, comme *LibreOffice.org* ,
|
||||
*HTML* , ou *LaTeX* pour permettre à l'utilisateur de choisir selon ses
|
||||
*HTML* , ou *LaTeX* pour permettre à l'utilisateur de choisir selon ses
|
||||
besoins
|
||||
|
||||
|
||||
**BUGS CONNUS ET LIMITATIONS**
|
||||
|
||||
**FICHIERS**
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps*
|
||||
|
||||
@@ -296,4 +297,4 @@ gramps(1) 4.0.0 gramps(1)
|
||||
|
||||
|
||||
|
||||
Janvier 2013 4.0.0 gramps(1)
|
||||
gramps(1) @VERSION@ gramps(1)
|
||||
|
||||
+32
-36
@@ -1,4 +1,4 @@
|
||||
.TH "GRAMPS" "1" "04 December 2012" "4.0" "Gramps"
|
||||
.TH "GRAMPS" "1" "28 December 2012" "4.0" "Gramps"
|
||||
.SH NAME
|
||||
gramps \- Gramps Documentation
|
||||
.
|
||||
@@ -28,10 +28,10 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.\" Man page generated from reStructeredText.
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.sp
|
||||
gramps(1) 4.0.0 gramps(1)
|
||||
gramps(1) @VERSION@ gramps(1)
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \fBNOM\fP
|
||||
@@ -72,7 +72,7 @@ Les formats natifs de gramps sont acceptés, voir ci\-dessous.
|
||||
.TP
|
||||
.B \fB\-f\fP , \fB\-\-format=\fP \fIFORMAT\fP
|
||||
Le format spécifique du \fIFICHIER\fP est précédé par les arguments
|
||||
\fB\-i\fP , ou \fB\-e\fP . Si l\(aqoption \fB\-f\fP n\(aqest pas donnée pour le \fIFICHIER\fP ,
|
||||
\fB\-i\fP , ou \fB\-e\fP . Si l\(aqoption \fB\-f\fP n\(aqest pas donnée pour le \fIFICHIER\fP ,
|
||||
alors le format sera celui de l\(aqextension ou du type\-MIME.
|
||||
.sp
|
||||
Les formats de sortie disponibles sont \fBgramps\-xml\fP (deviné si
|
||||
@@ -96,10 +96,10 @@ Débloquer une base de données verrouillée.
|
||||
.TP
|
||||
.B \fB\-O\fP , \fB\-\-open=\fP \fIBASE_DE_DONNEES\fP
|
||||
Ouvrir une \fIBASE_DE_DONNEES\fP qui doit être une base présente dans
|
||||
le répertoire des bases ou le nom d\(aqun arbre familial existant.
|
||||
le répertoire des bases ou le nom d\(aqun arbre familial existant.
|
||||
Si aucune action n\(aqest définie, les options d\(aqimport ou d\(aqexport
|
||||
sont données par la ligne de commande puis une session interac‐
|
||||
tive est ouverte, utilisant cette base de données.
|
||||
sont données par la ligne de commande puis une session interactive
|
||||
est ouverte, utilisant cette base de données.
|
||||
.sp
|
||||
Seulement une base peut être ouverte. Si vous utilisez plusieurs
|
||||
sources, vous devez utiliser l\(aqoption d\(aqimport.
|
||||
@@ -109,9 +109,9 @@ Importer des données depuis un \fIFICHIER\fP . Si vous n\(aqavez pas
|
||||
spécifié de base de données alors une base de données temporaire
|
||||
est utilisée; elle sera effacée quand vous quitterez gramps.
|
||||
.sp
|
||||
Quand plus d\(aqun fichier doit être importé, chacun doit être
|
||||
Quand plus d\(aqun fichier doit être importé, chacun doit être
|
||||
précédé par la commande \fB\-i\fP . Ces fichiers sont importés dans le
|
||||
même ordre, i.e. \fB\-i\fP \fIFICHIER1\fP \fB\-i\fP \fIFICHIER2\fP et \fB\-i\fP \fIFICHIER2\fP \fB\-i\fP
|
||||
même ordre, \fB\-i\fP \fIFICHIER1\fP \fB\-i\fP \fIFICHIER2\fP et \fB\-i\fP \fIFICHIER2\fP \fB\-i\fP
|
||||
\fIFICHIER1\fP vont tous les deux produire différents IDs gramps.
|
||||
.TP
|
||||
.B \fB\-e\fP , \fB\-\-export=\fP \fIFICHIER\fP
|
||||
@@ -124,17 +124,15 @@ précédé par la commande \fB\-e\fP . Ces fichiers sont importés dans le
|
||||
même ordre.
|
||||
.TP
|
||||
.B \fB\-a\fP , \fB\-\-action=\fP \fIACTION\fP
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
Accomplir une \fIACTION\fP sur les données importées. C\(aqest effectué à
|
||||
la fin de l\(aqimportation. Les actions possibles sont \fBsummary\fP
|
||||
(comme le rapport \-> Afficher \-> Statistiques sur la base),
|
||||
\fBcheck\fP (comme l\(aqoutil \-> Réparation de la base \-> Vérifier et
|
||||
réparer), \fBreport\fP (produit un rapport) et \fBtool\fP (utilise un
|
||||
la fin de l\(aqimportation. Les actions possibles sont \fBsummary\fP
|
||||
(comme le rapport \-> Afficher \-> Statistiques sur la base),
|
||||
\fBcheck\fP (comme l\(aqoutil \-> Réparation de la base \-> Vérifier et
|
||||
réparer), \fBreport\fP (produit un rapport) et \fBtool\fP (utilise un
|
||||
outil), ces derniers ont besoin de \fIOPTION\fP précédé par la commande \-p.
|
||||
.sp
|
||||
L\(aq \fIOPTION\fP doit satisfaire ces conditions:
|
||||
Il ne doit pas y avoir d\(aqespace. Si certains arguments doivent
|
||||
Il ne doit pas y avoir d\(aqespace. Si certains arguments doivent
|
||||
utiliser des espaces, la chaîne doit être encadrée par des
|
||||
guillemets. Les options vont par paire nom et valeur. Une
|
||||
paire est séparée par un signe égal. Différentes paires sont
|
||||
@@ -144,25 +142,21 @@ La plupart des options sont spécifiques à chaque rapport. Même
|
||||
s\(aqil existe des options communes.
|
||||
.sp
|
||||
\fBname=name\fP
|
||||
Cette option est obligatoire, elle détermine quel rapport ou
|
||||
Cette option est obligatoire, elle détermine quel rapport ou
|
||||
outil sera utilisé. Si le name saisi ne correspond à aucun
|
||||
module disponible, un message d\(aqerreur sera ajouté.
|
||||
.sp
|
||||
\fBshow=all\fP
|
||||
Cette option produit une liste avec les noms des options
|
||||
disponibles pour un rapport donné.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fBshow=optionname\fP
|
||||
Cette option affiche une description de toutes les fonctionnalités
|
||||
proposées par optionname, aussi bien les types que les valeurs pour une option.
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B Utiliser les options ci\-dessus pour trouver tout sur un rapport
|
||||
.sp
|
||||
Utiliser les options ci\-dessus pour trouver tout sur un rapport
|
||||
choisi.
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
Quand plus d\(aqune action doit être effectuée, chacune doit être précédée
|
||||
par la commande \fB\-a\fP . Les actions seront réalisées une à une, dans
|
||||
@@ -178,12 +172,12 @@ Imprime le numéro de version pour gramps puis quitte.
|
||||
.UNINDENT
|
||||
.TP
|
||||
.B \fBOpération\fP
|
||||
Si le premie argument de la ligne de commande ne commence pas par un
|
||||
tiret (i.e. pas d\(aqinstruction), gramps va essayer d\(aqouvrir la base de
|
||||
données avec le nom donné par le premier argument et démarrer une ses‐
|
||||
Si le premier argument de la ligne de commande ne commence pas par un
|
||||
tiret (i.e. pas d\(aqinstruction), gramps va essayer d\(aqouvrir la base de
|
||||
données avec le nom donné par le premier argument et démarrer une ses‐
|
||||
sion interactive, en ignorant le reste de la ligne de commande.
|
||||
.sp
|
||||
Si la commande \fB\-O\fP est notée, alors gramps va essayer le fichier défini
|
||||
Si la commande \fB\-O\fP est notée, alors gramps va essayer le fichier défini
|
||||
et va travailler avec ses données, comme pour les autres paramètres de
|
||||
la ligne de commande.
|
||||
.sp
|
||||
@@ -208,7 +202,7 @@ Utilisez les shell de redirection de \fIstdout\fP et \fIstderr\fP pour sauver
|
||||
les messages et les erreurs dans les fichiers.
|
||||
.TP
|
||||
.B \fBEXEMPLES\fP
|
||||
Pour ouvrir un arbre familial et y importer un fichier XML, on peut
|
||||
Pour ouvrir un arbre familial et y importer un fichier XML, on peut
|
||||
saisir:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
@@ -217,8 +211,8 @@ saisir:
|
||||
.UNINDENT
|
||||
.sp
|
||||
Ceci ouvre un arbre familial, pour faire la même chose, mais importer
|
||||
dans un arbre familial temporaire et démarrer une session interactive,
|
||||
on peut saisir:
|
||||
dans un arbre familial temporaire et démarrer une session interactive,
|
||||
on peut saisir :
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
\fBgramps \-i\fP \fI\(aqMon Arbre Familial\(aq\fP \fB\-i\fP \fI~/db3.gramps\fP
|
||||
@@ -292,22 +286,25 @@ PROFILE pour Windows 2000/XP).
|
||||
.TP
|
||||
.B \fBCONCEPTS\fP
|
||||
Gramps est un système basé sur le support de plugin\-python, permettant
|
||||
d\(aqimporter et d\(aqexporter, la saisie, générer des rapports, des outils,
|
||||
et afficher des filtres pouvant être ajoutés sans modifier le programme.
|
||||
d\(aqimporter et d\(aqexporter, la saisie, générer des rapports, des outils,
|
||||
et afficher des filtres pouvant être ajoutés sans modifier le programme.
|
||||
.sp
|
||||
Par ailleurs, gramps permet la génération directe : impression, rap‐
|
||||
ports avec sortie vers d\(aqautres formats, comme \fILibreOffice.org\fP ,
|
||||
\fIHTML\fP , ou \fILaTeX\fP pour permettre à l\(aqutilisateur de choisir selon ses
|
||||
\fIHTML\fP , ou \fILaTeX\fP pour permettre à l\(aqutilisateur de choisir selon ses
|
||||
besoins
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fBBUGS CONNUS ET LIMITATIONS\fP
|
||||
.sp
|
||||
\fBFICHIERS\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
\fI${PREFIX}/bin/gramps\fP
|
||||
.sp
|
||||
\fI${PREFIX}/share/gramps\fP
|
||||
\fI${PREFIX}/lib/python/dist\-packages/gramps/\fP
|
||||
.sp
|
||||
\fI${PREFIX}/share/\fP
|
||||
.sp
|
||||
\fI${HOME}/.gramps\fP
|
||||
.UNINDENT
|
||||
@@ -336,11 +333,10 @@ La documentation pour développeur est disponible sur le site
|
||||
\fI\%http://www.gramps-project.org/wiki/index.php?title=Portal:Developers\fP .
|
||||
.UNINDENT
|
||||
.sp
|
||||
Janvier 2013 4.0.0 gramps(1)
|
||||
gramps(1) @VERSION@ gramps(1)
|
||||
.SH AUTHOR
|
||||
Jerome Rapinat
|
||||
.SH COPYRIGHT
|
||||
2012, Gramps project
|
||||
.\" Generated by docutils manpage writer.
|
||||
.\"
|
||||
.
|
||||
|
||||
@@ -298,9 +298,11 @@ or LaTeX to allow the users to modify the format to suit their needs.
|
||||
|
||||
.SH FILES
|
||||
.LP
|
||||
\fI${PREFIX}/bin/gramps\fP
|
||||
\fI${PREFIX}/bin/gramps\fP
|
||||
.br
|
||||
\fI${PREFIX}/share/gramps\fP
|
||||
\fI${PREFIX}/lib/python/dist\-packages/gramps/\fP
|
||||
.br
|
||||
\fI${PREFIX}/share/\fP
|
||||
.br
|
||||
\fI${HOME}/.gramps\fP
|
||||
|
||||
|
||||
+4
-1
@@ -227,11 +227,14 @@ gramps(1) 3.4.0 gramps(1)
|
||||
|
||||
|
||||
**GEKENDE BUGS EN BEPERKINGEN**
|
||||
|
||||
**BESTANDEN**
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps*
|
||||
|
||||
|
||||
+3
-1
@@ -276,7 +276,9 @@ gramps(1) 3.4.0 gramps(1)
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps (jeśli nie użyta została zmienna środowiskowa GRAMP‐
|
||||
SHOME)*
|
||||
|
||||
@@ -255,9 +255,11 @@ gramps(1) 4.0.0 gramps(1)
|
||||
*ARQUIVOS**
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
|
||||
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps*
|
||||
|
||||
|
||||
|
||||
+3
-1
@@ -246,7 +246,9 @@ Gramps(1) 3.4.0 Gramps(1)
|
||||
|
||||
*${PREFIX}/bin/gramps*
|
||||
|
||||
*${PREFIX}/share/gramps*
|
||||
*${PREFIX}/lib/python/dist-packages/gramps/*
|
||||
|
||||
*${PREFIX}/share/*
|
||||
|
||||
*${HOME}/.gramps*
|
||||
|
||||
|
||||
@@ -151,6 +151,7 @@ register('behavior.surname-guessing', 0)
|
||||
register('behavior.use-tips', False)
|
||||
register('behavior.welcome', 100)
|
||||
register('behavior.web-search-url', 'http://google.com/#&q=%(text)s')
|
||||
register('behavior.addons-url', "http://svn.code.sf.net/p/gramps-addons/code/branches/gramps40/")
|
||||
|
||||
register('export.proxy-order', [
|
||||
["privacy", 0],
|
||||
@@ -278,6 +279,8 @@ register('preferences.date-format', 0)
|
||||
register('preferences.calendar-format-report', 0)
|
||||
register('preferences.cprefix', 'C%04d')
|
||||
register('preferences.default-source', False)
|
||||
register('preferences.tag-on-import', False)
|
||||
register('preferences.tag-on-import-format', _("Imported %Y/%m/%d %H:%M:%S"))
|
||||
register('preferences.eprefix', 'E%04d')
|
||||
register('preferences.family-warn', True)
|
||||
register('preferences.fprefix', 'F%04d')
|
||||
|
||||
+1
-13
@@ -89,19 +89,7 @@ APP_VCARD = ["text/x-vcard", "text/x-vcalendar"]
|
||||
# system paths
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
if sys.platform == "win32":
|
||||
if sys.prefix == os.path.dirname(os.getcwd()):
|
||||
PREFIXDIR = sys.prefix
|
||||
SYSCONFDIR = os.path.join(sys.prefix, "etc")
|
||||
else:
|
||||
PREFIXDIR = os.path.join(os.path.dirname(__file__), os.pardir)
|
||||
SYSCONFDIR = os.path.join(PREFIXDIR, "etc")
|
||||
elif sys.platform == "darwin" and sys.prefix != sys.exec_prefix:
|
||||
PREFIXDIR = sys.prefix
|
||||
SYSCONFDIR = os.path.join(sys.prefix, "etc")
|
||||
else:
|
||||
PREFIXDIR = "@prefix@"
|
||||
SYSCONFDIR = "@sysconfdir@"
|
||||
LOCALE_DIR = "@LOCALE_DIR@"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -745,6 +745,7 @@ class DbBsddbRead(DbReadBase, Callback):
|
||||
return self.get_from_handle(handle, Tag, self.tag_map)
|
||||
|
||||
def __get_obj_from_gramps_id(self, val, tbl, class_, prim_tbl):
|
||||
if isinstance(tbl, dict): return None ## trying to get object too early
|
||||
if isinstance(val, UNITYPE):
|
||||
val = val.encode('utf-8')
|
||||
try:
|
||||
|
||||
+76
-28
@@ -31,7 +31,7 @@ import logging
|
||||
LOG = logging.getLogger(".citation")
|
||||
|
||||
from ..ggettext import gettext as _
|
||||
from ..constfunc import cuni
|
||||
from ..constfunc import cuni, UNITYPE
|
||||
|
||||
"""
|
||||
methods to upgrade a database from version 13 to current version
|
||||
@@ -144,7 +144,9 @@ def gramps_upgrade_16(self):
|
||||
new_citation_list, note_list, change, tag_list,
|
||||
private, person_ref_list)
|
||||
with BSDDBTxn(self.env, self.person_map) as txn:
|
||||
txn.put(str(handle), new_person)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_person)
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d persons upgraded with %d citations in %d seconds. " %
|
||||
@@ -176,7 +178,9 @@ def gramps_upgrade_16(self):
|
||||
change, date, tag_list, private)
|
||||
LOG.debug(" upgrade new_media %s" % [new_media])
|
||||
with BSDDBTxn(self.env, self.media_map) as txn:
|
||||
txn.put(str(handle), new_media)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_media)
|
||||
LOG.debug(" update ref map media %s" % [handle,
|
||||
self.get_object_from_handle(handle) ])
|
||||
self.update()
|
||||
@@ -195,7 +199,7 @@ def gramps_upgrade_16(self):
|
||||
start_time = time.time()
|
||||
for place_handle in self.place_map.keys():
|
||||
place = self.place_map[place_handle]
|
||||
(handle, gramps_id, title, int, lat,
|
||||
(handle, gramps_id, title, longi, lat,
|
||||
main_loc, alt_loc, urls, media_list, source_list, note_list,
|
||||
change, private) = place
|
||||
if source_list:
|
||||
@@ -208,11 +212,13 @@ def gramps_upgrade_16(self):
|
||||
self, media_list)
|
||||
if source_list or media_list:
|
||||
new_place = (handle, gramps_id, title,
|
||||
int, lat, main_loc, alt_loc, urls,
|
||||
longi, lat, main_loc, alt_loc, urls,
|
||||
media_list, new_citation_list, note_list,
|
||||
change, private)
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
txn.put(str(handle), new_place)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_place)
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d places upgraded with %d citations in %d seconds. " %
|
||||
@@ -260,7 +266,9 @@ def gramps_upgrade_16(self):
|
||||
attribute_list, lds_seal_list, new_citation_list,
|
||||
note_list, change, tag_list, private)
|
||||
with BSDDBTxn(self.env, self.family_map) as txn:
|
||||
txn.put(str(handle), new_family)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_family)
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d familys upgraded with %d citations in %d seconds. " %
|
||||
@@ -300,7 +308,9 @@ def gramps_upgrade_16(self):
|
||||
attribute_list,
|
||||
change, private)
|
||||
with BSDDBTxn(self.env, self.event_map) as txn:
|
||||
txn.put(str(handle), new_event)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_event)
|
||||
t2 = time.time()
|
||||
upgrade_time += t2 - t1
|
||||
t3 = time.time()
|
||||
@@ -332,7 +342,9 @@ def gramps_upgrade_16(self):
|
||||
new_repository = (handle, gramps_id, the_type, name, note_list,
|
||||
address_list, urls, change, private)
|
||||
with BSDDBTxn(self.env, self.repository_map) as txn:
|
||||
txn.put(str(handle), new_repository)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_repository)
|
||||
self.update()
|
||||
|
||||
LOG.debug("%d repositorys upgraded with %d citations in %d seconds. " %
|
||||
@@ -535,7 +547,9 @@ def convert_source_list_to_citation_list_16(self, source_list):
|
||||
date, page, confidence, ref, note_list, new_media_list,
|
||||
new_data_map, new_change, private)
|
||||
with BSDDBTxn(self.env, self.citation_map) as txn:
|
||||
txn.put(str(new_handle), new_citation)
|
||||
if isinstance(new_handle, UNITYPE):
|
||||
new_handle = new_handle.encode('utf-8')
|
||||
txn.put(new_handle, new_citation)
|
||||
self.cmap_index += 1
|
||||
# # add backlinks for references from Citation to Source
|
||||
# with BSDDBTxn(self.env) as txn:
|
||||
@@ -621,7 +635,9 @@ def gramps_upgrade_15(self):
|
||||
)
|
||||
|
||||
with BSDDBTxn(self.env, self.person_map) as txn:
|
||||
txn.put(str(handle), new_person)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_person)
|
||||
self.update()
|
||||
#surname is now different, remove secondary index with names
|
||||
_db = db.DB(self.env)
|
||||
@@ -644,7 +660,9 @@ def gramps_upgrade_15(self):
|
||||
new_family[13] = []
|
||||
new_family = tuple(new_family)
|
||||
with BSDDBTxn(self.env, self.family_map) as txn:
|
||||
txn.put(str(handle), new_family)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_family)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -661,7 +679,9 @@ def gramps_upgrade_15(self):
|
||||
new_note[6] = []
|
||||
new_note = tuple(new_note)
|
||||
with BSDDBTxn(self.env, self.note_map) as txn:
|
||||
txn.put(str(handle), new_note)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_note)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -674,7 +694,9 @@ def gramps_upgrade_15(self):
|
||||
new_media[10] = []
|
||||
new_media = tuple(new_media)
|
||||
with BSDDBTxn(self.env, self.media_map) as txn:
|
||||
txn.put(str(handle), new_media)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_media)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -688,7 +710,9 @@ def gramps_upgrade_15(self):
|
||||
#new_event[11] = []
|
||||
new_event = tuple(new_event)
|
||||
with BSDDBTxn(self.env, self.event_map) as txn:
|
||||
txn.put(str(handle), new_event)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_event)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -704,7 +728,9 @@ def gramps_upgrade_15(self):
|
||||
new_place = new_place[:12] + new_place[13:]
|
||||
new_place = tuple(new_place)
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
txn.put(str(handle), new_place)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_place)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -717,7 +743,9 @@ def gramps_upgrade_15(self):
|
||||
new_source = new_source[:11] + new_source[12:]
|
||||
new_source = tuple(new_source)
|
||||
with BSDDBTxn(self.env, self.source_map) as txn:
|
||||
txn.put(str(handle), new_source)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_source)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -731,7 +759,9 @@ def gramps_upgrade_15(self):
|
||||
new_repository[5] = list(map(convert_address, new_repository[5]))
|
||||
new_repository = tuple(new_repository)
|
||||
with BSDDBTxn(self.env, self.repository_map) as txn:
|
||||
txn.put(str(handle), new_repository)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_repository)
|
||||
self.update()
|
||||
|
||||
# Bump up database version. Separate transaction to save metadata.
|
||||
@@ -753,6 +783,8 @@ def convert_marker(self, marker_field):
|
||||
tag.set_name(tag_name)
|
||||
tag.set_priority(len(self.tags))
|
||||
with BSDDBTxn(self.env, self.tag_map) as txn:
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, tag.serialize())
|
||||
self.tags[tag_name] = handle
|
||||
return self.tags[tag_name]
|
||||
@@ -819,7 +851,9 @@ def gramps_upgrade_14(self):
|
||||
new_note = (handle, gramps_id, styled_text, format, note_type,
|
||||
change, marker, private)
|
||||
with BSDDBTxn(self.env, self.note_map) as txn:
|
||||
txn.put(str(handle), new_note)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_note)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -839,7 +873,9 @@ def gramps_upgrade_14(self):
|
||||
description, place, new_source_list, note_list,
|
||||
new_media_list, new_attribute_list, change,marker,private)
|
||||
with BSDDBTxn(self.env, self.event_map) as txn:
|
||||
txn.put(str(handle), new_event)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_event)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -921,7 +957,9 @@ def gramps_upgrade_14(self):
|
||||
)
|
||||
|
||||
with BSDDBTxn(self.env, self.person_map) as txn:
|
||||
txn.put(str(handle), new_person)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_person)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -953,7 +991,9 @@ def gramps_upgrade_14(self):
|
||||
change, marker, private)
|
||||
|
||||
with BSDDBTxn(self.env, self.family_map) as txn:
|
||||
txn.put(str(handle), new_family)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_family)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -978,7 +1018,9 @@ def gramps_upgrade_14(self):
|
||||
new_address_list, urls, change, marker, private)
|
||||
|
||||
with BSDDBTxn(self.env, self.repository_map) as txn:
|
||||
txn.put(str(handle), new_repository)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_repository)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -996,7 +1038,9 @@ def gramps_upgrade_14(self):
|
||||
new_date, marker, private)
|
||||
|
||||
with BSDDBTxn(self.env, self.media_map) as txn:
|
||||
txn.put(str(handle), new_media)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_media)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -1004,17 +1048,19 @@ def gramps_upgrade_14(self):
|
||||
# ---------------------------------
|
||||
for place_handle in self.place_map.keys():
|
||||
place = self.place_map[place_handle]
|
||||
(handle, gramps_id, title, int, lat,
|
||||
(handle, gramps_id, title, longi, lat,
|
||||
main_loc, alt_loc, urls, media_list, source_list, note_list,
|
||||
change, marker, private) = place
|
||||
new_media_list = new_media_list_14(media_list)
|
||||
new_source_list = new_source_list_14(source_list)
|
||||
new_place = (handle, gramps_id, title, int, lat,
|
||||
new_place = (handle, gramps_id, title, longi, lat,
|
||||
main_loc, alt_loc, urls, new_media_list,
|
||||
new_source_list, note_list, change, marker, private)
|
||||
|
||||
with BSDDBTxn(self.env, self.place_map) as txn:
|
||||
txn.put(str(handle), new_place)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_place)
|
||||
self.update()
|
||||
|
||||
# ---------------------------------
|
||||
@@ -1033,7 +1079,9 @@ def gramps_upgrade_14(self):
|
||||
marker, private)
|
||||
|
||||
with BSDDBTxn(self.env, self.source_map) as txn:
|
||||
txn.put(str(handle), new_source)
|
||||
if isinstance(handle, UNITYPE):
|
||||
handle = handle.encode('utf-8')
|
||||
txn.put(handle, new_source)
|
||||
self.update()
|
||||
|
||||
# Bump up database version. Separate transaction to save metadata.
|
||||
|
||||
@@ -54,7 +54,10 @@ Specific symbols for parts of a name are defined:
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..ggettext import sgettext as _
|
||||
import sys
|
||||
import re
|
||||
import logging
|
||||
LOG = logging.getLogger(".gramps.gen")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -1047,8 +1050,17 @@ def fn(%s):
|
||||
else:
|
||||
return p + str + s
|
||||
return cleanup_name("%s" %% (%s))""" % (args, new_fmt, ",".join(param))
|
||||
exec(s)
|
||||
|
||||
return locals()['fn']
|
||||
try:
|
||||
exec(s) in globals(), locals()
|
||||
return locals()['fn']
|
||||
except:
|
||||
LOG.error("\n" + 'Wrong name format string %s' % new_fmt
|
||||
+"\n" + ("ERROR, Edit Name format in Preferences->Display to correct")
|
||||
+"\n" + _('Wrong name format string %s') % new_fmt
|
||||
+"\n" + ("ERROR, Edit Name format in Preferences->Display to correct")
|
||||
)
|
||||
def errfn(*arg):
|
||||
return _("ERROR, Edit Name format in Preferences")
|
||||
return errfn
|
||||
|
||||
displayer = NameDisplay()
|
||||
|
||||
@@ -368,7 +368,7 @@ class Gramplet(object):
|
||||
"""
|
||||
from gi.repository import GObject
|
||||
self._pause = True
|
||||
if self._idle_id == 0:
|
||||
if self._idle_id != 0:
|
||||
GObject.source_remove(self._idle_id)
|
||||
self._idle_id = 0
|
||||
|
||||
|
||||
@@ -43,14 +43,13 @@ from .. import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE, CATEGORY_WEB,
|
||||
CATEGORY_BOOK, CATEGORY_GRAPHVIZ)
|
||||
|
||||
standalone_categories = {
|
||||
CATEGORY_TEXT : _("Text Reports"),
|
||||
CATEGORY_DRAW : _("Graphical Reports"),
|
||||
CATEGORY_CODE : _("Code Generators"),
|
||||
CATEGORY_WEB : _("Web Pages"),
|
||||
CATEGORY_BOOK : _("Books"),
|
||||
CATEGORY_GRAPHVIZ : _("Graphs"),
|
||||
CATEGORY_TEXT : ("RepText", _("Text Reports")),
|
||||
CATEGORY_DRAW : ("RepGraph", _("Graphical Reports")),
|
||||
CATEGORY_CODE : ("RepCode", _("Code Generators")),
|
||||
CATEGORY_WEB : ("RepWeb", _("Web Pages")),
|
||||
CATEGORY_BOOK : ("RepBook", _("Books")),
|
||||
CATEGORY_GRAPHVIZ : ("Graphs", _("Graphs")),
|
||||
}
|
||||
|
||||
book_categories = {
|
||||
CATEGORY_TEXT : _("Text"),
|
||||
CATEGORY_DRAW : _("Graphics"),
|
||||
|
||||
@@ -35,7 +35,8 @@ from __future__ import division
|
||||
#-------------------------------------------------------------------------
|
||||
import time
|
||||
import collections
|
||||
|
||||
import logging
|
||||
_LOG = logging.getLogger(".gen")
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Callback updater
|
||||
@@ -71,6 +72,9 @@ class UpdateCallback(object):
|
||||
|
||||
def set_total(self, total):
|
||||
self.total = total
|
||||
if self.total == 0:
|
||||
_LOG.warning('UpdateCallback with total == 0 created')
|
||||
self.total = 1
|
||||
|
||||
def update_empty(self, count=None):
|
||||
pass
|
||||
|
||||
@@ -226,13 +226,25 @@ class ProbablyAlive(object):
|
||||
if mother_handle == person.handle and father_handle:
|
||||
father = self.db.get_person_from_handle(father_handle)
|
||||
date1, date2, explain, other = self.probably_alive_range(father, is_spouse=True)
|
||||
if date1 and date2:
|
||||
return date1, date2, _("a spouse, ") + explain, other
|
||||
if date1 and date1.get_year() != 0:
|
||||
return (Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP),
|
||||
Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE),
|
||||
_("a spouse's birth-related date, ") + explain, other)
|
||||
elif date2 and date2.get_year() != 0:
|
||||
return (Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP - self.MAX_AGE_PROB_ALIVE),
|
||||
Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP),
|
||||
_("a spouse's death-related date, ") + explain, other)
|
||||
elif father_handle == person.handle and mother_handle:
|
||||
mother = self.db.get_person_from_handle(mother_handle)
|
||||
date1, date2, explain, other = self.probably_alive_range(mother, is_spouse=True)
|
||||
if date1 and date2:
|
||||
return date1, date2, _("a spouse, ") + explain, other
|
||||
if date1 and date1.get_year() != 0:
|
||||
return (Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP),
|
||||
Date().copy_ymd(date1.get_year() - self.AVG_GENERATION_GAP + self.MAX_AGE_PROB_ALIVE),
|
||||
_("a spouse's birth-related date, ") + explain, other)
|
||||
elif date2 and date2.get_year() != 0:
|
||||
return (Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP - self.MAX_AGE_PROB_ALIVE),
|
||||
Date().copy_ymd(date2.get_year() + self.AVG_GENERATION_GAP),
|
||||
_("a spouse's death-related date, ") + explain, other)
|
||||
# Let's check the family events and see if we find something
|
||||
for ref in family.get_event_ref_list():
|
||||
if ref:
|
||||
|
||||
@@ -41,7 +41,7 @@ import logging
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ..const import PREFIXDIR, ROOT_DIR
|
||||
from ..const import LOCALE_DIR
|
||||
from ..constfunc import mac, UNITYPE
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -49,22 +49,16 @@ from ..constfunc import mac, UNITYPE
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
if "GRAMPSI18N" in os.environ:
|
||||
if os.path.exists(os.environ["GRAMPSI18N"]):
|
||||
LOCALEDIR = os.environ["GRAMPSI18N"]
|
||||
else:
|
||||
LOCALEDIR = None
|
||||
elif os.path.exists( os.path.join(ROOT_DIR, "lang") ):
|
||||
LOCALEDIR = os.path.join(ROOT_DIR, "lang")
|
||||
elif os.path.exists(os.path.join(PREFIXDIR, "share/locale")):
|
||||
LOCALEDIR = os.path.join(PREFIXDIR, "share/locale")
|
||||
else:
|
||||
LOCALEDIR = os.environ["GRAMPSI18N"]
|
||||
else:
|
||||
LOCALEDIR = LOCALE_DIR
|
||||
|
||||
if not os.path.exists(LOCALEDIR):
|
||||
lang = os.environ.get('LANG', 'en')
|
||||
if lang and lang[:2] == 'en':
|
||||
pass # No need to display warning, we're in English
|
||||
else:
|
||||
logging.warning('Locale dir does not exist at ' +
|
||||
os.path.join(PREFIXDIR, "share/locale"))
|
||||
logging.warning('Running python setup.py install --prefix=YourPrefixDir might fix the problem')
|
||||
logging.warning('Locale dir does not exist at ' + LOCALEDIR)
|
||||
LOCALEDIR = None
|
||||
|
||||
LOCALEDOMAIN = 'gramps'
|
||||
|
||||
+28
-2
@@ -187,6 +187,16 @@ if not sys.version_info >= MIN_PYTHON_VERSION :
|
||||
'v3': MIN_PYTHON_VERSION[2]})
|
||||
sys.exit(1)
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
#check if bsddb3 is installed
|
||||
try:
|
||||
import bsddb3
|
||||
except ImportError:
|
||||
logging.warning(_("\nYou don't have the python bsddb3 package installed."
|
||||
" This package is needed to start Gramps.\n\n"
|
||||
"Gramps will terminate now."))
|
||||
sys.exit(1)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# gramps libraries
|
||||
@@ -236,14 +246,27 @@ def show_settings():
|
||||
except ImportError:
|
||||
gobjectver_str = 'not found'
|
||||
|
||||
try:
|
||||
from gi.repository import Pango
|
||||
try:
|
||||
pangover_str = Pango.version_string()
|
||||
except :# any failure to 'get' the version
|
||||
pangover_str = 'unknown version'
|
||||
|
||||
except ImportError:
|
||||
pangover_str = 'not found'
|
||||
|
||||
try:
|
||||
import cairo
|
||||
try:
|
||||
cairover_str = '%d.%d.%d' % cairo.version_info
|
||||
pycairover_str = '%d.%d.%d' % cairo.version_info
|
||||
cairover_str = cairo.cairo_version_string()
|
||||
except :# any failure to 'get' the version
|
||||
pycairover_str = 'unknown version'
|
||||
cairover_str = 'unknown version'
|
||||
|
||||
except ImportError:
|
||||
pycairover_str = 'not found'
|
||||
cairover_str = 'not found'
|
||||
|
||||
try:
|
||||
@@ -279,7 +302,8 @@ def show_settings():
|
||||
else:
|
||||
import bsddb
|
||||
bsddb_str = bsddb.__version__
|
||||
bsddb_db_str = str(bsddb.db.version())
|
||||
bsddb_db_str = str(bsddb.db.version()).replace(', ', '.')\
|
||||
.replace('(', '').replace(')', '')
|
||||
except:
|
||||
bsddb_str = 'not found'
|
||||
bsddb_db_str = 'not found'
|
||||
@@ -327,6 +351,7 @@ def show_settings():
|
||||
print (' gramps : %s' % gramps_str)
|
||||
print (' gtk++ : %s' % gtkver_str)
|
||||
print (' gobject : %s' % gobjectver_str)
|
||||
print (' pango : %s' % pangover_str)
|
||||
if usebsddb3:
|
||||
print (' Using bsddb3')
|
||||
else:
|
||||
@@ -334,6 +359,7 @@ def show_settings():
|
||||
print (' bsddb : %s' % bsddb_str)
|
||||
print (' bsddb.db : %s' % bsddb_db_str)
|
||||
print (' cairo : %s' % cairover_str)
|
||||
print (' pycairo : %s' % pycairover_str)
|
||||
print (' osmgpsmap : %s' % osmgpsmap_str)
|
||||
print (' pyexiv2 : %s' % pyexiv2_str)
|
||||
print (' o.s. : %s' % operating_system)
|
||||
|
||||
+16
-5
@@ -1163,7 +1163,10 @@ class ClipboardListView(object):
|
||||
def object_drag_data_get(self, widget, context, sel_data, info, time):
|
||||
tree_selection = widget.get_selection()
|
||||
model, paths = tree_selection.get_selected_rows()
|
||||
tgs = context.list_targets()
|
||||
if hasattr(context, "targets"):
|
||||
tgs = context.targets
|
||||
else:
|
||||
tgs = context.list_targets()
|
||||
if len(paths) == 1:
|
||||
path = paths[0]
|
||||
node = model.get_iter(path)
|
||||
@@ -1181,7 +1184,10 @@ class ClipboardListView(object):
|
||||
time, title=None, value=None, dbid=None,
|
||||
dbname=None):
|
||||
model = widget.get_model()
|
||||
sel_data = selection.get_data()
|
||||
if hasattr(selection, "data"):
|
||||
sel_data = selection.data
|
||||
else:
|
||||
sel_data = selection.get_data() # GtkSelectionData
|
||||
# In Windows time is always zero. Until that is fixed, use the seconds
|
||||
# of the local time to filter out double drops.
|
||||
realTime = strftime("%S")
|
||||
@@ -1212,7 +1218,10 @@ class ClipboardListView(object):
|
||||
if dragtype in self._target_type_to_wrapper_class_map:
|
||||
possible_wrappers = [dragtype]
|
||||
else:
|
||||
tgs = [atm.name() for atm in context.list_targets()]
|
||||
if hasattr(context, "targets"):
|
||||
tgs = context.targets
|
||||
else:
|
||||
tgs = [atm.name() for atm in context.list_targets()]
|
||||
possible_wrappers = [target for target in tgs
|
||||
if target in self._target_type_to_wrapper_class_map]
|
||||
|
||||
@@ -1246,7 +1255,8 @@ class ClipboardListView(object):
|
||||
data = [o.__class__.DRAG_TARGET.drag_type, o, None,
|
||||
o._type, o._value, o._dbid, o._dbname]
|
||||
contains = model_contains(model, data)
|
||||
if context.get_actions() != Gdk.DragAction.MOVE and contains:
|
||||
if ((context.action if hasattr(context, "action") else context.get_actions())
|
||||
!= Gdk.DragAction.MOVE) and contains:
|
||||
continue
|
||||
drop_info = widget.get_dest_row_at_pos(x, y)
|
||||
if drop_info:
|
||||
@@ -1263,7 +1273,8 @@ class ClipboardListView(object):
|
||||
# FIXME: there is one bug here: if you multi-select and drop
|
||||
# on self, then it moves the first, and copies the rest.
|
||||
|
||||
if context.get_actions() == Gdk.DragAction.MOVE:
|
||||
if ((context.action if hasattr(context, "action") else context.get_actions()) ==
|
||||
Gdk.DragAction.MOVE):
|
||||
context.finish(True, True, time)
|
||||
|
||||
# remember time for double drop workaround.
|
||||
|
||||
+57
-19
@@ -5,6 +5,7 @@
|
||||
# Copyright (C) 2008 Raphael Ackermann
|
||||
# Copyright (C) 2010 Benny Malengier
|
||||
# Copyright (C) 2010 Nick Hall
|
||||
# Copyright (C) 2012 Doug Blank <doug.blank@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
|
||||
@@ -321,18 +322,23 @@ class ConfigureDialog(ManagedWindow):
|
||||
table.attach(hbox, 2, 3, index, index+1, yoptions=0)
|
||||
|
||||
def add_entry(self, table, label, index, constant, callback=None,
|
||||
config=None):
|
||||
config=None, col_attach=0):
|
||||
if not config:
|
||||
config = self.__config
|
||||
if not callback:
|
||||
callback = self.update_entry
|
||||
lwidget = BasicLabel("%s: " % label)
|
||||
if label:
|
||||
lwidget = BasicLabel("%s: " % label)
|
||||
entry = Gtk.Entry()
|
||||
entry.set_text(config.get(constant))
|
||||
entry.connect('changed', callback, constant)
|
||||
table.attach(lwidget, 0, 1, index, index+1, yoptions=0,
|
||||
xoptions=Gtk.AttachOptions.FILL)
|
||||
table.attach(entry, 1, 2, index, index+1, yoptions=0)
|
||||
if label:
|
||||
table.attach(lwidget, col_attach, col_attach+1, index, index+1, yoptions=0,
|
||||
xoptions=Gtk.AttachOptions.FILL)
|
||||
table.attach(entry, col_attach+1, col_attach+2, index, index+1, yoptions=0)
|
||||
else:
|
||||
table.attach(entry, col_attach, col_attach+1, index, index+1, yoptions=0)
|
||||
return entry
|
||||
|
||||
def add_pos_int_entry(self, table, label, index, constant, callback=None,
|
||||
config=None, col_attach=1):
|
||||
@@ -1100,6 +1106,11 @@ class GrampsPreferences(ConfigureDialog):
|
||||
config.set('behavior.do-not-show-previously-seen-updates',
|
||||
bool(active))
|
||||
|
||||
def toggle_tag_on_import(self, obj):
|
||||
active = obj.get_active()
|
||||
config.set('preferences.tag-on-import', bool(active))
|
||||
self.tag_format_entry.set_sensitive(bool(active))
|
||||
|
||||
def check_for_updates_changed(self, obj):
|
||||
active = obj.get_active()
|
||||
config.set('behavior.check-for-updates', active)
|
||||
@@ -1147,32 +1158,54 @@ class GrampsPreferences(ConfigureDialog):
|
||||
return _('Dates'), table
|
||||
|
||||
def add_behavior_panel(self, configdialog):
|
||||
table = Gtk.Table(3, 6)
|
||||
table = Gtk.Table(2, 8)
|
||||
table.set_border_width(12)
|
||||
table.set_col_spacings(6)
|
||||
table.set_row_spacings(6)
|
||||
|
||||
current_line = 0
|
||||
self.add_checkbox(table,
|
||||
_('Add default source on import'),
|
||||
0, 'preferences.default-source')
|
||||
_('Add default source on GEDCOM import'),
|
||||
current_line, 'preferences.default-source')
|
||||
|
||||
current_line += 1
|
||||
checkbutton = Gtk.CheckButton(_("Add tag on import"))
|
||||
checkbutton.set_active(config.get('preferences.tag-on-import'))
|
||||
checkbutton.connect("toggled", self.toggle_tag_on_import)
|
||||
table.attach(checkbutton, 1, 2, current_line, current_line+1, yoptions=0)
|
||||
self.tag_format_entry = self.add_entry(table, None, current_line,
|
||||
'preferences.tag-on-import-format',
|
||||
col_attach=2)
|
||||
self.tag_format_entry.set_sensitive(config.get('preferences.tag-on-import'))
|
||||
|
||||
current_line += 1
|
||||
self.add_checkbox(table,
|
||||
_('Enable spelling checker'),
|
||||
1, 'behavior.spellcheck')
|
||||
current_line, 'behavior.spellcheck')
|
||||
|
||||
current_line += 1
|
||||
self.add_checkbox(table,
|
||||
_('Display Tip of the Day'),
|
||||
2, 'behavior.use-tips')
|
||||
current_line, 'behavior.use-tips')
|
||||
|
||||
current_line += 1
|
||||
self.add_checkbox(table,
|
||||
_('Remember last view displayed'),
|
||||
3, 'preferences.use-last-view')
|
||||
current_line, 'preferences.use-last-view')
|
||||
|
||||
current_line += 1
|
||||
self.add_spinner(table,
|
||||
_('Max generations for relationships'),
|
||||
4, 'behavior.generation-depth', (5, 50), self.update_gendepth)
|
||||
current_line, 'behavior.generation-depth', (5, 50), self.update_gendepth)
|
||||
|
||||
current_line += 1
|
||||
self.path_entry = Gtk.Entry()
|
||||
self.add_path_box(table,
|
||||
_('Base path for relative media paths'),
|
||||
5, self.path_entry, self.dbstate.db.get_mediapath(),
|
||||
current_line, self.path_entry, self.dbstate.db.get_mediapath(),
|
||||
self.set_mediapath, self.select_mediapath)
|
||||
|
||||
current_line += 1
|
||||
# Check for updates:
|
||||
obox = Gtk.ComboBoxText()
|
||||
formats = [_("Never"),
|
||||
@@ -1185,9 +1218,10 @@ class GrampsPreferences(ConfigureDialog):
|
||||
obox.set_active(active)
|
||||
obox.connect('changed', self.check_for_updates_changed)
|
||||
lwidget = BasicLabel("%s: " % _('Check for updates'))
|
||||
table.attach(lwidget, 1, 2, 6, 7, yoptions=0)
|
||||
table.attach(obox, 2, 3, 6, 7, yoptions=0)
|
||||
table.attach(lwidget, 1, 2, current_line, current_line+1, yoptions=0)
|
||||
table.attach(obox, 2, 3, current_line, current_line+1, yoptions=0)
|
||||
|
||||
current_line += 1
|
||||
self.whattype_box = Gtk.ComboBoxText()
|
||||
formats = [_("Updated addons only"),
|
||||
_("New addons only"),
|
||||
@@ -1202,19 +1236,23 @@ class GrampsPreferences(ConfigureDialog):
|
||||
self.whattype_box.set_active(0)
|
||||
self.whattype_box.connect('changed', self.check_for_type_changed)
|
||||
lwidget = BasicLabel("%s: " % _('What to check'))
|
||||
table.attach(lwidget, 1, 2, 7, 8, yoptions=0)
|
||||
table.attach(self.whattype_box, 2, 3, 7, 8, yoptions=0)
|
||||
table.attach(lwidget, 1, 2, current_line, current_line+1, yoptions=0)
|
||||
table.attach(self.whattype_box, 2, 3, current_line, current_line+1, yoptions=0)
|
||||
|
||||
current_line += 1
|
||||
self.add_entry(table, _('Where to check'), current_line, 'behavior.addons-url', col_attach=1)
|
||||
|
||||
current_line += 1
|
||||
checkbutton = Gtk.CheckButton(
|
||||
_("Do not ask about previously notified addons"))
|
||||
checkbutton.set_active(config.get('behavior.do-not-show-previously-seen-updates'))
|
||||
checkbutton.connect("toggled", self.toggle_hide_previous_addons)
|
||||
|
||||
table.attach(checkbutton, 0, 3, 8, 9, yoptions=0)
|
||||
table.attach(checkbutton, 0, 3, current_line, current_line+1, yoptions=0)
|
||||
button = Gtk.Button(_("Check now"))
|
||||
button.connect("clicked", lambda obj: \
|
||||
self.uistate.viewmanager.check_for_updates(force=True))
|
||||
table.attach(button, 3, 4, 8, 9, yoptions=0)
|
||||
table.attach(button, 3, 4, current_line, current_line+1, yoptions=0)
|
||||
|
||||
return _('General'), table
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ class EmbeddedList(ButtonTab):
|
||||
self.build_model = build_model
|
||||
|
||||
# handle the selection
|
||||
self.tree.set_hover_selection(True)
|
||||
self.selection = self.tree.get_selection()
|
||||
self.selection.connect('changed', self._selection_changed)
|
||||
self.track_ref_for_deletion("selection")
|
||||
@@ -104,13 +105,24 @@ class EmbeddedList(ButtonTab):
|
||||
Handle button press, not double-click, that is done in init_interface
|
||||
"""
|
||||
if is_right_click(event):
|
||||
ref = self.get_selected()
|
||||
if ref:
|
||||
self.right_click(obj, event)
|
||||
#ref = self.get_selected()
|
||||
#if ref:
|
||||
self.right_click(obj, event)
|
||||
return True
|
||||
elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 2:
|
||||
fun = self.get_middle_click()
|
||||
if fun:
|
||||
fun()
|
||||
return True
|
||||
elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 1:
|
||||
if self.tree.get_hover_selection():
|
||||
self.tree.set_hover_selection(False)
|
||||
return True
|
||||
else:
|
||||
self.tree.set_hover_selection(True)
|
||||
#let code for single click still select the current row:
|
||||
return False
|
||||
return False
|
||||
|
||||
def get_popup_menu_items(self):
|
||||
"""
|
||||
@@ -146,20 +158,18 @@ class EmbeddedList(ButtonTab):
|
||||
On right click show a popup menu.
|
||||
This is populated with get_popup_menu_items
|
||||
"""
|
||||
menu = Gtk.Menu()
|
||||
self.__store_menu = Gtk.Menu() #need to keep reference or menu disappears
|
||||
menu = self.__store_menu
|
||||
for (needs_write_access, image, title, func) in self.get_popup_menu_items():
|
||||
if image:
|
||||
if isinstance(title, tuple):
|
||||
img_stock, txt = title
|
||||
item = Gtk.ImageMenuItem(txt)
|
||||
item = Gtk.ImageMenuItem.new_with_label(txt)
|
||||
img = Gtk.Image()
|
||||
img.set_from_stock(img_stock, Gtk.IconSize.MENU)
|
||||
item.set_image(img)
|
||||
else:
|
||||
item = Gtk.ImageMenuItem('')
|
||||
img = Gtk.Image()
|
||||
img.set_from_stock(title, Gtk.IconSize.MENU)
|
||||
item.set_image(img)
|
||||
item = Gtk.ImageMenuItem.new_from_stock(title, None)
|
||||
else:
|
||||
item = Gtk.MenuItem(label=title)
|
||||
item.connect('activate', func)
|
||||
|
||||
@@ -219,7 +219,7 @@ class GalleryTab(ButtonTab, DbGUIElement):
|
||||
self.iconlist.set_selection_mode(Gtk.SelectionMode.SINGLE)
|
||||
|
||||
# connect the signals
|
||||
self.iconlist.connect('selection-changed', self._selection_changed)
|
||||
self.__id_connect_sel = self.iconlist.connect('selection-changed', self._selection_changed)
|
||||
self.iconlist.connect('button_press_event', self.double_click)
|
||||
self.iconlist.connect('key_press_event', self.key_pressed)
|
||||
self._connect_icon_model()
|
||||
@@ -563,3 +563,7 @@ class GalleryTab(ButtonTab, DbGUIElement):
|
||||
returns the index of the object within the associated data
|
||||
"""
|
||||
return self.get_data().index(obj)
|
||||
|
||||
def clean_up(self):
|
||||
self.iconlist.disconnect(self.__id_connect_sel)
|
||||
super(ButtonTab, self).clean_up()
|
||||
|
||||
@@ -113,10 +113,21 @@ class GroupEmbeddedList(EmbeddedList):
|
||||
if obj and obj[1]:
|
||||
self._tmpgroup = obj[0]
|
||||
self.right_click(obj[1], event)
|
||||
return True
|
||||
elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 2:
|
||||
fun = self.get_middle_click()
|
||||
if fun:
|
||||
fun()
|
||||
return True
|
||||
elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 1:
|
||||
if self.tree.get_hover_selection():
|
||||
self.tree.set_hover_selection(False)
|
||||
return True
|
||||
else:
|
||||
self.tree.set_hover_selection(True)
|
||||
#let code for single click still select the current row:
|
||||
return False
|
||||
return False
|
||||
|
||||
def is_empty(self):
|
||||
"""
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<object class="GtkBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||
@@ -22,11 +23,9 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="cancel">
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -39,11 +38,9 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="apply">
|
||||
<property name="label" translatable="yes">Install Selected _Addons</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -88,8 +85,8 @@
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
@@ -101,11 +98,9 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="select_all">
|
||||
<property name="label" translatable="yes">_Select All</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -117,11 +112,9 @@
|
||||
<child>
|
||||
<object class="GtkButton" id="select_none">
|
||||
<property name="label" translatable="yes">Select _None</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
@@ -160,7 +153,7 @@
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">2</property>
|
||||
|
||||
@@ -51,7 +51,14 @@ except (ImportError, ValueError):
|
||||
"pygobject version 3.3.2 or later.\n\n"
|
||||
"Gramps will terminate now.")))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
try:
|
||||
import cairo
|
||||
except ImportError:
|
||||
print((_("\ncairo python support not installed. Install cairo for your "
|
||||
"version of python\n\n"
|
||||
"Gramps will terminate now.")))
|
||||
sys.exit(0)
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Miscellaneous initialization
|
||||
|
||||
@@ -216,7 +216,7 @@ class PluginDialog(ManagedWindow):
|
||||
for key in key_list:
|
||||
data = item_hash[key]
|
||||
node = self.store.insert_after(None, prev)
|
||||
self.store.set(node, 0, key)
|
||||
self.store.set(node, 0, key[1])
|
||||
next = None
|
||||
data.sort(key=lambda k:k.name)
|
||||
for item in data:
|
||||
|
||||
@@ -483,7 +483,8 @@ class PluginStatus(ManagedWindow):
|
||||
'<span weight="bold" color="red">%s</span>' % _('Fail'),
|
||||
i[0], str(i[1][1]), i[1], pdata.id, hiddenstr])
|
||||
|
||||
success_list = sorted(self.__pmgr.get_success_list())
|
||||
success_list = sorted(self.__pmgr.get_success_list(),
|
||||
key=lambda x: (x[0], x[2]._get_name()))
|
||||
for i in success_list:
|
||||
# i = (filename, module, pdata)
|
||||
pdata = i[2]
|
||||
|
||||
@@ -205,7 +205,7 @@ class ReportDialog(ManagedWindow):
|
||||
def get_title(self):
|
||||
"""The window title for this dialog"""
|
||||
name = self.report_name
|
||||
category = standalone_categories[self.category]
|
||||
category = standalone_categories[self.category][1]
|
||||
return "%s - %s - Gramps" % (name, category)
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
@@ -644,7 +644,6 @@ def report(dbstate, uistate, person, report_class, options_class,
|
||||
task be in the format of task that takes a database and a person as
|
||||
its arguments.
|
||||
"""
|
||||
|
||||
if require_active and not person:
|
||||
ErrorDialog(
|
||||
_('Active person has not been set'),
|
||||
|
||||
@@ -55,14 +55,13 @@ from gramps.gen.plug import (TOOL_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX,
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
tool_categories = {
|
||||
TOOL_DEBUG : _("Debug"),
|
||||
TOOL_ANAL : _("Analysis and Exploration"),
|
||||
TOOL_DBPROC : _("Family Tree Processing"),
|
||||
TOOL_DBFIX : _("Family Tree Repair"),
|
||||
TOOL_REVCTL : _("Revision Control"),
|
||||
TOOL_UTILS : _("Utilities"),
|
||||
TOOL_DEBUG : ("ToolDebug", _("Debug")),
|
||||
TOOL_ANAL : ("ToolAnExp", _("Analysis and Exploration")),
|
||||
TOOL_DBPROC : ("ToolProc", _("Family Tree Processing")),
|
||||
TOOL_DBFIX : ("ToolRep", _("Family Tree Repair")),
|
||||
TOOL_REVCTL : ("ToolRev", _("Revision Control")),
|
||||
TOOL_UTILS : ("ToolUtil", _("Utilities")),
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Tool
|
||||
|
||||
@@ -121,7 +121,7 @@ class UndoHistory(ManagedWindow):
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node or len(self.model) == 1:
|
||||
return
|
||||
path = self.model.get_path(node)
|
||||
path = self.model.get_path(node).get_indices()
|
||||
start = min(path[0], self.undodb.undo_count)
|
||||
end = max(path[0], self.undodb.undo_count)
|
||||
|
||||
@@ -158,7 +158,7 @@ class UndoHistory(ManagedWindow):
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node:
|
||||
return
|
||||
path = self.model.get_path(node)
|
||||
path = self.model.get_path(node).get_indices()
|
||||
nsteps = path[0] - self.undodb.undo_count - 1
|
||||
self._move(nsteps or -1)
|
||||
|
||||
@@ -167,7 +167,7 @@ class UndoHistory(ManagedWindow):
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node:
|
||||
return
|
||||
path = self.model.get_path(node)
|
||||
path = self.model.get_path(node).get_indices()
|
||||
nsteps = path[0] - self.undodb.undo_count
|
||||
self._move(nsteps or 1)
|
||||
|
||||
|
||||
+21
-13
@@ -7,6 +7,7 @@
|
||||
# Copyright (C) 2010 Nick Hall
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2012 Gary Burton
|
||||
# Copyright (C) 2012 Doug Blank <doug.blank@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
|
||||
@@ -119,7 +120,7 @@ if is_quartz():
|
||||
else:
|
||||
_GTKOSXAPPLICATION = False
|
||||
|
||||
_UNSUPPORTED = _("Unsupported")
|
||||
_UNSUPPORTED = ("Unsupported", _("Unsupported"))
|
||||
|
||||
UIDEFAULT = '''<ui>
|
||||
<menubar name="MenuBar">
|
||||
@@ -237,7 +238,6 @@ UIDEFAULT = '''<ui>
|
||||
WIKI_HELP_PAGE_FAQ = '%s_-_FAQ' % URL_MANUAL_PAGE
|
||||
WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % URL_MANUAL_PAGE
|
||||
WIKI_HELP_PAGE_MAN = '%s' % URL_MANUAL_PAGE
|
||||
ADDONS_URL = "http://gramps-addons.svn.sourceforge.net/viewvc/gramps-addons/trunk"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -250,7 +250,7 @@ def update_rows(model, path, iter, user_data):
|
||||
"""
|
||||
#path: (8,) iter: <GtkTreeIter at 0xbfa89fa0>
|
||||
#path: (8, 0) iter: <GtkTreeIter at 0xbfa89f60>
|
||||
if len(path) == 2:
|
||||
if len(path.get_indices()) == 2:
|
||||
row = model[path]
|
||||
row[0] = user_data
|
||||
model.row_changed(path, iter)
|
||||
@@ -383,10 +383,10 @@ class ViewManager(CLIManager):
|
||||
# now we have a list of languages to try:
|
||||
fp = None
|
||||
for lang in langs:
|
||||
URL = "%s/listings/addons-%s.txt" % (ADDONS_URL, lang)
|
||||
URL = "%s/listings/addons-%s.txt" % (config.get("behavior.addons-url"), lang)
|
||||
LOG.debug(" trying: %s" % URL)
|
||||
try:
|
||||
fp = urlopen(URL)
|
||||
fp = urlopen(URL, timeout=10) # abort after 10 seconds
|
||||
except: # some error
|
||||
LOG.debug(" IOError!")
|
||||
fp = None
|
||||
@@ -420,7 +420,7 @@ class ViewManager(CLIManager):
|
||||
plugin_dict["i"] not in config.get('behavior.previously-seen-updates')):
|
||||
addon_update_list.append((_("Updated"),
|
||||
"%s/download/%s" %
|
||||
(ADDONS_URL,
|
||||
(config.get("behavior.addons-url"),
|
||||
plugin_dict["z"]),
|
||||
plugin_dict))
|
||||
else:
|
||||
@@ -432,14 +432,22 @@ class ViewManager(CLIManager):
|
||||
plugin_dict["i"] not in config.get('behavior.previously-seen-updates')):
|
||||
addon_update_list.append((_("New"),
|
||||
"%s/download/%s" %
|
||||
(ADDONS_URL,
|
||||
(config.get("behavior.addons-url"),
|
||||
plugin_dict["z"]),
|
||||
plugin_dict))
|
||||
config.set("behavior.last-check-for-updates",
|
||||
datetime.date.today().strftime("%Y/%m/%d"))
|
||||
count += 1
|
||||
if fp:
|
||||
fp.close()
|
||||
if fp:
|
||||
fp.close()
|
||||
else:
|
||||
from .dialog import OkDialog
|
||||
OkDialog(_("Checking Addons Failed"),
|
||||
_("The addon repository appears to be unavailable. Please try again later."),
|
||||
self.window)
|
||||
if fp:
|
||||
fp.close()
|
||||
return
|
||||
LOG.debug("Done checking!")
|
||||
# List of translated strings used here
|
||||
# Dead code for l10n
|
||||
@@ -1796,9 +1804,9 @@ class ViewManager(CLIManager):
|
||||
if item != _UNSUPPORTED)
|
||||
|
||||
for key in catlist:
|
||||
new_key = key.replace(' ', '-')
|
||||
new_key = key[0].replace(' ', '-')
|
||||
ofile.write('<menu action="%s">' % new_key)
|
||||
actions.append((new_key, None, key))
|
||||
actions.append((new_key, None, key[1]))
|
||||
pdatas = hash_data[key]
|
||||
pdatas.sort(key=lambda x: x.name)
|
||||
for pdata in pdatas:
|
||||
@@ -1813,8 +1821,8 @@ class ViewManager(CLIManager):
|
||||
# and the unsupported category at the end of the menu
|
||||
if _UNSUPPORTED in hash_data:
|
||||
ofile.write('<separator/>')
|
||||
ofile.write('<menu action="%s">' % _UNSUPPORTED)
|
||||
actions.append((_UNSUPPORTED, None, _UNSUPPORTED))
|
||||
ofile.write('<menu action="%s">' % _UNSUPPORTED[0])
|
||||
actions.append((_UNSUPPORTED[0], None, _UNSUPPORTED[1]))
|
||||
pdatas = hash_data[_UNSUPPORTED]
|
||||
pdatas.sort(key=lambda x: x.name)
|
||||
for pdata in pdatas:
|
||||
|
||||
@@ -620,11 +620,16 @@ class ListView(NavigationView):
|
||||
filter_info = (False, value, value[0] in self.exact_search())
|
||||
|
||||
if same_col:
|
||||
##TODO GTK3 rows_reordered not exposed by gi, we need to reconnect
|
||||
## model to obtain desired effect, but this collapses nodes ...
|
||||
self.list.set_model(None)
|
||||
self.model.reverse_order()
|
||||
self.list.set_model(self.model)
|
||||
# activate when https://bugzilla.gnome.org/show_bug.cgi?id=684558
|
||||
# is resolved
|
||||
if False and (Gtk.get_major_version(), Gtk.get_minor_version()) >= (3,8):
|
||||
self.model.reverse_order()
|
||||
else:
|
||||
## GTK 3.6 rows_reordered not exposed by gi, we need to reconnect
|
||||
## model to obtain desired effect, but this collapses nodes ...
|
||||
self.list.set_model(None)
|
||||
self.model.reverse_order()
|
||||
self.list.set_model(self.model)
|
||||
else:
|
||||
self.model = self.make_model(self.dbstate.db, self.sort_col,
|
||||
self.sort_order,
|
||||
|
||||
@@ -146,10 +146,11 @@ class NoteModel(FlatBaseModel):
|
||||
tag_priority = None
|
||||
for handle in data[Note.POS_TAGS]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
this_priority = tag.get_priority()
|
||||
if tag_priority is None or this_priority < tag_priority:
|
||||
tag_color = tag.get_color()
|
||||
tag_priority = this_priority
|
||||
if tag:
|
||||
this_priority = tag.get_priority()
|
||||
if tag_priority is None or this_priority < tag_priority:
|
||||
tag_color = tag.get_color()
|
||||
tag_priority = this_priority
|
||||
return tag_color
|
||||
|
||||
def column_tags(self, data):
|
||||
|
||||
@@ -699,10 +699,11 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
|
||||
def reverse_order(self):
|
||||
"""
|
||||
Reverse the order of the map. This does not signal rows_reordered,
|
||||
so to propagate the change to the view, you need to reattach the
|
||||
model to the view.
|
||||
Reverse the order of the map. Only for Gtk 3.9+ does this signal
|
||||
rows_reordered, so to propagate the change to the view, you need to
|
||||
reattach the model to the view.
|
||||
"""
|
||||
self.GTK38PLUS = (Gtk.get_major_version(), Gtk.get_minor_version()) >= (3,8)
|
||||
self.__reverse = not self.__reverse
|
||||
top_node = self.tree[None]
|
||||
self._reverse_level(top_node)
|
||||
@@ -722,8 +723,11 @@ class TreeBaseModel(GObject.Object, Gtk.TreeModel):
|
||||
else:
|
||||
iternode = self.get_iter(node)
|
||||
path = self.do_get_path(iternode)
|
||||
##TODO GTK3: rows_reordered is not exposed in gi
|
||||
#self.rows_reordered(path, iter, rows)
|
||||
# activate when https://bugzilla.gnome.org/show_bug.cgi?id=684558
|
||||
# is resolved
|
||||
if False and self.GTK38PLUS:
|
||||
##rows_reordered is only exposed in gi starting GTK 3.8
|
||||
self.rows_reordered(path, iter, rows)
|
||||
if self.nrgroups > 1:
|
||||
for child in node.children:
|
||||
self._reverse_level(self.nodemap.node(child[1]))
|
||||
|
||||
@@ -432,12 +432,12 @@ class _GtkProgressBar(Gtk.VBox):
|
||||
self._cancel.connect("clicked",
|
||||
lambda x: long_op_status.cancel())
|
||||
self._cancel.show()
|
||||
self._hbox.pack_end(self._cancel, expand=False, fill=True, padding=0)
|
||||
self._hbox.pack_end(self._cancel, False, True, 0)
|
||||
|
||||
self._hbox.pack_start(self._pbar, True, True, 0)
|
||||
|
||||
self.pack_start(self._lbl, expand=False, fill=False)
|
||||
self.pack_start(self._hbox, expand=False, fill=False)
|
||||
self.pack_start(self._lbl, False, False, 0)
|
||||
self.pack_start(self._hbox, False, False, 0)
|
||||
|
||||
|
||||
self._pbar_max = (long_op_status.get_total_steps()/
|
||||
@@ -483,7 +483,18 @@ class GtkProgressDialog(Gtk.Dialog):
|
||||
""":param title: The title to display on the top of the window.
|
||||
:type title: string
|
||||
"""
|
||||
GObject.GObject.__init__(self, *window_params)
|
||||
#GObject.GObject.__init__(self, *window_params)
|
||||
GObject.GObject.__init__(self)
|
||||
if len(window_params) >= 2:
|
||||
self.set_transient_for(window_params[1])
|
||||
if len(window_params) >= 3:
|
||||
flags = window_params[2]
|
||||
if Gtk.DialogFlags.MODAL & flags:
|
||||
self.set_modal(True)
|
||||
if Gtk.DialogFlags.DESTROY_WITH_PARENT & flags:
|
||||
self.set_destroy_with_parent(True)
|
||||
if len(window_params) >= 4:
|
||||
self.add_buttons(window_params[3:])
|
||||
self.connect('delete_event', self._warn)
|
||||
self.set_title(title)
|
||||
#self.set_resize_mode(Gtk.RESIZE_IMMEDIATE)
|
||||
@@ -502,7 +513,7 @@ class GtkProgressDialog(Gtk.Dialog):
|
||||
"""
|
||||
pbar = _GtkProgressBar(long_op_status)
|
||||
|
||||
self.vbox.pack_start(pbar, expand=False, fill=False)
|
||||
self.vbox.pack_start(pbar, False, False, 0)
|
||||
|
||||
pbar.show()
|
||||
# this seems to cause an infinite loop:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2007-2008 Zsolt Foldvari
|
||||
# Copyright (C) 2012 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
|
||||
@@ -135,8 +136,12 @@ class FadeOut(GObject.GObject):
|
||||
return
|
||||
|
||||
##_LOG.debug('_start_merging: Starting')
|
||||
func = self._merge_colors(self._start_color,
|
||||
Gdk.color_parse(self.ERROR_COLOR)).next
|
||||
generator = self._merge_colors(self._start_color,
|
||||
Gdk.color_parse(self.ERROR_COLOR))
|
||||
if sys.version_info[0] < 3:
|
||||
func = generator.next
|
||||
else:
|
||||
func = generator.__next__
|
||||
self._background_timeout_id = (
|
||||
GObject.timeout_add(FadeOut.MERGE_COLORS_DELAY, func))
|
||||
self._countdown_timeout_id = -1
|
||||
@@ -173,444 +178,9 @@ class FadeOut(GObject.GObject):
|
||||
GObject.source_remove(self._countdown_timeout_id)
|
||||
self._countdown_timeout_id = -1
|
||||
|
||||
self._widget.update_background(self._start_color)
|
||||
self._widget.update_background(self._start_color, unset=True)
|
||||
self._done = False
|
||||
|
||||
class Tooltip(Gtk.Window):
|
||||
"""Tooltip for the Icon in the MaskedEntry"""
|
||||
|
||||
DEFAULT_DELAY = 500
|
||||
BORDER_WIDTH = 4
|
||||
|
||||
def __init__(self, widget):
|
||||
GObject.GObject.__init__(self, type=Gtk.WindowType.POPUP)
|
||||
# from gtktooltips.c:gtk_tooltips_force_window
|
||||
self.set_app_paintable(True)
|
||||
self.set_resizable(False)
|
||||
self.set_name("gtk-tooltips")
|
||||
self.set_border_width(Tooltip.BORDER_WIDTH)
|
||||
#TODO GTK3: this signal no longer exists. Convert to draw
|
||||
self.connect('draw', self._on__draw_event)
|
||||
|
||||
self._label = Gtk.Label()
|
||||
self.add(self._label)
|
||||
self._show_timeout_id = -1
|
||||
|
||||
# from gtktooltips.c:gtk_tooltips_draw_tips
|
||||
def _calculate_pos(self, widget):
|
||||
screen = widget.get_screen()
|
||||
|
||||
greq = Gtk.Requisition()
|
||||
greq = self.size_request()
|
||||
w = greq.width
|
||||
h = greq.height
|
||||
|
||||
_, x, y = widget.get_window().get_origin()
|
||||
|
||||
# TODO GTK3 No longer WidgetFlags!
|
||||
#if widget.get_state_flags() & Gtk.WidgetFlags.NO_WINDOW:
|
||||
x += widget.get_allocation().width
|
||||
y += widget.get_allocation().height
|
||||
|
||||
x = screen.get_root_window().get_pointer()[1]
|
||||
#TODO GTK3, how: x = screen.get_window().get_device_position()[0]
|
||||
x -= (w / 2 + Tooltip.BORDER_WIDTH)
|
||||
|
||||
pointer_screen, px, py, _ = screen.get_display().get_pointer()
|
||||
if pointer_screen != screen:
|
||||
px = x
|
||||
py = y
|
||||
|
||||
monitor_num = screen.get_monitor_at_point(px, py)
|
||||
monitor = screen.get_monitor_geometry(monitor_num)
|
||||
|
||||
if (x + w) > monitor.x + monitor.width:
|
||||
x -= (x + w) - (monitor.x + monitor.width);
|
||||
elif x < monitor.x:
|
||||
x = monitor.x
|
||||
|
||||
if ((y + h + widget.get_allocation().height + Tooltip.BORDER_WIDTH) >
|
||||
monitor.y + monitor.height):
|
||||
y -= h + Tooltip.BORDER_WIDTH
|
||||
else:
|
||||
y += widget.get_allocation().height + Tooltip.BORDER_WIDTH
|
||||
|
||||
return x, y
|
||||
|
||||
# from gtktooltips.c:gtk_tooltips_paint_window
|
||||
def _on__draw_event(self, window, cairo_context):
|
||||
#GTK3 TODO, paint_flat_box deprecated !!
|
||||
greq = self.size_request()
|
||||
w = greq.width
|
||||
h = greq.height
|
||||
Gtk.render_frame(window.get_style_context(), cairo_context,
|
||||
0,0,w,h)
|
||||
#window.get_style().paint_flat_box(window.window,
|
||||
# Gtk.StateType.NORMAL, Gtk.ShadowType.OUT,
|
||||
# None, window, "tooltip",
|
||||
# 0, 0, w, h)
|
||||
return False
|
||||
|
||||
def _real_display(self, widget):
|
||||
x, y = self._calculate_pos(widget)
|
||||
|
||||
self.move(x, y)
|
||||
self.show_all()
|
||||
|
||||
# Public API
|
||||
|
||||
def set_text(self, text):
|
||||
self._label.set_text(text)
|
||||
|
||||
def hide(self):
|
||||
Gtk.Window.hide(self)
|
||||
GObject.source_remove(self._show_timeout_id)
|
||||
self._show_timeout_id = -1
|
||||
|
||||
def display(self, widget):
|
||||
if not self._label.get_text():
|
||||
return
|
||||
|
||||
if self._show_timeout_id != -1:
|
||||
return
|
||||
|
||||
self._show_timeout_id = GObject.timeout_add(Tooltip.DEFAULT_DELAY,
|
||||
self._real_display,
|
||||
widget)
|
||||
|
||||
# This is tricky and contains quite a few hacks:
|
||||
# An entry contains 2 GdkWindows, one for the background and one for
|
||||
# the text area. The normal one, on which the (normally white) background
|
||||
# is drawn can be accessed through entry.window (after realization)
|
||||
# The other window is the one where the cursor and the text is drawn upon,
|
||||
# it's refered to as "text area" inside the GtkEntry code and it is called
|
||||
# the same here. It can only be accessed through window.get_children()[0],
|
||||
# since it's considered private to the entry.
|
||||
#
|
||||
# +-------------------------------------+
|
||||
# | (1) | (1) parent widget (grey)
|
||||
# |+----------------(2)----------------+|
|
||||
# || |-- /-\ | || (2) entry.window (white)
|
||||
# || |- | | |(4) (3) ||
|
||||
# || | \-/ | || (3) text area (transparent)
|
||||
# |+-----------------------------------+|
|
||||
# |-------------------------------------| (4) cursor, black
|
||||
# | |
|
||||
# +-------------------------------------|
|
||||
#
|
||||
# So, now we want to put an icon in the edge:
|
||||
# An earlier approached by Lorzeno drew the icon directly on the text area,
|
||||
# which is not desired since if the text is using the whole width of the
|
||||
# entry the icon will be drawn on top of the text.
|
||||
# Now what we want to do is to resize the text area and create a
|
||||
# new window upon which we can draw the icon.
|
||||
#
|
||||
# +-------------------------------------+
|
||||
# | | (5) icon window
|
||||
# |+----------------------------++-----+|
|
||||
# || |-- /-\ | || ||
|
||||
# || |- | | | || (5) ||
|
||||
# || | \-/ | || ||
|
||||
# |+----------------------------++-----+|
|
||||
# |-------------------------------------|
|
||||
# | |
|
||||
# +-------------------------------------+
|
||||
#
|
||||
# When resizing the text area the cursor and text is not moved into the
|
||||
# correct position, it'll still be off by the width of the icon window
|
||||
# To fix this we need to call a private function, gtk_entry_recompute,
|
||||
# a workaround is to call set_visiblity() which calls recompute()
|
||||
# internally.
|
||||
#
|
||||
|
||||
class IconEntry(object):
|
||||
"""
|
||||
Helper object for rendering an icon in a GtkEntry
|
||||
"""
|
||||
|
||||
def __init__(self, entry):
|
||||
if not isinstance(entry, Gtk.Entry):
|
||||
raise TypeError("entry must be a Gtk.Entry")
|
||||
self._constructed = False
|
||||
self._pixbuf = None
|
||||
self._pixw = 1
|
||||
self._pixh = 1
|
||||
self._text_area = None
|
||||
self._text_area_pos = (0, 0)
|
||||
self._icon_win = None
|
||||
self._entry = entry
|
||||
self._tooltip = Tooltip(self)
|
||||
self._locked = False
|
||||
entry.connect('enter-notify-event',
|
||||
self._on_entry__enter_notify_event)
|
||||
entry.connect('leave-notify-event',
|
||||
self._on_entry__leave_notify_event)
|
||||
entry.connect('notify::xalign',
|
||||
self._on_entry__notify_xalign)
|
||||
self._update_position()
|
||||
|
||||
def _on_entry__notify_xalign(self, entry, pspec):
|
||||
self._update_position()
|
||||
|
||||
def _on_entry__enter_notify_event(self, entry, event):
|
||||
icon_win = self.get_icon_window()
|
||||
if event.window != icon_win:
|
||||
return
|
||||
|
||||
self._tooltip.display(entry)
|
||||
|
||||
def _on_entry__leave_notify_event(self, entry, event):
|
||||
if event.window != self.get_icon_window():
|
||||
return
|
||||
|
||||
self._tooltip.hide()
|
||||
|
||||
def set_tooltip(self, text):
|
||||
self._tooltip.set_text(text)
|
||||
|
||||
def get_icon_window(self):
|
||||
return self._icon_win
|
||||
|
||||
def set_pixbuf(self, pixbuf):
|
||||
"""
|
||||
@param pixbuf: a GdkPixbuf.Pixbuf or None
|
||||
"""
|
||||
entry = self._entry
|
||||
if not isinstance(entry.get_toplevel(), Gtk.Window):
|
||||
# For widgets in SlaveViews, wait until they're attached
|
||||
# to something visible, then set the pixbuf
|
||||
entry.connect_object('realize', self.set_pixbuf, pixbuf)
|
||||
return
|
||||
|
||||
if pixbuf:
|
||||
if not isinstance(pixbuf, GdkPixbuf.Pixbuf):
|
||||
raise TypeError("pixbuf must be a GdkPixbuf")
|
||||
else:
|
||||
# Turning off the icon should also restore the background
|
||||
entry.override_background_color(Gtk.StateType.NORMAL, None)
|
||||
if not self._pixbuf:
|
||||
return
|
||||
self._pixbuf = pixbuf
|
||||
|
||||
if pixbuf:
|
||||
self._pixw = pixbuf.get_width()
|
||||
self._pixh = pixbuf.get_height()
|
||||
else:
|
||||
self._pixw = self._pixh = 0
|
||||
|
||||
win = self._icon_win
|
||||
if not win:
|
||||
self.construct()
|
||||
win = self._icon_win
|
||||
|
||||
self.resize_windows()
|
||||
|
||||
# XXX: Why?
|
||||
if win:
|
||||
if not pixbuf:
|
||||
win.hide()
|
||||
else:
|
||||
win.show()
|
||||
|
||||
self._recompute()
|
||||
entry.queue_draw()
|
||||
|
||||
def construct(self):
|
||||
if self._constructed:
|
||||
return
|
||||
|
||||
entry = self._entry
|
||||
if not entry.get_realized():
|
||||
entry.realize()
|
||||
|
||||
# Hack: Save a reference to the text area, now when its created
|
||||
self._text_area = entry.get_window().get_children()[0]
|
||||
self._text_area_pos = self._text_area.get_position()
|
||||
|
||||
# PyGTK should allow default values for most of the values here.
|
||||
attr = Gdk.WindowAttr()
|
||||
attr.width = self._pixw
|
||||
attr.height = self._pixh
|
||||
attr.x = 0
|
||||
attr.y = 0
|
||||
attr.cursor = Gdk.Cursor.new_for_display(
|
||||
entry.get_display(), Gdk.CursorType.LEFT_PTR)
|
||||
#attr.wmclass_name=''
|
||||
#attr.wmclass_class=''
|
||||
attr.override_redirect=True
|
||||
attr.event_mask = (Gdk.EventMask.ENTER_NOTIFY_MASK |
|
||||
Gdk.EventMask.LEAVE_NOTIFY_MASK)
|
||||
# GTK3 We can we not set title?
|
||||
#attr.title = 'icon window'
|
||||
attr.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT
|
||||
attr.window_type = Gdk.WindowType.CHILD
|
||||
attr.visual = entry.get_visual()
|
||||
attrmask = (
|
||||
#Gdk.WindowAttributesType.TITLE |
|
||||
Gdk.WindowAttributesType.X |
|
||||
Gdk.WindowAttributesType.Y |
|
||||
Gdk.WindowAttributesType.CURSOR |
|
||||
Gdk.WindowAttributesType.VISUAL |
|
||||
Gdk.WindowAttributesType.NOREDIR
|
||||
)
|
||||
#the window containing the icon image
|
||||
self._icon_win = Gdk.Window(entry.get_window(),
|
||||
attr,
|
||||
attrmask)
|
||||
## Gdk.WindowType.CHILD,
|
||||
## (Gdk.EventMask.ENTER_NOTIFY_MASK |
|
||||
## Gdk.EventMask.LEAVE_NOTIFY_MASK),
|
||||
## Gdk.WindowWindowClass.INPUT_OUTPUT,
|
||||
## title='icon window',
|
||||
## x=0, y=0,
|
||||
## visual=entry.get_visual(),
|
||||
## #TODO GTK3: is there alternative for:
|
||||
## #colormap=entry.get_colormap(),
|
||||
## cursor=Gdk.Cursor.new_for_display(
|
||||
## entry.get_display(), Gdk.CursorType.LEFT_PTR),
|
||||
## wmclass_name='',
|
||||
## wmclass_class='', override_redirect=True)
|
||||
self._icon_win.set_user_data(entry)
|
||||
#win.set_background(entry.get_style().base[entry.get_state()])
|
||||
self._constructed = True
|
||||
|
||||
def deconstruct(self):
|
||||
if self._icon_win:
|
||||
self._icon_win.set_user_data(None)
|
||||
# Destroy not needed, called by the GC.
|
||||
# TODO GTK3: we see error: Gdk-WARNING **: losing last reference to undestroyed window
|
||||
# TODO Investigate
|
||||
self._icon_win = None
|
||||
|
||||
def update_background(self, color):
|
||||
if self._locked:
|
||||
return
|
||||
if not self._icon_win:
|
||||
return
|
||||
|
||||
self.draw_pixbuf()
|
||||
|
||||
maxvalcol = 65535.
|
||||
if color:
|
||||
red = int(color.red/ maxvalcol*255)
|
||||
green = int(color.green/ maxvalcol*255)
|
||||
blue = int(color.blue/ maxvalcol*255)
|
||||
rgba = Gdk.RGBA()
|
||||
Gdk.RGBA.parse(rgba, 'rgb(%f,%f,%f)'%(red, green, blue))
|
||||
self._entry.override_background_color(Gtk.StateFlags.NORMAL, rgba)
|
||||
#GTK 3: workaround, background not changing in themes, use symbolic
|
||||
self._entry.override_symbolic_color('bg_color', rgba)
|
||||
self._entry.override_symbolic_color('theme_bg_color', rgba)
|
||||
else:
|
||||
self._entry.override_background_color(Gtk.StateFlags.NORMAL, None)
|
||||
self._entry.override_symbolic_color('bg_color', None)
|
||||
self._entry.override_symbolic_color('theme_bg_color', None)
|
||||
|
||||
|
||||
def get_background(self):
|
||||
""" Return default background color as a Gdk.Color """
|
||||
backcol = self._entry.get_style_context().get_background_color(Gtk.StateType.NORMAL)
|
||||
bcol= Gdk.Color.parse('#fff')[1]
|
||||
bcol.red = int(backcol.red * 65535)
|
||||
bcol.green = int(backcol.green * 65535)
|
||||
bcol.blue = int(backcol.blue * 65535)
|
||||
return bcol
|
||||
|
||||
def resize_windows(self):
|
||||
if not self._pixbuf:
|
||||
return
|
||||
|
||||
icony = iconx = 0
|
||||
|
||||
# Make space for the icon, both windows
|
||||
# GTK 3 gives for entry the sizes for the entire editor
|
||||
geom =self._text_area.get_geometry()
|
||||
origx = geom[0]
|
||||
origy = geom[1]
|
||||
origw = geom[2]
|
||||
origh = geom[3]
|
||||
textw = origw
|
||||
texth = origh
|
||||
textw = textw - self._pixw - (iconx + icony)
|
||||
|
||||
if self._pos == Gtk.PositionType.LEFT:
|
||||
textx, texty = self._text_area_pos
|
||||
textx += iconx + self._pixw
|
||||
|
||||
# FIXME: Why is this needed. Focus padding?
|
||||
# The text jumps without this
|
||||
textw -= 2
|
||||
self._text_area.move_resize(textx, texty, textw, texth)
|
||||
self._recompute()
|
||||
elif self._pos == Gtk.PositionType.RIGHT:
|
||||
self._text_area.resize(textw, texth)
|
||||
iconx += textw
|
||||
|
||||
icon_win = self._icon_win
|
||||
# XXX: Why?
|
||||
if not icon_win:
|
||||
return
|
||||
|
||||
# If the size of the window is large enough, resize and move it
|
||||
# Otherwise just move it to the right side of the entry
|
||||
if (icon_win.get_width(), icon_win.get_height()) != (self._pixw, self._pixh):
|
||||
icon_win.move_resize(origx + origw - self._pixw, icony + origy, 100, 100)
|
||||
icon_win.move_resize(origx + origw - self._pixw, icony + origy, self._pixw, self._pixh)
|
||||
else:
|
||||
icon_win.move(origx + origw - self._pixw, icony + origy)
|
||||
|
||||
def draw_pixbuf(self):
|
||||
if not self._pixbuf:
|
||||
return
|
||||
|
||||
win = self._icon_win
|
||||
# XXX: Why?
|
||||
if not win:
|
||||
return
|
||||
|
||||
# Draw background first - not needed with cairo!
|
||||
##color = self._entry.get_style_context().get_background_color(
|
||||
## self._entry.get_state())
|
||||
|
||||
# If sensitive draw the icon, regardless of the window emitting the
|
||||
# event since makes it a bit smoother on resize
|
||||
if self._entry.get_sensitive():
|
||||
#GTK 3: we use cairo to draw the pixbuf
|
||||
cairo_t = Gdk.cairo_create(win)
|
||||
Gdk.cairo_set_source_pixbuf(cairo_t, self._pixbuf, 0, 0)
|
||||
cairo_t.new_path()
|
||||
cairo_t.move_to (0, 0);
|
||||
cairo_t.rel_line_to (win.get_width(), 0);
|
||||
cairo_t.rel_line_to (0, win.get_height());
|
||||
cairo_t.rel_line_to (-win.get_width(), 0);
|
||||
cairo_t.close_path ();
|
||||
cairo_t.fill()
|
||||
|
||||
def _update_position(self):
|
||||
if self._entry.get_property('xalign') > 0.5:
|
||||
self._pos = Gtk.PositionType.LEFT
|
||||
else:
|
||||
self._pos = Gtk.PositionType.RIGHT
|
||||
|
||||
def _recompute(self):
|
||||
# Protect against re-entrancy when inserting text, happens in DateEntry
|
||||
if self._locked:
|
||||
return
|
||||
|
||||
self._locked = True
|
||||
|
||||
# Hack: This triggers a .recompute() which is private
|
||||
visibility = self._entry.get_visibility()
|
||||
self._entry.set_visibility(not visibility)
|
||||
self._entry.set_visibility(visibility)
|
||||
|
||||
# Another option would be to call insert_text, however it
|
||||
# emits the signal ::changed which is not desirable.
|
||||
#self._entry.insert_text('')
|
||||
|
||||
self._locked = False
|
||||
|
||||
|
||||
(DIRECTION_LEFT, DIRECTION_RIGHT) = (1, -1)
|
||||
|
||||
(INPUT_ASCII_LETTER,
|
||||
@@ -683,7 +253,8 @@ class MaskedEntry(UndoableEntry):
|
||||
self._completion = None
|
||||
self._exact_completion = False
|
||||
self._block_changed = False
|
||||
self._icon = IconEntry(self)
|
||||
self.hasicon = False
|
||||
## self._icon = IconEntry(self)
|
||||
|
||||
# List of validators
|
||||
# str -> static characters
|
||||
@@ -703,25 +274,25 @@ class MaskedEntry(UndoableEntry):
|
||||
self.in_do_draw = False
|
||||
|
||||
# Virtual methods, note do_size_alloc needs gtk 2.9 +
|
||||
def do_size_allocate(self, allocation):
|
||||
Gtk.Entry.do_size_allocate(self, allocation)
|
||||
## def do_size_allocate(self, allocation):
|
||||
## Gtk.Entry.do_size_allocate(self, allocation)
|
||||
##
|
||||
## if self.get_realized():
|
||||
## self._icon.resize_windows()
|
||||
|
||||
if self.get_realized():
|
||||
self._icon.resize_windows()
|
||||
## def do_draw(self, cairo_t):
|
||||
## Gtk.Entry.do_draw(self, cairo_t)
|
||||
##
|
||||
## if Gtk.cairo_should_draw_window(cairo_t, self.get_window()):
|
||||
## self._icon.draw_pixbuf()
|
||||
|
||||
def do_draw(self, cairo_t):
|
||||
Gtk.Entry.do_draw(self, cairo_t)
|
||||
## def do_realize(self):
|
||||
## Gtk.Entry.do_realize(self)
|
||||
## self._icon.construct()
|
||||
|
||||
if Gtk.cairo_should_draw_window(cairo_t, self.get_window()):
|
||||
self._icon.draw_pixbuf()
|
||||
|
||||
def do_realize(self):
|
||||
Gtk.Entry.do_realize(self)
|
||||
self._icon.construct()
|
||||
|
||||
def do_unrealize(self):
|
||||
self._icon.deconstruct()
|
||||
Gtk.Entry.do_unrealize(self)
|
||||
## def do_unrealize(self):
|
||||
## self._icon.deconstruct()
|
||||
## Gtk.Entry.do_unrealize(self)
|
||||
|
||||
# Mask & Fields
|
||||
|
||||
@@ -1455,23 +1026,58 @@ class MaskedEntry(UndoableEntry):
|
||||
# IconEntry
|
||||
|
||||
def set_tooltip(self, text):
|
||||
self._icon.set_tooltip(text)
|
||||
self.set_icon_tooltip_text(Gtk.EntryIconPosition.SECONDARY, text)
|
||||
|
||||
def set_pixbuf(self, pixbuf):
|
||||
self._icon.set_pixbuf(pixbuf)
|
||||
self.set_icon_from_pixbuf(Gtk.EntryIconPosition.SECONDARY, pixbuf)
|
||||
|
||||
def set_stock(self, stock_name):
|
||||
pixbuf = self.render_icon(stock_name, Gtk.IconSize.MENU)
|
||||
self._icon.set_pixbuf(pixbuf)
|
||||
self.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, stock_name)
|
||||
|
||||
def update_background(self, color):
|
||||
self._icon.update_background(color)
|
||||
def update_background(self, color, unset=False):
|
||||
maxvalcol = 65535.
|
||||
if color:
|
||||
red = int(color.red/ maxvalcol*255)
|
||||
green = int(color.green/ maxvalcol*255)
|
||||
blue = int(color.blue/ maxvalcol*255)
|
||||
rgba = Gdk.RGBA()
|
||||
Gdk.RGBA.parse(rgba, 'rgb(%f,%f,%f)'%(red, green, blue))
|
||||
self.override_background_color(Gtk.StateFlags.NORMAL |
|
||||
Gtk.StateFlags.ACTIVE | Gtk.StateFlags.SELECTED |
|
||||
Gtk.StateFlags.FOCUSED, rgba)
|
||||
#GTK 3: workaround, background not changing in themes, use symbolic
|
||||
self.override_symbolic_color('bg_color', rgba)
|
||||
self.override_symbolic_color('base_color', rgba)
|
||||
self.override_symbolic_color('theme_bg_color', rgba)
|
||||
self.override_symbolic_color('theme_base_color', rgba)
|
||||
self.get_window().set_background_rgba(rgba)
|
||||
pango_context = self.get_layout().get_context()
|
||||
font_description = pango_context.get_font_description()
|
||||
if unset:
|
||||
font_description.set_weight(Pango.Weight.NORMAL)
|
||||
else:
|
||||
font_description.set_weight(Pango.Weight.BOLD)
|
||||
self.override_font(font_description)
|
||||
else:
|
||||
self.override_background_color(Gtk.StateFlags.NORMAL |
|
||||
Gtk.StateFlags.ACTIVE | Gtk.StateFlags.SELECTED |
|
||||
Gtk.StateFlags.FOCUSED, None)
|
||||
self.override_symbolic_color('bg_color', None)
|
||||
self.override_symbolic_color('base_color', None)
|
||||
self.override_symbolic_color('theme_bg_color', None)
|
||||
self.override_symbolic_color('theme_base_color', None)
|
||||
pango_context = self.get_layout().get_context()
|
||||
font_description = pango_context.get_font_description()
|
||||
font_description.set_weight(Pango.Weight.NORMAL)
|
||||
self.override_font(font_description)
|
||||
|
||||
def get_background(self):
|
||||
return self._icon.get_background()
|
||||
|
||||
def get_icon_window(self):
|
||||
return self._icon.get_icon_window()
|
||||
backcol = self.get_style_context().get_background_color(Gtk.StateType.NORMAL)
|
||||
bcol= Gdk.Color.parse('#fff')[1]
|
||||
bcol.red = int(backcol.red * 65535)
|
||||
bcol.green = int(backcol.green * 65535)
|
||||
bcol.blue = int(backcol.blue * 65535)
|
||||
return bcol
|
||||
|
||||
# Gtk.EntryCompletion convenience function
|
||||
|
||||
@@ -1674,7 +1280,6 @@ class ValidatableMaskedEntry(MaskedEntry):
|
||||
"""Change the validation state to valid, which will remove icons and
|
||||
reset the background color
|
||||
"""
|
||||
|
||||
##_LOG.debug('Setting state for %s to VALID' % self.model_attribute)
|
||||
self._set_valid_state(True)
|
||||
|
||||
|
||||
@@ -255,10 +255,9 @@ class Calendar(Report):
|
||||
last_edge = 0
|
||||
font_height = pt2cm(1.5 * ptext1style.get_font().get_size())
|
||||
x = last_edge + (width - last_edge)/2
|
||||
y = height - font_height
|
||||
self.doc.center_text("CAL-Text1style", self.text1, x, y * 3)
|
||||
self.doc.center_text("CAL-Text2style", self.text2, x, y * 2)
|
||||
self.doc.center_text("CAL-Text3style", self.text3, x, y * 1)
|
||||
self.doc.center_text("CAL-Text1style", self.text1, x, height - font_height * 3)
|
||||
self.doc.center_text("CAL-Text2style", self.text2, x, height - font_height * 2)
|
||||
self.doc.center_text("CAL-Text3style", self.text3, x, height - font_height * 1)
|
||||
self.doc.end_page()
|
||||
|
||||
def collect_data(self):
|
||||
|
||||
@@ -39,7 +39,7 @@ import tarfile
|
||||
if sys.version_info[0] < 3:
|
||||
from cStringIO import StringIO
|
||||
else:
|
||||
from io import StringIO
|
||||
import io
|
||||
from gramps.gen.ggettext import gettext as _
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
@@ -63,7 +63,7 @@ from gi.repository import Gtk
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gui.plug.export import WriterOptionBox
|
||||
from exportxml import XmlWriter
|
||||
from .exportxml import XmlWriter
|
||||
from gramps.gen.utils.file import media_path_full, get_unicode_path_from_file_chooser
|
||||
from gramps.gen.constfunc import win
|
||||
|
||||
@@ -214,7 +214,10 @@ class PackageWriter(object):
|
||||
# select_clicked()
|
||||
|
||||
# Write XML now
|
||||
g = StringIO()
|
||||
if sys.version_info[0] < 3:
|
||||
g = StringIO()
|
||||
else:
|
||||
g = io.BytesIO()
|
||||
gfile = XmlWriter(self.db, self.user, 2)
|
||||
gfile.write_handle(g)
|
||||
tarinfo = tarfile.TarInfo('data.gramps')
|
||||
|
||||
@@ -121,7 +121,7 @@ class GrampsXmlWriter(UpdateCallback):
|
||||
|
||||
self.status = None
|
||||
|
||||
def write(self,filename):
|
||||
def write(self, filename):
|
||||
"""
|
||||
Write the database to the specified file.
|
||||
"""
|
||||
@@ -180,7 +180,7 @@ class GrampsXmlWriter(UpdateCallback):
|
||||
|
||||
if self.compress and _gzip_ok:
|
||||
try:
|
||||
g = gzip.GzipFile(mode="wb",fileobj=handle)
|
||||
g = gzip.GzipFile(mode="wb", fileobj=handle)
|
||||
except:
|
||||
g = handle
|
||||
else:
|
||||
|
||||
@@ -39,10 +39,12 @@ class CalendarGramplet(Gramplet):
|
||||
self.set_tooltip(_("Double-click a day for details"))
|
||||
self.gui.calendar = Gtk.Calendar()
|
||||
self.gui.calendar.connect('day-selected-double-click', self.double_click)
|
||||
if self.uistate.screen_width() <= 1024:
|
||||
self.gui.calendar.set_display_options(Gtk.CALENDAR_SHOW_HEADING)
|
||||
self.gui.calendar.set_display_options(
|
||||
Gtk.CalendarDisplayOptions.SHOW_HEADING)
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
self.gui.get_container_widget().add_with_viewport(self.gui.calendar)
|
||||
vbox = Gtk.VBox(False, 0)
|
||||
vbox.pack_start(self.gui.calendar, False, False, 0)
|
||||
self.gui.get_container_widget().add_with_viewport(vbox)
|
||||
self.gui.calendar.show()
|
||||
|
||||
def post_init(self):
|
||||
|
||||
@@ -111,7 +111,7 @@ class WelcomeGramplet(Gramplet):
|
||||
welcome += linkst(_('Start with Genealogy and Gramps'),
|
||||
_('http://www.gramps-project.org/wiki/index.php?title=Start_with_Genealogy')) + '\n'
|
||||
welcome += linkst(_('Gramps online manual'),
|
||||
_('http://www.gramps-project.org/wiki/index.php?title=Gramps_3.3_Wiki_Manual')) + '\n'
|
||||
_('http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual')) + '\n'
|
||||
welcome += linkst(_('Ask questions on gramps-users mailing list'),
|
||||
_('http://gramps-project.org/contact/')) + '\n\n'
|
||||
|
||||
|
||||
@@ -400,8 +400,15 @@ class RelGraphReport(Report):
|
||||
label += " (%s)" % p_id
|
||||
if self.includedates:
|
||||
birth, death = self.get_date_strings(person)
|
||||
label = label + '%s(%s - %s)' % (lineDelimiter, birth, death)
|
||||
|
||||
if birth or death:
|
||||
label += ' %s(' % lineDelimiter
|
||||
if birth:
|
||||
label += '%s' % birth
|
||||
label += ' - '
|
||||
if death:
|
||||
label += '%s' % death
|
||||
label += ')'
|
||||
|
||||
# see if we have a table that needs to be terminated
|
||||
if self.bUseHtmlOutput:
|
||||
label += '</TD></TR></TABLE>'
|
||||
|
||||
@@ -50,7 +50,7 @@ LOG = logging.getLogger(".ImportCSV")
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.ggettext import sgettext as _
|
||||
from gramps.gen.ggettext import ngettext
|
||||
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname
|
||||
from gramps.gen.lib import ChildRef, Citation, Event, EventRef, EventType, Family, FamilyRelType, Name, NameType, Note, NoteType, Person, Place, Source, Surname, Tag
|
||||
from gramps.gen.db import DbTxn
|
||||
from gramps.gen.plug.utils import OpenFileOrStdin
|
||||
from gramps.gen.datehandler import parser as _dp
|
||||
@@ -59,6 +59,7 @@ from gramps.gen.utils.id import create_id
|
||||
from gramps.gui.utils import ProgressMeter
|
||||
from gramps.gen.lib.eventroletype import EventRoleType
|
||||
from gramps.gen.constfunc import cuni, conv_to_unicode, STRTYPE
|
||||
from gramps.gen.config import config
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -95,6 +96,8 @@ class UTF8Recoder(object):
|
||||
"Encode the next line of the file."
|
||||
return self.reader.next().encode("utf-8")
|
||||
|
||||
next = __next__
|
||||
|
||||
class UnicodeReader(object):
|
||||
"""
|
||||
A CSV reader which will iterate over lines in the CSV file,
|
||||
@@ -120,6 +123,8 @@ class UnicodeReader(object):
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
next = __next__
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Support and main functions
|
||||
@@ -141,7 +146,8 @@ def rd(line_number, row, col, key, default = None):
|
||||
|
||||
def importData(dbase, filename, user):
|
||||
"""Function called by Gramps to import data on persons in CSV format."""
|
||||
parser = CSVParser(dbase, user)
|
||||
parser = CSVParser(dbase, user, (config.get('preferences.tag-on-import-format') if
|
||||
config.get('preferences.tag-on-import') else None))
|
||||
try:
|
||||
with OpenFileOrStdin(filename, 'b') as filehandle:
|
||||
parser.parse(filehandle)
|
||||
@@ -157,7 +163,7 @@ def importData(dbase, filename, user):
|
||||
#-------------------------------------------------------------------------
|
||||
class CSVParser(object):
|
||||
"""Class to read data in CSV format from a file object."""
|
||||
def __init__(self, dbase, user):
|
||||
def __init__(self, dbase, user, default_tag_format=None):
|
||||
self.db = dbase
|
||||
self.user = user
|
||||
self.trans = None
|
||||
@@ -235,6 +241,16 @@ class CSVParser(object):
|
||||
for val in column2label[key]:
|
||||
lab2col_dict.append((val, key))
|
||||
self.label2column = dict(lab2col_dict)
|
||||
if default_tag_format:
|
||||
name = time.strftime(default_tag_format)
|
||||
tag = self.db.get_tag_from_name(name)
|
||||
if tag:
|
||||
self.default_tag = tag
|
||||
else:
|
||||
self.default_tag = Tag()
|
||||
self.default_tag.set_name(name)
|
||||
else:
|
||||
self.default_tag = None
|
||||
|
||||
def cleanup_column_name(self, column):
|
||||
"""Handle column aliases for CSV spreadsheet import and SQL."""
|
||||
@@ -313,6 +329,8 @@ class CSVParser(object):
|
||||
tym = time.time()
|
||||
self.db.disable_signals()
|
||||
with DbTxn(_("CSV import"), self.db, batch=True) as self.trans:
|
||||
if self.default_tag and self.default_tag.handle is None:
|
||||
self.db.add_tag(self.default_tag, self.trans)
|
||||
self._parse_csv_data(data, progress)
|
||||
self.db.enable_signals()
|
||||
self.db.request_rebuild()
|
||||
@@ -432,6 +450,8 @@ class CSVParser(object):
|
||||
new_note.handle = create_id()
|
||||
new_note.type.set(NoteType.EVENT)
|
||||
new_note.set(note)
|
||||
if self.default_tag:
|
||||
new_note.add_tag(self.default_tag.handle)
|
||||
self.db.add_note(new_note, self.trans)
|
||||
marriage.add_note(new_note.handle)
|
||||
self.db.commit_event(marriage, self.trans)
|
||||
@@ -506,6 +526,8 @@ class CSVParser(object):
|
||||
new_note.handle = create_id()
|
||||
new_note.type.set(NoteType.PERSON)
|
||||
new_note.set(note)
|
||||
if self.default_tag:
|
||||
new_note.add_tag(self.default_tag.handle)
|
||||
self.db.add_note(new_note, self.trans)
|
||||
child.add_note(new_note.handle)
|
||||
self.db.commit_person(child, self.trans)
|
||||
@@ -592,6 +614,8 @@ class CSVParser(object):
|
||||
new_note.handle = create_id()
|
||||
new_note.type.set(NoteType.PERSON)
|
||||
new_note.set(note)
|
||||
if self.default_tag:
|
||||
new_note.add_tag(self.default_tag.handle)
|
||||
self.db.add_note(new_note, self.trans)
|
||||
person.add_note(new_note.handle)
|
||||
if grampsid is not None:
|
||||
@@ -719,6 +743,8 @@ class CSVParser(object):
|
||||
family.set_gramps_id(id_)
|
||||
# add it:
|
||||
family.set_handle(self.db.create_id())
|
||||
if self.default_tag:
|
||||
family.add_tag(self.default_tag.handle)
|
||||
if husband:
|
||||
family.set_father_handle(husband.get_handle())
|
||||
husband.add_family_handle(family.get_handle())
|
||||
@@ -775,6 +801,8 @@ class CSVParser(object):
|
||||
def create_person(self):
|
||||
""" Used to create a new person we know doesn't exist """
|
||||
person = Person()
|
||||
if self.default_tag:
|
||||
person.add_tag(self.default_tag.handle)
|
||||
self.db.add_person(person, self.trans)
|
||||
self.indi_count += 1
|
||||
return person
|
||||
|
||||
@@ -115,8 +115,10 @@ def importData(database, filename, user):
|
||||
stage_one.set_encoding(code_set)
|
||||
ifile.seek(0)
|
||||
gedparse = libgedcom.GedcomParser(
|
||||
database, ifile, filename, user, stage_one,
|
||||
config.get('preferences.default-source'))
|
||||
database, ifile, filename, user, stage_one,
|
||||
config.get('preferences.default-source'),
|
||||
(config.get('preferences.tag-on-import-format') if
|
||||
config.get('preferences.tag-on-import') else None))
|
||||
except IOError as msg:
|
||||
user.notify_error(_("%s could not be opened\n") % filename, str(msg))
|
||||
return
|
||||
|
||||
@@ -94,6 +94,7 @@ def impData(database, name, user):
|
||||
|
||||
importer = importData
|
||||
info = importer(database, imp_db_name, user)
|
||||
|
||||
newmediapath = database.get_mediapath()
|
||||
#import of gpkg should not change media path as all media has new paths!
|
||||
if not oldmediapath == newmediapath :
|
||||
|
||||
@@ -67,6 +67,7 @@ from gramps.gen.db.dbconst import (PERSON_KEY, FAMILY_KEY, SOURCE_KEY,
|
||||
CITATION_KEY)
|
||||
from gramps.gen.updatecallback import UpdateCallback
|
||||
from gramps.gen.const import VERSION
|
||||
from gramps.gen.config import config
|
||||
#import gramps.plugins.lib.libgrampsxml
|
||||
from gramps.plugins.lib import libgrampsxml
|
||||
|
||||
@@ -123,7 +124,9 @@ def importData(database, filename, user):
|
||||
change = time.time()
|
||||
else:
|
||||
change = os.path.getmtime(filename)
|
||||
parser = GrampsParser(database, user, change)
|
||||
parser = GrampsParser(database, user, change,
|
||||
(config.get('preferences.tag-on-import-format') if
|
||||
config.get('preferences.tag-on-import') else None))
|
||||
|
||||
if filename != '-':
|
||||
linecounter = LineParser(filename)
|
||||
@@ -457,7 +460,7 @@ class ImportOpenFileContextManager:
|
||||
#-------------------------------------------------------------------------
|
||||
class GrampsParser(UpdateCallback):
|
||||
|
||||
def __init__(self, database, user, change):
|
||||
def __init__(self, database, user, change, default_tag_format=None):
|
||||
UpdateCallback.__init__(self, user.callback)
|
||||
self.user = user
|
||||
self.__gramps_version = 'unknown'
|
||||
@@ -564,6 +567,17 @@ class GrampsParser(UpdateCallback):
|
||||
self.eidswap = {}
|
||||
self.import_handles = {}
|
||||
|
||||
if default_tag_format:
|
||||
name = time.strftime(default_tag_format)
|
||||
tag = self.db.get_tag_from_name(name)
|
||||
if tag:
|
||||
self.default_tag = tag
|
||||
else:
|
||||
self.default_tag = Tag()
|
||||
self.default_tag.set_name(name)
|
||||
else:
|
||||
self.default_tag = None
|
||||
|
||||
self.func_map = {
|
||||
#name part
|
||||
"name": (self.start_name, self.stop_name),
|
||||
@@ -895,6 +909,9 @@ class GrampsParser(UpdateCallback):
|
||||
|
||||
self.db.disable_signals()
|
||||
|
||||
if self.default_tag and self.default_tag.handle is None:
|
||||
self.db.add_tag(self.default_tag, self.trans)
|
||||
|
||||
self.p = ParserCreate()
|
||||
self.p.StartElementHandler = self.startElement
|
||||
self.p.EndElementHandler = self.endElement
|
||||
@@ -1384,6 +1401,8 @@ class GrampsParser(UpdateCallback):
|
||||
self.person.change = int(attrs.get('change', self.change))
|
||||
self.info.add('new-object', PERSON_KEY, self.person)
|
||||
self.convert_marker(attrs, self.person)
|
||||
if self.default_tag:
|
||||
self.person.add_tag(self.default_tag.handle)
|
||||
return self.person
|
||||
|
||||
def start_people(self, attrs):
|
||||
@@ -1520,6 +1539,8 @@ class GrampsParser(UpdateCallback):
|
||||
if 'type' in attrs:
|
||||
self.family.type.set_from_xml_str(attrs["type"])
|
||||
self.convert_marker(attrs, self.family)
|
||||
if self.default_tag:
|
||||
self.family.add_tag(self.default_tag.handle)
|
||||
return self.family
|
||||
|
||||
def start_rel(self, attrs):
|
||||
@@ -1833,6 +1854,8 @@ class GrampsParser(UpdateCallback):
|
||||
#set correct change time
|
||||
self.db.commit_note(self.note, self.trans, self.change)
|
||||
self.info.add('new-object', NOTE_KEY, self.note)
|
||||
if self.default_tag:
|
||||
self.note.add_tag(self.default_tag.handle)
|
||||
return self.note
|
||||
|
||||
def start_noteref(self, attrs):
|
||||
@@ -2088,6 +2111,8 @@ class GrampsParser(UpdateCallback):
|
||||
src = attrs.get("src", '')
|
||||
if src:
|
||||
self.object.path = src
|
||||
if self.default_tag:
|
||||
self.object.add_tag(self.default_tag.handle)
|
||||
return self.object
|
||||
|
||||
def start_repo(self, attrs):
|
||||
|
||||
@@ -69,7 +69,7 @@ log = logging.getLogger(".libcairodoc")
|
||||
# GTK modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Pango, PangoCairo
|
||||
from gi.repository import Pango, PangoCairo, Gdk
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@@ -629,18 +629,50 @@ class GtkDocParagraph(GtkDocBaseElement):
|
||||
#now recalculate the attrilist:
|
||||
newattrlist = layout.get_attributes().copy()
|
||||
newattrlist.filter(self.filterattr, index)
|
||||
oldattrlist = newattrlist.get_iterator()
|
||||
while next(oldattrlist) :
|
||||
vals = oldattrlist.get_attrs()
|
||||
#print vals
|
||||
for attr in vals:
|
||||
newattr = attr.copy()
|
||||
newattr.start_index -= index if newattr.start_index > index \
|
||||
else 0
|
||||
newattr.end_index -= index
|
||||
newattrlist.insert(newattr)
|
||||
new_paragraph.__set_attrlist(newattrlist)
|
||||
|
||||
## GTK3 PROBLEM: get_iterator no longer available!!
|
||||
## REFERENCES:
|
||||
## http://www.gramps-project.org/bugs/view.php?id=6208
|
||||
## https://bugzilla.gnome.org/show_bug.cgi?id=646788
|
||||
## workaround: https://github.com/matasbbb/pitivit/commit/da815339e5ce3631b122a72158ba9ffcc9ee4372
|
||||
## OLD EASY CODE:
|
||||
## oldattrlist = newattrlist.get_iterator()
|
||||
## while oldattrlist.next() :
|
||||
## vals = oldattrlist.get_attrs()
|
||||
## #print (vals)
|
||||
## for attr in vals:
|
||||
## newattr = attr.copy()
|
||||
## newattr.start_index -= index if newattr.start_index > index \
|
||||
## else 0
|
||||
## newattr.end_index -= index
|
||||
## newattrlist.insert(newattr)
|
||||
## ## START OF WORKAROUND
|
||||
oldtext = self._text
|
||||
pos = 0
|
||||
realpos = 0
|
||||
markstarts = []
|
||||
while pos < index:
|
||||
char = oldtext[realpos]
|
||||
if char == '<' and oldtext[realpos+1] != '/':
|
||||
# a markup starts
|
||||
end = realpos + oldtext[realpos:].find('>') + 1
|
||||
markstarts += [oldtext[realpos:end]]
|
||||
realpos = end
|
||||
elif char == '<':
|
||||
#this is the closing tag, we did not stop yet, so remove tag!
|
||||
realpos = realpos + oldtext[realpos:].find('>') + 1
|
||||
markstarts.pop()
|
||||
else:
|
||||
pos +=1
|
||||
realpos += 1
|
||||
#now construct the marked up text to use
|
||||
newtext = ''.join(markstarts)
|
||||
newtext += oldtext[realpos:]
|
||||
#have it parsed
|
||||
parse_ok, newattrlist, _plaintext, accel_char= \
|
||||
Pango.parse_markup(newtext, -1, '\000')
|
||||
## ##END OF WORKAROUND
|
||||
new_paragraph.__set_attrlist(newattrlist)
|
||||
# then update the first one
|
||||
self.__set_plaintext(self._plaintext.encode('utf-8')[:index])
|
||||
self._style.set_bottom_margin(0)
|
||||
@@ -1031,8 +1063,7 @@ class GtkDocPicture(GtkDocBaseElement):
|
||||
cr.save()
|
||||
cr.translate(l_margin, 0)
|
||||
cr.scale(scale, scale)
|
||||
gcr = Gdk.CairoContext(cr)
|
||||
gcr.set_source_pixbuf(pixbuf,
|
||||
Gdk.cairo_set_source_pixbuf(cr, pixbuf,
|
||||
(img_width / scale - pixbuf_width) / 2,
|
||||
(img_height / scale - pixbuf_height) / 2)
|
||||
cr.rectangle(0 , 0, img_width / scale, img_height / scale)
|
||||
|
||||
@@ -127,7 +127,7 @@ from gramps.gen.lib import (Address, Attribute, AttributeType, ChildRef,
|
||||
ChildRefType, Citation, Date, Event, EventRef, EventRoleType,
|
||||
EventType, Family, FamilyRelType, LdsOrd, Location, MediaObject,
|
||||
MediaRef, Name, NameType, Note, NoteType, Person, PersonRef, Place,
|
||||
RepoRef, Repository, RepositoryType, Researcher, Source,
|
||||
RepoRef, Repository, RepositoryType, Researcher, Source, Tag,
|
||||
SourceMediaType, Surname, Url, UrlType)
|
||||
from gramps.gen.db import DbTxn
|
||||
from gramps.gen.updatecallback import UpdateCallback
|
||||
@@ -1807,7 +1807,7 @@ class GedcomParser(UpdateCallback):
|
||||
return name
|
||||
|
||||
def __init__(self, dbase, ifile, filename, user, stage_one,
|
||||
default_source):
|
||||
default_source, default_tag_format=None):
|
||||
UpdateCallback.__init__(self, user.callback)
|
||||
self.user = user
|
||||
self.set_total(stage_one.get_line_count())
|
||||
@@ -1835,6 +1835,16 @@ class GedcomParser(UpdateCallback):
|
||||
self.def_src = Source()
|
||||
fname = os.path.basename(filename).split('\\')[-1]
|
||||
self.def_src.set_title(_("Import from GEDCOM (%s)") % fname)
|
||||
if default_tag_format:
|
||||
name = time.strftime(default_tag_format)
|
||||
tag = self.dbase.get_tag_from_name(name)
|
||||
if tag:
|
||||
self.default_tag = tag
|
||||
else:
|
||||
self.default_tag = Tag()
|
||||
self.default_tag.set_name(name)
|
||||
else:
|
||||
self.default_tag = None
|
||||
self.dir_path = os.path.dirname(filename)
|
||||
self.is_ftw = False
|
||||
self.groups = None
|
||||
@@ -2594,6 +2604,8 @@ class GedcomParser(UpdateCallback):
|
||||
self.want_parse_warnings = True
|
||||
if self.use_def_src:
|
||||
self.dbase.add_source(self.def_src, self.trans)
|
||||
if self.default_tag and self.default_tag.handle is None:
|
||||
self.dbase.add_tag(self.default_tag, self.trans)
|
||||
self.__parse_record()
|
||||
self.__parse_trailer()
|
||||
for title, handle in self.inline_srcs.items():
|
||||
@@ -3318,6 +3330,9 @@ class GedcomParser(UpdateCallback):
|
||||
# Add the default reference if no source has found
|
||||
self.__add_default_source(person)
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(person)
|
||||
|
||||
self.__check_msgs(_("INDI (individual) Gramps ID %s") %
|
||||
person.get_gramps_id(), state, person)
|
||||
# commit the person to the database
|
||||
@@ -4579,6 +4594,9 @@ class GedcomParser(UpdateCallback):
|
||||
# add default reference if no reference exists
|
||||
self.__add_default_source(family)
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(family)
|
||||
|
||||
self.__check_msgs(_("FAM (family) Gramps ID %s") % family.get_gramps_id(),
|
||||
state, family)
|
||||
# commit family to database
|
||||
@@ -6118,6 +6136,9 @@ class GedcomParser(UpdateCallback):
|
||||
# Add the default reference if no source has found
|
||||
self.__add_default_source(media)
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(media)
|
||||
|
||||
self.__check_msgs(_("OBJE (multi-media object) Gramps ID %s") %
|
||||
media.get_gramps_id(), state, media)
|
||||
# commit the person to the database
|
||||
@@ -6931,6 +6952,9 @@ class GedcomParser(UpdateCallback):
|
||||
self.__undefined)
|
||||
state.msg += sub_state.msg
|
||||
|
||||
# Add a default tag if provided
|
||||
self.__add_default_tag(new_note)
|
||||
|
||||
self.dbase.commit_note(new_note, self.trans, new_note.change)
|
||||
obj.add_note(new_note.get_handle())
|
||||
|
||||
@@ -7255,6 +7279,13 @@ class GedcomParser(UpdateCallback):
|
||||
self.dbase.add_citation(citation, self.trans)
|
||||
obj.add_citation(citation.handle)
|
||||
|
||||
def __add_default_tag(self, obj):
|
||||
"""
|
||||
Add the default tag to the object.
|
||||
"""
|
||||
if self.default_tag:
|
||||
obj.add_tag(self.default_tag.handle)
|
||||
|
||||
def __subm_name(self, line, state):
|
||||
"""
|
||||
@param line: The current line in GedLine format
|
||||
|
||||
@@ -79,7 +79,7 @@ class Rebuild(tool.Tool, UpdateCallback):
|
||||
uistate.push_message(dbstate, _("Rebuilding secondary indexes..."))
|
||||
|
||||
UpdateCallback.__init__(self, self.callback)
|
||||
self.set_total(11)
|
||||
self.set_total(12)
|
||||
self.db.rebuild_secondary(self.update)
|
||||
self.reset()
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
|
||||
|
||||
def selection_toggled(self, cell, path_string):
|
||||
sort_path = tuple(map(int, path_string.split(':')))
|
||||
real_path = self.sort_model.convert_path_to_child_path(sort_path)
|
||||
real_path = self.sort_model.convert_path_to_child_path(Gtk.TreePath(sort_path))
|
||||
row = self.real_model[real_path]
|
||||
row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]
|
||||
self.real_model.row_changed(real_path, row.iter)
|
||||
|
||||
@@ -28,13 +28,12 @@ A plugin to verify the data against user-adjusted tests.
|
||||
This is the research tool, not the low-level data ingerity check.
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import division, print_function
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# standard python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -127,7 +126,7 @@ def clear_cache():
|
||||
# helper functions
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def get_date_from_event_handle(db,event_handle,estimate=False):
|
||||
def get_date_from_event_handle(db, event_handle, estimate=False):
|
||||
if not event_handle:
|
||||
return 0
|
||||
event = find_event(db,event_handle)
|
||||
@@ -140,7 +139,7 @@ def get_date_from_event_handle(db,event_handle,estimate=False):
|
||||
else:
|
||||
return 0
|
||||
|
||||
def get_date_from_event_type(db,person,event_type,estimate=False):
|
||||
def get_date_from_event_type(db, person, event_type, estimate=False):
|
||||
if not person:
|
||||
return 0
|
||||
for event_ref in person.get_event_ref_list():
|
||||
@@ -157,11 +156,11 @@ def get_date_from_event_type(db,person,event_type,estimate=False):
|
||||
return date_obj.get_sort_value()
|
||||
return 0
|
||||
|
||||
def get_bapt_date(db,person,estimate=False):
|
||||
def get_bapt_date(db, person, estimate=False):
|
||||
return get_date_from_event_type(db, person,
|
||||
EventType.BAPTISM, estimate)
|
||||
|
||||
def get_bury_date(db,person,estimate=False):
|
||||
def get_bury_date(db, person, estimate=False):
|
||||
# check role on burial event
|
||||
for event_ref in person.get_event_ref_list():
|
||||
event = find_event(db, event_ref.ref)
|
||||
@@ -170,7 +169,7 @@ def get_bury_date(db,person,estimate=False):
|
||||
return get_date_from_event_type(db, person,
|
||||
EventType.BURIAL, estimate)
|
||||
|
||||
def get_birth_date(db,person,estimate=False):
|
||||
def get_birth_date(db, person, estimate=False):
|
||||
if not person:
|
||||
return 0
|
||||
birth_ref = person.get_birth_ref()
|
||||
@@ -182,7 +181,7 @@ def get_birth_date(db,person,estimate=False):
|
||||
ret = get_bapt_date(db,person,estimate)
|
||||
return ret
|
||||
|
||||
def get_death_date(db,person,estimate=False):
|
||||
def get_death_date(db, person, estimate=False):
|
||||
if not person:
|
||||
return 0
|
||||
death_ref = person.get_death_ref()
|
||||
@@ -194,14 +193,14 @@ def get_death_date(db,person,estimate=False):
|
||||
ret = get_bury_date(db,person,estimate)
|
||||
return ret
|
||||
|
||||
def get_age_at_death(db,person,estimate):
|
||||
def get_age_at_death(db, person, estimate):
|
||||
birth_date = get_birth_date(db,person,estimate)
|
||||
death_date = get_death_date(db,person,estimate)
|
||||
if (birth_date > 0) and (death_date > 0):
|
||||
return death_date - birth_date
|
||||
return 0
|
||||
|
||||
def get_father(db,family):
|
||||
def get_father(db, family):
|
||||
if not family:
|
||||
return None
|
||||
father_handle = family.get_father_handle()
|
||||
@@ -209,24 +208,24 @@ def get_father(db,family):
|
||||
return find_person(db,father_handle)
|
||||
return None
|
||||
|
||||
def get_mother(db,family):
|
||||
def get_mother(db, family):
|
||||
if not family:
|
||||
return None
|
||||
mother_handle = family.get_mother_handle()
|
||||
if mother_handle:
|
||||
return find_person(db,mother_handle)
|
||||
return find_person(db, mother_handle)
|
||||
return None
|
||||
|
||||
def get_child_birth_dates(db,family,estimate):
|
||||
def get_child_birth_dates(db, family, estimate):
|
||||
dates = []
|
||||
for child_ref in family.get_child_ref_list():
|
||||
child = find_person(db,child_ref.ref)
|
||||
child_birth_date = get_birth_date(db,child,estimate)
|
||||
child_birth_date = get_birth_date(db, child, estimate)
|
||||
if child_birth_date > 0:
|
||||
dates.append(child_birth_date)
|
||||
return dates
|
||||
|
||||
def get_n_children(db,person):
|
||||
def get_n_children(db, person):
|
||||
n = 0
|
||||
for family_handle in person.get_family_handle_list():
|
||||
family = find_family(db,family_handle)
|
||||
@@ -234,7 +233,7 @@ def get_n_children(db,person):
|
||||
n += len(family.get_child_ref_list())
|
||||
return n
|
||||
|
||||
def get_marriage_date(db,family):
|
||||
def get_marriage_date(db, family):
|
||||
if not family:
|
||||
return 0
|
||||
for event_ref in family.get_event_ref_list():
|
||||
@@ -496,10 +495,10 @@ class VerifyResults(ManagedWindow):
|
||||
self.renderer = Gtk.CellRendererText()
|
||||
self.img_renderer = Gtk.CellRendererPixbuf()
|
||||
self.bool_renderer = Gtk.CellRendererToggle()
|
||||
self.bool_renderer.connect('toggled',self.selection_toggled)
|
||||
self.bool_renderer.connect('toggled', self.selection_toggled)
|
||||
|
||||
# Add ignore column
|
||||
ignore_column = Gtk.TreeViewColumn(_('Mark'),self.bool_renderer,
|
||||
ignore_column = Gtk.TreeViewColumn(_('Mark'), self.bool_renderer,
|
||||
active=VerifyResults.IGNORE_COL)
|
||||
ignore_column.set_sort_column_id(VerifyResults.IGNORE_COL)
|
||||
self.warn_tree.append_column(ignore_column)
|
||||
@@ -588,13 +587,13 @@ class VerifyResults(ManagedWindow):
|
||||
new_ignores[handle].add(rule_id)
|
||||
return new_ignores
|
||||
|
||||
def close(self,*obj):
|
||||
def close(self, *obj):
|
||||
new_ignores = self.get_new_marking()
|
||||
self.save_ignored(new_ignores)
|
||||
|
||||
ManagedWindow.close(self,*obj)
|
||||
|
||||
def hide_toggled(self,button):
|
||||
def hide_toggled(self, button):
|
||||
if button.get_active():
|
||||
button.set_label(_("_Show all"))
|
||||
self.filt_model = self.real_model.filter_new()
|
||||
@@ -608,16 +607,16 @@ class VerifyResults(ManagedWindow):
|
||||
self.warn_tree.set_model(self.sort_model)
|
||||
button.set_label(_("_Hide marked"))
|
||||
|
||||
def selection_toggled(self,cell,path_string):
|
||||
def selection_toggled(self, cell, path_string):
|
||||
sort_path = tuple(map(int, path_string.split(':')))
|
||||
filt_path = self.sort_model.convert_path_to_child_path(sort_path)
|
||||
filt_path = self.sort_model.convert_path_to_child_path(Gtk.TreePath(sort_path))
|
||||
real_path = self.filt_model.convert_path_to_child_path(filt_path)
|
||||
row = self.real_model[real_path]
|
||||
row[VerifyResults.IGNORE_COL] = not row[VerifyResults.IGNORE_COL]
|
||||
row[VerifyResults.SHOW_COL] = not row[VerifyResults.IGNORE_COL]
|
||||
self.real_model.row_changed(real_path,row.iter)
|
||||
|
||||
def mark_clicked(self,mark_button):
|
||||
def mark_clicked(self, mark_button):
|
||||
for row_num in range(len(self.real_model)):
|
||||
path = (row_num,)
|
||||
row = self.real_model[path]
|
||||
@@ -625,7 +624,7 @@ class VerifyResults(ManagedWindow):
|
||||
row[VerifyResults.SHOW_COL] = False
|
||||
self.filt_model.refilter()
|
||||
|
||||
def unmark_clicked(self,unmark_button):
|
||||
def unmark_clicked(self, unmark_button):
|
||||
for row_num in range(len(self.real_model)):
|
||||
path = (row_num,)
|
||||
row = self.real_model[path]
|
||||
@@ -633,7 +632,7 @@ class VerifyResults(ManagedWindow):
|
||||
row[VerifyResults.SHOW_COL] = True
|
||||
self.filt_model.refilter()
|
||||
|
||||
def invert_clicked(self,invert_button):
|
||||
def invert_clicked(self, invert_button):
|
||||
for row_num in range(len(self.real_model)):
|
||||
path = (row_num,)
|
||||
row = self.real_model[path]
|
||||
@@ -641,7 +640,7 @@ class VerifyResults(ManagedWindow):
|
||||
row[VerifyResults.SHOW_COL] = not row[VerifyResults.SHOW_COL]
|
||||
self.filt_model.refilter()
|
||||
|
||||
def double_click(self, obj,event):
|
||||
def double_click(self, obj, event):
|
||||
if event.type == Gdk.EventType._2BUTTON_PRESS and event.button == 1:
|
||||
(model, node) = self.selection.get_selected()
|
||||
if not node:
|
||||
|
||||
@@ -32,6 +32,7 @@ Each object can be operated on with the following actions:
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
if sys.version_info[0] < 3:
|
||||
import cPickle as pickle
|
||||
else:
|
||||
@@ -171,6 +172,12 @@ def user_page(request, username=None):
|
||||
else:
|
||||
raise Http404(_("Requested page is not accessible."))
|
||||
|
||||
def timestamp():
|
||||
"""
|
||||
Construct a string of current time for filenames.
|
||||
"""
|
||||
return time.strftime("%Y-%m-%d:%H:%M:%S")
|
||||
|
||||
def send_file(request, filename, mimetype):
|
||||
"""
|
||||
Send a file through Django without loading the whole file into
|
||||
@@ -215,17 +222,18 @@ def process_report_run(request, handle):
|
||||
args[key] = value
|
||||
#############################################################################
|
||||
if report.report_type == "report":
|
||||
filename = "/tmp/%s-%s.%s" % (str(profile.user.username), str(handle), args["off"])
|
||||
filename = "/tmp/%s-%s-%s.%s" % (str(profile.user.username), str(handle), timestamp(), args["off"])
|
||||
run_report(db, handle, of=filename, **args)
|
||||
mimetype = 'application/%s' % args["off"]
|
||||
elif report.report_type == "export":
|
||||
filename = "/tmp/%s-%s.%s" % (str(profile.user.username), str(handle), args["off"])
|
||||
filename = "/tmp/%s-%s-%s.%s" % (str(profile.user.username), str(handle), timestamp(), args["off"])
|
||||
export_file(db, filename, gramps.cli.user.User()) # callback
|
||||
mimetype = 'text/plain'
|
||||
elif report.report_type == "import":
|
||||
filename = download(args["i"], "/tmp/%s-%s.%s" % (str(profile.user.username),
|
||||
str(handle),
|
||||
args["iff"]))
|
||||
filename = download(args["i"], "/tmp/%s-%s-%s.%s" % (str(profile.user.username),
|
||||
str(handle),
|
||||
timestamp(),
|
||||
args["iff"]))
|
||||
if filename is not None:
|
||||
if True: # run in background, with error handling
|
||||
import threading
|
||||
@@ -248,12 +256,17 @@ def process_report_run(request, handle):
|
||||
else:
|
||||
make_message(request, "Invalid report type '%s'" % report.report_type)
|
||||
return redirect("/report/")
|
||||
if os.path.exists(filename):
|
||||
return send_file(request, filename, mimetype)
|
||||
# need to wait for the file to exist:
|
||||
start = time.time()
|
||||
while not os.path.exists(filename):
|
||||
# but let's not wait forever:
|
||||
if time.time() - start > 10: # after 10 seconds, give up!
|
||||
context = RequestContext(request)
|
||||
make_message(request, "Failed: '%s' is not found" % filename)
|
||||
return redirect("/report/")
|
||||
time.sleep(1)
|
||||
return send_file(request, filename, mimetype)
|
||||
else:
|
||||
context = RequestContext(request)
|
||||
make_message(request, "Failed: '%s' is not found" % filename)
|
||||
return redirect("/report/")
|
||||
# If failure, just fail for now:
|
||||
context = RequestContext(request)
|
||||
context["message"] = "You need to be logged in."
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Gramps</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>Trunk, (C) 1997-2012 The Gramps Team http://www.gramps-project.org</string>
|
||||
<string>4.0.0-alpha1, (C) 1997-2012 The Gramps Team http://www.gramps-project.org</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>gramps.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -15,13 +15,13 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<string>4.0.0-alpha1</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>Trunk</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>Trunk</string>
|
||||
<string>4.0.0-alpha1</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright 1997 - 2012 The Gramps Team, GNU General Public License.</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
|
||||
+47
-33
@@ -6,6 +6,9 @@
|
||||
<destination overwrite="yes">${env:HOME}/Desktop</destination>
|
||||
<run-install-name-tool/>
|
||||
<launcher-script>${project}/gramps.launcher</launcher-script >
|
||||
<!-- Indicate the active gtk version to use. This is needed only
|
||||
for gtk+-3.0 projects. -->
|
||||
<gtk>gtk+-3.0</gtk>
|
||||
</meta>
|
||||
|
||||
<plist>${project}/Info.plist</plist>
|
||||
@@ -27,23 +30,18 @@
|
||||
<binary>
|
||||
${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/
|
||||
</binary>
|
||||
<!-- Copy in the theme engines. -->
|
||||
<!-- Copy in the input methods. Dunno if they actually work with OSX. -->
|
||||
<binary>
|
||||
${prefix}/lib/gtk-2.0/${pkg:gtk+-2.0:gtk_binary_version}/engines/*.so
|
||||
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
|
||||
</binary>
|
||||
|
||||
<!-- And the print backends -->
|
||||
<binary>
|
||||
${prefix}/lib/gtk-2.0/${pkg:gtk+-2.0:gtk_binary_version}/printbackends/*.so
|
||||
${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/pango-basic-fc.so
|
||||
</binary>
|
||||
|
||||
<!-- Copy in libpyglib, which will pull in other dependencies we need -->
|
||||
<binary>
|
||||
${prefix}/lib/libpyglib-2.0-python.0.dylib
|
||||
${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/*.so
|
||||
</binary>
|
||||
|
||||
<binary recurse="True">
|
||||
@@ -59,15 +57,7 @@
|
||||
</binary-->
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/libgoocanvas.3.dylib
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/libgtkmacintegration.0.dylib
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/libart_lgpl_2.2.dylib
|
||||
${prefix}/lib/libgtkmacintegration.2.dylib
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
@@ -87,7 +77,7 @@
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
${prefix}/lib/libosmgpsmap.2.dylib
|
||||
${prefix}/lib/libosmgpsmap.3.dylib
|
||||
</binary>
|
||||
|
||||
<binary>
|
||||
@@ -110,7 +100,27 @@
|
||||
want to copy in to the bundle. The "dest" attribute is
|
||||
optional, as usual. Bundler will find all translations of that
|
||||
library/program under the indicated directory and copy them.-->
|
||||
<translations name="gtk20">
|
||||
<translations name="gtk30">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
<translations name="gtk30-properties">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
<translations name="glib20">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
<translations name="gdk-pixbuf">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
<translations name="atk10">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
<translations name="gtkspell3">
|
||||
${prefix}/share/locale
|
||||
</translations>
|
||||
|
||||
@@ -121,6 +131,10 @@
|
||||
|
||||
<!-- We have to pull in the python modules, which are mixed python
|
||||
and loadable modules. -->
|
||||
<data>
|
||||
${prefix}/share/glib-2.0/schemas
|
||||
</data>
|
||||
|
||||
<data recurse="True">
|
||||
${prefix}/lib/python2.7/*.py
|
||||
</data>
|
||||
@@ -133,10 +147,6 @@
|
||||
${prefix}/include/python2.7/pyconfig.h
|
||||
</data>
|
||||
|
||||
<data>
|
||||
${prefix}/share/gramps/
|
||||
</data>
|
||||
|
||||
<!--data>
|
||||
${prefix}/share/webkit-1.0/
|
||||
</data-->
|
||||
@@ -149,6 +159,18 @@
|
||||
${prefix}/share/mime/
|
||||
</data>
|
||||
|
||||
<data recurse="True">
|
||||
${prefix}/lib/python2.7/site-packages/gramps/*.glade
|
||||
</data>
|
||||
|
||||
<data>
|
||||
${prefix}/lib/python2.7/site-packages/gramps/data/
|
||||
</data>
|
||||
|
||||
<data recurse="True">
|
||||
${prefix}/lib/python2.7/site-packages/gramps/images/*.png
|
||||
</data>
|
||||
|
||||
<data>
|
||||
${prefix}/share/mime-info/
|
||||
</data>
|
||||
@@ -171,15 +193,7 @@
|
||||
${project}/gramps.icns
|
||||
</data>
|
||||
|
||||
<!-- This is where theme commands go. You can copy them in from your
|
||||
theme of choice if they provide and example, or you can just
|
||||
change the source path. -->
|
||||
|
||||
<data dest="${bundle}/Contents/Resources/etc/gtk-2.0/gtkrc">
|
||||
${project}/gtkrc
|
||||
</data>
|
||||
|
||||
<data dest="${bundle}/Contents/Resources/share/gramps/data/gramps.accel">
|
||||
<data dest="${bundle}/Contents/Resources/lib/python2.7/site-packages/gramps/data/gramps.accel">
|
||||
${project}/gramps.accel
|
||||
</data>
|
||||
|
||||
|
||||
+4
-7
@@ -21,9 +21,8 @@ export GTK_EXE_PREFIX="$bundle_res"
|
||||
export GTK_PATH="$bundle_res"
|
||||
|
||||
export PANGO_RC_FILE="$bundle_etc/pango/pangorc"
|
||||
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
|
||||
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
|
||||
export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
|
||||
export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-3.0/gdk-pixbuf.loaders"
|
||||
export GTK_IM_MODULE_FILE="$bundle_etc/gtk-3.0/gtk.immodules"
|
||||
export GVBINDIR="$bundle_lib/graphviz"
|
||||
|
||||
|
||||
@@ -31,10 +30,8 @@ export GVBINDIR="$bundle_lib/graphviz"
|
||||
PYVER=2.7
|
||||
export PYTHON="$bundle_contents/MacOS/python"
|
||||
export PYTHONHOME="$bundle_res"
|
||||
PYTHONPATH="$bundle_lib/python$PYVER/site-packages/pyenchant-1.6.1-py$PYVER.egg:$PYTHONPATH"
|
||||
export PYTHONPATH="$bundle_lib/python$PYVER/site-packages/gtk-2.0:$PYTHONPATH"
|
||||
|
||||
export GRAMPSDIR="$bundle_data"/gramps
|
||||
export GRAMPSDIR="$bundle_lib/python$PYVER/site-packages/gramps"
|
||||
export GRAMPSI18N="$bundle_data"/locale
|
||||
export GRAMPSHOME="$HOME/Library/Application Support"
|
||||
|
||||
@@ -42,5 +39,5 @@ export GRAMPSHOME="$HOME/Library/Application Support"
|
||||
if /bin/expr "x$1" : '^x-psn_' > /dev/null; then
|
||||
shift 1
|
||||
fi
|
||||
exec "$PYTHON" -O "$GRAMPSDIR/gramps.py" "$@"
|
||||
exec "$PYTHON" -O "$bundle_contents/MacOS/Gramps-bin" "$@"
|
||||
|
||||
|
||||
+27
-7
@@ -60,7 +60,7 @@ gtk-mac-bundler gtk-osx-build/projects/gramps/gramps.bundle
|
||||
|
||||
|
||||
<include href="http://git.gnome.org/browse/gtk-osx/plain/modulesets-stable/gtk-osx.modules"/>
|
||||
<!--include href="/Users/john/Development/GTK-OSX/gtk-osx-build/modulesets-stable/gtk-osx.modules"/-->
|
||||
<!--include href="/Users/john/GTK-OSX/gtk-osx-build/modulesets-stable/gtk-osx.modules"/-->
|
||||
|
||||
|
||||
|
||||
@@ -81,6 +81,24 @@ gtk-mac-bundler gtk-osx-build/projects/gramps/gramps.bundle
|
||||
</after>
|
||||
</distutils>
|
||||
|
||||
<distutils id="gramps-40">
|
||||
<branch module="gramps/gramps-4.0.0-alpha1.tar.gz" version="4.0.0-alpha1"
|
||||
repo="sourceforge"/>
|
||||
<dependencies>
|
||||
<dep package="meta-gtk-osx-python-gtk3"/>
|
||||
<dep package="librsvg"/>
|
||||
<dep package="shared-mime-info"/>
|
||||
<dep package="hunspell"/>
|
||||
<dep package="gtkspell3"/>
|
||||
<dep package="osmgpsmap"/>
|
||||
<dep package="graphviz"/>
|
||||
<dep package="pil"/>
|
||||
</dependencies>
|
||||
<after>
|
||||
<dep package="pyexiv2"/>
|
||||
</after>
|
||||
</distutils>
|
||||
|
||||
<distutils id="gramps-addons-svn">
|
||||
<branch module="gramps-addons/trunk/contrib"
|
||||
repo="gramps-addons"/>
|
||||
@@ -127,17 +145,19 @@ gtk-mac-bundler gtk-osx-build/projects/gramps/gramps.bundle
|
||||
version="0.7.3"/>
|
||||
<dependencies>
|
||||
<dep package="osmgpsmap"/>
|
||||
<dep package="pygtk"/>
|
||||
<dep package="pycairo-python2.6"/>
|
||||
<dep package="pygobject"/>
|
||||
</dependencies>
|
||||
<after>
|
||||
<dep package="pygtk"/>
|
||||
<dep package="pygobject"/>
|
||||
<dep package="pygobject3"/>
|
||||
<dep package="pycairo-python2.6"/>
|
||||
<dep package="pycairo-python3"/>
|
||||
</after>
|
||||
</distutils>
|
||||
|
||||
<autotools id="graphviz" autogenargs="--disable-sharp --disable-guile --disable-java --disable-lua --disable-ocaml --disable-perl --disable-php --disable-r --disable-ruby --disable-tcl --with-pangocairo=yes --with-freetype2=no --with-fontconfig=no --with-included-ltdl=yes">
|
||||
<autotools id="graphviz" autogenargs="--disable-sharp --disable-guile --disable-java --disable-lua --disable-ocaml --disable-perl --disable-php --disable-r --disable-ruby --disable-tcl --with-pangocairo=no --with-freetype2=no --with-fontconfig=no --with-included-ltdl=yes">
|
||||
<branch module="graphviz-2.28.0.tar.gz" version="2.28.0" repo="graphviz"/>
|
||||
<dependencies>
|
||||
<dep package="meta-gtk-osx-freetype"/>
|
||||
<dep package="pango"/>
|
||||
<dep package="zlib"/>
|
||||
</dependencies>
|
||||
</autotools>
|
||||
|
||||
+436
-436
@@ -41,558 +41,558 @@ all_coverage = {}
|
||||
all_template_coverage = {}
|
||||
|
||||
def strip_quotes(st):
|
||||
if len(st) >= 2 and st[0] == '"' and st[len(st)-1] == '"':
|
||||
st = st.strip()[1:-1]
|
||||
return st
|
||||
if len(st) >= 2 and st[0] == '"' and st[len(st)-1] == '"':
|
||||
st = st.strip()[1:-1]
|
||||
return st
|
||||
|
||||
class CheckException( Exception ):
|
||||
pass
|
||||
pass
|
||||
|
||||
# This is a base class for all checks
|
||||
class Check:
|
||||
def __init__( self ):
|
||||
self.msgs = []
|
||||
def diag( self ):
|
||||
if len( self.msgs ):
|
||||
print
|
||||
print self.diag_header
|
||||
for m in self.msgs:
|
||||
m.diag()
|
||||
def summary( self ):
|
||||
print "%-20s%d" % ( self.summary_text, len(self.msgs) )
|
||||
def __init__( self ):
|
||||
self.msgs = []
|
||||
def diag( self ):
|
||||
if len( self.msgs ):
|
||||
print
|
||||
print(self.diag_header)
|
||||
for m in self.msgs:
|
||||
m.diag()
|
||||
def summary( self ):
|
||||
print("%-20s%d" % ( self.summary_text, len(self.msgs) ))
|
||||
|
||||
class Check_fmt( Check ):
|
||||
def __init__( self, fmt ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %s mismatches --------------" % fmt
|
||||
self.summary_text = "%s mismatches:" % fmt
|
||||
self.fmt = fmt
|
||||
def __init__( self, fmt ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %s mismatches --------------" % fmt
|
||||
self.summary_text = "%s mismatches:" % fmt
|
||||
self.fmt = fmt
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
cnt1 = msgid.count( self.fmt )
|
||||
cnt2 = msgstr.count( self.fmt )
|
||||
if cnt1 != cnt2:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
cnt1 = msgid.count( self.fmt )
|
||||
cnt2 = msgstr.count( self.fmt )
|
||||
if cnt1 != cnt2:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_named_fmt( Check ):
|
||||
# A pattern to find all %()
|
||||
find_named_fmt_pat = re.compile('% \( \w+ \) \d* \D', re.VERBOSE)
|
||||
# A pattern to find all %()
|
||||
find_named_fmt_pat = re.compile('% \( \w+ \) \d* \D', re.VERBOSE)
|
||||
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() name mismatches --------------"
|
||||
self.summary_text = "%() name mismatches:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() name mismatches --------------"
|
||||
self.summary_text = "%() name mismatches:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Same number of named formats?
|
||||
fmts1 = self.find_named_fmt_pat.findall( msgid )
|
||||
fmts2 = self.find_named_fmt_pat.findall( msgstr )
|
||||
if len( fmts1 ) != len( fmts2 ):
|
||||
self.msgs.append( msg )
|
||||
else:
|
||||
# Do we have the same named formats?
|
||||
fmts1.sort()
|
||||
fmts2.sort()
|
||||
if fmts1 != fmts2:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Same number of named formats?
|
||||
fmts1 = self.find_named_fmt_pat.findall( msgid )
|
||||
fmts2 = self.find_named_fmt_pat.findall( msgstr )
|
||||
if len( fmts1 ) != len( fmts2 ):
|
||||
self.msgs.append( msg )
|
||||
else:
|
||||
# Do we have the same named formats?
|
||||
fmts1.sort()
|
||||
fmts2.sort()
|
||||
if fmts1 != fmts2:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_missing_sd( Check ):
|
||||
# A pattern to find %() without s or d
|
||||
# Here is a command to use for testing
|
||||
# print re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE).findall( '%(event_name)s: %(place)s%(endnotes)s. ' )
|
||||
find_named_fmt_pat2 = re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE)
|
||||
# A pattern to find %() without s or d
|
||||
# Here is a command to use for testing
|
||||
# print(re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE).findall( '%(event_name)s: %(place)s%(endnotes)s. ' ))
|
||||
find_named_fmt_pat2 = re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE)
|
||||
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() without 's' or 'd' mismatches --------------"
|
||||
self.summary_text = "%() missing s/d:"
|
||||
def process( self, msg ):
|
||||
for msgstr in msg.msgstr:
|
||||
fmts = self.find_named_fmt_pat2.findall( msgstr )
|
||||
for f in fmts:
|
||||
if not f in ('s', 'd'):
|
||||
self.msgs.append( msg )
|
||||
break
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() without 's' or 'd' mismatches --------------"
|
||||
self.summary_text = "%() missing s/d:"
|
||||
def process( self, msg ):
|
||||
for msgstr in msg.msgstr:
|
||||
fmts = self.find_named_fmt_pat2.findall( msgstr )
|
||||
for f in fmts:
|
||||
if not f in ('s', 'd'):
|
||||
self.msgs.append( msg )
|
||||
break
|
||||
|
||||
class Check_runaway( Check ):
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- Runaway context in translation ---------"
|
||||
self.summary_text = "Runaway context:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- Runaway context in translation ---------"
|
||||
self.summary_text = "Runaway context:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Runaway context. In the translated part we only to see
|
||||
# the translation of the word after the |
|
||||
if msgid.count('|') > 0 and msgstr.count('|') > 0 and msgid != msgstr:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Runaway context. In the translated part we only to see
|
||||
# the translation of the word after the |
|
||||
if msgid.count('|') > 0 and msgstr.count('|') > 0 and msgid != msgstr:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_xml_chars( Check ):
|
||||
# Special XML characters
|
||||
# It is not allowed to have a quote, an ampersand or an angle bracket
|
||||
xml_chars_pat = re.compile( r'<(?!(b>|/b>|i>|/i>|br/>)) | (?<=!(<b|/b|<i|/i|r/))> | " | & (?!(quot|nbsp|gt|amp);)', re.VERBOSE )
|
||||
# Special XML characters
|
||||
# It is not allowed to have a quote, an ampersand or an angle bracket
|
||||
xml_chars_pat = re.compile( r'<(?!(b>|/b>|i>|/i>|br/>)) | (?<=!(<b|/b|<i|/i|r/))> | " | & (?!(quot|nbsp|gt|amp);)', re.VERBOSE )
|
||||
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- unescaped XML special characters ---------"
|
||||
self.summary_text = "XML special chars:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- unescaped XML special characters ---------"
|
||||
self.summary_text = "XML special chars:"
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
|
||||
# XML errors
|
||||
# Only look at messages in the tips.xml
|
||||
if msg.is_tips_xml:
|
||||
if self.xml_chars_pat.search( msgstr ):
|
||||
self.msgs.append( msg )
|
||||
# XML errors
|
||||
# Only look at messages in the tips.xml
|
||||
if msg.is_tips_xml:
|
||||
if self.xml_chars_pat.search( msgstr ):
|
||||
self.msgs.append( msg )
|
||||
|
||||
class Check_last_char( Check ):
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- last character not identical ---------"
|
||||
self.summary_text = "Last character:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- last character not identical ---------"
|
||||
self.summary_text = "Last character:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
msgid_last = msgid[-1:]
|
||||
msgstr_last = msgstr[-1:]
|
||||
if msgid_last.isspace() != msgstr_last.isspace():
|
||||
self.msgs.append( msg )
|
||||
elif (msgid_last == '.') != (msgstr_last == '.'):
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
msgid_last = msgid[-1:]
|
||||
msgstr_last = msgstr[-1:]
|
||||
if msgid_last.isspace() != msgstr_last.isspace():
|
||||
self.msgs.append( msg )
|
||||
elif (msgid_last == '.') != (msgstr_last == '.'):
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
# Last character of msgid? White space? Period?
|
||||
if msg.is_fuzzy:
|
||||
return
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
# Last character of msgid? White space? Period?
|
||||
if msg.is_fuzzy:
|
||||
return
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_shortcut_trans( Check ):
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- shortcut key in translation ---------"
|
||||
self.summary_text = "Shortcut in msgstr:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- shortcut key in translation ---------"
|
||||
self.summary_text = "Shortcut in msgstr:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
if msgid.count('_') == 0 and msgstr.count('_') > 0:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
if msgid.count('_') == 0 and msgstr.count('_') > 0:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Msgid:
|
||||
fuzzy_pat = re.compile( 'fuzzy' )
|
||||
tips_xml_pat = re.compile( r'tips\.xml' )
|
||||
def __init__( self, msgnr, lineno ):
|
||||
self._msgid = [] # For debugging purpose the original text
|
||||
self._msgidp = [] # For debugging purpose the original text
|
||||
self._msgstr = [] # For debugging purpose the original text
|
||||
self.msgid = ''
|
||||
self.msgidp = ''
|
||||
self.msgstr = [] # This is a list to support plural
|
||||
self._cmnt = []
|
||||
self.nr = msgnr
|
||||
self.lineno = lineno
|
||||
self.is_fuzzy = 0
|
||||
self.is_tips_xml = 0
|
||||
fuzzy_pat = re.compile( 'fuzzy' )
|
||||
tips_xml_pat = re.compile( r'tips\.xml' )
|
||||
def __init__( self, msgnr, lineno ):
|
||||
self._msgid = [] # For debugging purpose the original text
|
||||
self._msgidp = [] # For debugging purpose the original text
|
||||
self._msgstr = [] # For debugging purpose the original text
|
||||
self.msgid = ''
|
||||
self.msgidp = ''
|
||||
self.msgstr = [] # This is a list to support plural
|
||||
self._cmnt = []
|
||||
self.nr = msgnr
|
||||
self.lineno = lineno
|
||||
self.is_fuzzy = 0
|
||||
self.is_tips_xml = 0
|
||||
|
||||
def diag( self ):
|
||||
print
|
||||
print "msg nr: %d, lineno: %d%s" % ( self.nr, self.lineno, self.is_fuzzy and " (fuzzy)" or "" )
|
||||
sys.stdout.write( ''.join( self._msgid ) )
|
||||
sys.stdout.write( ''.join( self._msgidp ) )
|
||||
sys.stdout.write( ''.join( self._msgstr ) )
|
||||
def diag( self ):
|
||||
print
|
||||
print("msg nr: %d, lineno: %d%s" % ( self.nr, self.lineno, self.is_fuzzy and " (fuzzy)" or "" ))
|
||||
sys.stdout.write( ''.join( self._msgid ) )
|
||||
sys.stdout.write( ''.join( self._msgidp ) )
|
||||
sys.stdout.write( ''.join( self._msgstr ) )
|
||||
|
||||
def add_msgid( self, line, lineno ):
|
||||
self._msgid.append( line )
|
||||
line = re.sub( r'msgid\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print "ERROR at line %d: Missing quote." % lineno
|
||||
line = strip_quotes( line )
|
||||
self.msgid += line
|
||||
def add_msgid( self, line, lineno ):
|
||||
self._msgid.append( line )
|
||||
line = re.sub( r'msgid\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print("ERROR at line %d: Missing quote." % lineno)
|
||||
line = strip_quotes( line )
|
||||
self.msgid += line
|
||||
|
||||
def add_msgidp( self, line, lineno ):
|
||||
self._msgidp.append( line )
|
||||
line = re.sub( r'msgid_plural\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print "ERROR at line %d: Missing quote." % lineno
|
||||
line = strip_quotes( line )
|
||||
self.msgidp += line
|
||||
def add_msgidp( self, line, lineno ):
|
||||
self._msgidp.append( line )
|
||||
line = re.sub( r'msgid_plural\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print("ERROR at line %d: Missing quote." % lineno)
|
||||
line = strip_quotes( line )
|
||||
self.msgidp += line
|
||||
|
||||
def add_new_msgstr( self, line, lineno ):
|
||||
self.msgstr.append( '' ) # Start a new msgstr
|
||||
self.add_msgstr( line, lineno )
|
||||
def add_new_msgstr( self, line, lineno ):
|
||||
self.msgstr.append( '' ) # Start a new msgstr
|
||||
self.add_msgstr( line, lineno )
|
||||
|
||||
def add_msgstr( self, line, lineno ):
|
||||
self._msgstr.append( line )
|
||||
line = re.sub( r'msgstr(\[\d\])?\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print "ERROR at line %d: Missing quote." % lineno
|
||||
line = strip_quotes( line )
|
||||
self.msgstr[-1] += line
|
||||
def add_msgstr( self, line, lineno ):
|
||||
self._msgstr.append( line )
|
||||
line = re.sub( r'msgstr(\[\d\])?\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print("ERROR at line %d: Missing quote." % lineno)
|
||||
line = strip_quotes( line )
|
||||
self.msgstr[-1] += line
|
||||
|
||||
def add_cmnt( self, line ):
|
||||
self._cmnt.append( line )
|
||||
if not self.is_fuzzy and self.fuzzy_pat.search( line ):
|
||||
self.is_fuzzy = 1
|
||||
if not self.is_tips_xml and self.tips_xml_pat.search( line ):
|
||||
self.is_tips_xml = 1
|
||||
def add_cmnt( self, line ):
|
||||
self._cmnt.append( line )
|
||||
if not self.is_fuzzy and self.fuzzy_pat.search( line ):
|
||||
self.is_fuzzy = 1
|
||||
if not self.is_tips_xml and self.tips_xml_pat.search( line ):
|
||||
self.is_tips_xml = 1
|
||||
|
||||
def create_new_Msgid( msgs, lineno ):
|
||||
msg = Msgid( len(msgs), lineno )
|
||||
msgs.append( msg )
|
||||
return msg
|
||||
msg = Msgid( len(msgs), lineno )
|
||||
msgs.append( msg )
|
||||
return msg
|
||||
|
||||
def read_msgs( fname ):
|
||||
empty_pat = re.compile( r'^ \s* $', re.VERBOSE )
|
||||
comment_pat = re.compile( r'\#', re.VERBOSE )
|
||||
msgid_pat = re.compile( r'msgid \s+ "', re.VERBOSE )
|
||||
msgid_plural_pat = re.compile( r'msgid_plural \s+ "', re.VERBOSE )
|
||||
msgstr_pat = re.compile( r'msgstr (\[\d\])? \s+ "', re.VERBOSE )
|
||||
str_pat = re.compile( r'"', re.VERBOSE )
|
||||
old_pat = re.compile( r'\#~ \s+ ', re.VERBOSE )
|
||||
empty_pat = re.compile( r'^ \s* $', re.VERBOSE )
|
||||
comment_pat = re.compile( r'\#', re.VERBOSE )
|
||||
msgid_pat = re.compile( r'msgid \s+ "', re.VERBOSE )
|
||||
msgid_plural_pat = re.compile( r'msgid_plural \s+ "', re.VERBOSE )
|
||||
msgstr_pat = re.compile( r'msgstr (\[\d\])? \s+ "', re.VERBOSE )
|
||||
str_pat = re.compile( r'"', re.VERBOSE )
|
||||
old_pat = re.compile( r'\#~ \s+ ', re.VERBOSE )
|
||||
|
||||
f = open( fname )
|
||||
lines = f.readlines()
|
||||
|
||||
# parse it like a statemachine
|
||||
NONE = 'NONE' # Nothing detected, yet
|
||||
CMNT = 'CMNT' # Inside comment part
|
||||
MSGID = 'msgid' # Inside msgid part
|
||||
MSGIDP = 'msgid_plural' # Inside msgid_plural part
|
||||
MSGSTR = 'msgstr' # Inside msgstr part
|
||||
STR = 'STR' # A continuation string
|
||||
OLD = 'OLD' # An old pattern with #~
|
||||
f = open( fname )
|
||||
lines = f.readlines()
|
||||
|
||||
global msgs
|
||||
state = NONE
|
||||
msg = None
|
||||
# parse it like a statemachine
|
||||
NONE = 'NONE' # Nothing detected, yet
|
||||
CMNT = 'CMNT' # Inside comment part
|
||||
MSGID = 'msgid' # Inside msgid part
|
||||
MSGIDP = 'msgid_plural' # Inside msgid_plural part
|
||||
MSGSTR = 'msgstr' # Inside msgstr part
|
||||
STR = 'STR' # A continuation string
|
||||
OLD = 'OLD' # An old pattern with #~
|
||||
|
||||
msgs = []
|
||||
for ix, line in enumerate( lines ): # Use line numbers for messages
|
||||
lineno = ix + 1
|
||||
global msgs
|
||||
state = NONE
|
||||
msg = None
|
||||
|
||||
m = empty_pat.match( line )
|
||||
if m:
|
||||
continue # Empty lines are not interesting
|
||||
msgs = []
|
||||
for ix, line in enumerate( lines ): # Use line numbers for messages
|
||||
lineno = ix + 1
|
||||
|
||||
# What's the next state?
|
||||
if old_pat.match( line ):
|
||||
next_state = OLD
|
||||
elif comment_pat.match( line ):
|
||||
next_state = CMNT
|
||||
elif msgid_pat.match( line ):
|
||||
next_state = MSGID
|
||||
elif msgid_plural_pat.match( line ):
|
||||
next_state = MSGIDP
|
||||
elif msgstr_pat.match( line ):
|
||||
next_state = MSGSTR
|
||||
elif str_pat.match( line ):
|
||||
next_state = STR
|
||||
else:
|
||||
print 'WARNING: Unexpected input at %(fname)s:%(lineno)d' % vars()
|
||||
next_state = NONE
|
||||
m = empty_pat.match( line )
|
||||
if m:
|
||||
continue # Empty lines are not interesting
|
||||
|
||||
#print "%(state)d->%(next_state)d\t%(line)s" % vars()
|
||||
if state == NONE:
|
||||
# expect msgid or comment or old stuff
|
||||
if next_state == CMNT:
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_cmnt( line )
|
||||
# What's the next state?
|
||||
if old_pat.match( line ):
|
||||
next_state = OLD
|
||||
elif comment_pat.match( line ):
|
||||
next_state = CMNT
|
||||
elif msgid_pat.match( line ):
|
||||
next_state = MSGID
|
||||
elif msgid_plural_pat.match( line ):
|
||||
next_state = MSGIDP
|
||||
elif msgstr_pat.match( line ):
|
||||
next_state = MSGSTR
|
||||
elif str_pat.match( line ):
|
||||
next_state = STR
|
||||
else:
|
||||
print('WARNING: Unexpected input at %(fname)s:%(lineno)d' % vars())
|
||||
next_state = NONE
|
||||
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
#print("%(state)d->%(next_state)d\t%(line)s" % vars())
|
||||
if state == NONE:
|
||||
# expect msgid or comment or old stuff
|
||||
if next_state == CMNT:
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_cmnt( line )
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
print 'WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars()
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
print 'WARNING: Wild string at %(fname)s:%(lineno)d' % vars()
|
||||
elif next_state == MSGSTR:
|
||||
print('WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars())
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
print('WARNING: Wild string at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
pass # Just skip
|
||||
|
||||
elif state == CMNT:
|
||||
# Expect more comment, or msgid. If msgstr or string it is flagged as error.
|
||||
if next_state == CMNT:
|
||||
if msg:
|
||||
msg.add_cmnt( line )
|
||||
else:
|
||||
# Note. We may need to do something about these comments
|
||||
# Skip for now
|
||||
pass
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
if not msg:
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
elif state == CMNT:
|
||||
# Expect more comment, or msgid. If msgstr or string it is flagged as error.
|
||||
if next_state == CMNT:
|
||||
if msg:
|
||||
msg.add_cmnt( line )
|
||||
else:
|
||||
# Note. We may need to do something about these comments
|
||||
# Skip for now
|
||||
pass
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
if not msg:
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
print 'WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars()
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
print 'WARNING: Wild string at %(fname)s:%(lineno)d' % vars()
|
||||
elif next_state == MSGSTR:
|
||||
print('WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars())
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
print('WARNING: Wild string at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
elif state == MSGID:
|
||||
# Expect msgstr or msgid_plural or string
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print 'WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars()
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif state == MSGID:
|
||||
# Expect msgstr or msgid_plural or string
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print('WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
state = MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
state = MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid, stay in state MSGID
|
||||
msg.add_msgid( line, lineno )
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid, stay in state MSGID
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
elif state == MSGIDP:
|
||||
# Expect msgstr or string or comment
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print 'WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars()
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif state == MSGIDP:
|
||||
# Expect msgstr or string or comment
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print('WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid_plural, stay in state MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid_plural, stay in state MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
elif state == MSGSTR:
|
||||
# Expect comment, or msgid, or string.
|
||||
if next_state == CMNT:
|
||||
# A comment probably starts a new item
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_cmnt( line )
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_msgid( line, lineno )
|
||||
elif state == MSGSTR:
|
||||
# Expect comment, or msgid, or string.
|
||||
if next_state == CMNT:
|
||||
# A comment probably starts a new item
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_cmnt( line )
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
# New msgstr, probably for plural form
|
||||
# Stay in MSGSTR state
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
msg.add_msgstr( line, lineno )
|
||||
elif next_state == MSGSTR:
|
||||
# New msgstr, probably for plural form
|
||||
# Stay in MSGSTR state
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
msg.add_msgstr( line, lineno )
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
# Strip items with just comments. (Can this happen?)
|
||||
msgs1 = []
|
||||
for m in msgs:
|
||||
if not m.msgid and not m.msgstr:
|
||||
#print "INFO: No msgid or msgstr at %s:%s" % ( fname, m.lineno )
|
||||
pass
|
||||
else:
|
||||
msgs1.append( m )
|
||||
msgs = msgs1
|
||||
return msgs
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
# Strip items with just comments. (Can this happen?)
|
||||
msgs1 = []
|
||||
for m in msgs:
|
||||
if not m.msgid and not m.msgstr:
|
||||
#print("INFO: No msgid or msgstr at %s:%s" % ( fname, m.lineno ))
|
||||
pass
|
||||
else:
|
||||
msgs1.append( m )
|
||||
msgs = msgs1
|
||||
return msgs
|
||||
|
||||
def analyze_msgs( args, fname, msgs, nr_templates = None, nth = 0 ):
|
||||
nr_fuzzy = 0
|
||||
nr_untranslated = 0
|
||||
nr_fuzzy = 0
|
||||
nr_untranslated = 0
|
||||
|
||||
checks = []
|
||||
checks.append( Check_fmt( '%s' ) )
|
||||
checks.append( Check_fmt( '%d' ) )
|
||||
checks.append( Check_named_fmt() )
|
||||
checks.append( Check_missing_sd() )
|
||||
checks.append( Check_runaway() )
|
||||
checks.append( Check_xml_chars() )
|
||||
checks.append( Check_last_char() )
|
||||
checks.append( Check_shortcut_trans() )
|
||||
checks = []
|
||||
checks.append( Check_fmt( '%s' ) )
|
||||
checks.append( Check_fmt( '%d' ) )
|
||||
checks.append( Check_named_fmt() )
|
||||
checks.append( Check_missing_sd() )
|
||||
checks.append( Check_runaway() )
|
||||
checks.append( Check_xml_chars() )
|
||||
checks.append( Check_last_char() )
|
||||
checks.append( Check_shortcut_trans() )
|
||||
|
||||
for msg in msgs:
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr
|
||||
#print
|
||||
#print "msgid: %(msgid)s" % vars()
|
||||
#print "msgstr: %(msgstr)s" % vars()
|
||||
for msg in msgs:
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr
|
||||
#print
|
||||
#print("msgid: %(msgid)s" % vars())
|
||||
#print("msgstr: %(msgstr)s" % vars())
|
||||
|
||||
if ''.join(msgstr) == '':
|
||||
nr_untranslated += 1
|
||||
continue
|
||||
if ''.join(msgstr) == '':
|
||||
nr_untranslated += 1
|
||||
continue
|
||||
|
||||
if msg.is_fuzzy:
|
||||
nr_fuzzy += 1
|
||||
continue
|
||||
if msg.is_fuzzy:
|
||||
nr_fuzzy += 1
|
||||
continue
|
||||
|
||||
for c in checks:
|
||||
c.process( msg )
|
||||
for c in checks:
|
||||
c.process( msg )
|
||||
|
||||
nr_msgs = len(msgs)
|
||||
if nth > 0:
|
||||
print
|
||||
print "====================================="
|
||||
print "%-20s%s" % ( "File:", fname )
|
||||
print "%-20s%d" % ( "Template total:", nr_templates )
|
||||
print "%-20s%d" % ( "PO total:", nr_msgs )
|
||||
print "%-20s%d" % ( "Fuzzy:", nr_fuzzy )
|
||||
print "%-20s%d" % ( "Untranslated:", nr_untranslated )
|
||||
nr_msgs = len(msgs)
|
||||
if nth > 0:
|
||||
print
|
||||
print("=====================================")
|
||||
print("%-20s%s" % ( "File:", fname ))
|
||||
print("%-20s%d" % ( "Template total:", nr_templates ))
|
||||
print("%-20s%d" % ( "PO total:", nr_msgs ))
|
||||
print("%-20s%d" % ( "Fuzzy:", nr_fuzzy ))
|
||||
print("%-20s%d" % ( "Untranslated:", nr_untranslated ))
|
||||
|
||||
for c in checks:
|
||||
c.summary()
|
||||
for c in checks:
|
||||
c.summary()
|
||||
|
||||
po_coverage = (1.0 - (float(nr_untranslated) / float(nr_msgs))) * 100
|
||||
print "%-20s%5.2f%%" % ( "PO Coverage:", po_coverage )
|
||||
po_coverage = (1.0 - (float(nr_untranslated) / float(nr_msgs))) * 100
|
||||
print("%-20s%5.2f%%" % ( "PO Coverage:", po_coverage ))
|
||||
|
||||
template_coverage = po_coverage * float(nr_msgs) / float(nr_templates)
|
||||
print "%-20s%5.2f%%" % ( "Template Coverage:", template_coverage )
|
||||
template_coverage = po_coverage * float(nr_msgs) / float(nr_templates)
|
||||
print("%-20s%5.2f%%" % ( "Template Coverage:", template_coverage ))
|
||||
|
||||
not_displayed = nr_untranslated + nr_fuzzy
|
||||
translation = (1.0 - (float(not_displayed) / float(nr_templates))) * 100
|
||||
text = "%-20s%5.2f%%" % ( "Localized at:", translation)
|
||||
not_displayed = nr_untranslated + nr_fuzzy
|
||||
translation = (1.0 - (float(not_displayed) / float(nr_templates))) * 100
|
||||
text = "%-20s%5.2f%%" % ( "Localized at:", translation)
|
||||
|
||||
if template_coverage == po_coverage:
|
||||
print text
|
||||
else:
|
||||
print text + ' (previous gramps.pot)'
|
||||
if int(template_coverage*1000) == int(po_coverage*1000):
|
||||
print(text)
|
||||
else:
|
||||
print(text + ' (previous gramps.pot)')
|
||||
|
||||
for c in checks:
|
||||
c.diag()
|
||||
for c in checks:
|
||||
c.diag()
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
parser = ArgumentParser( description='This program validates a PO file for GRAMPS.')
|
||||
|
||||
|
||||
parser.add_argument("-s", dest="summary",
|
||||
choices=[file for file in os.listdir('.') if file.endswith('.po')],
|
||||
choices=[file for file in os.listdir('.') if file.endswith('.po')],
|
||||
default=False, help="the summary of check, and if need, it gives details")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
if args.summary:
|
||||
files = sys.argv[2:]
|
||||
|
||||
try:
|
||||
pot_msgs = read_msgs( 'gramps.pot' )
|
||||
nr_templates = len( pot_msgs )
|
||||
nth = 0
|
||||
for fname in files:
|
||||
msgs = read_msgs( fname )
|
||||
analyze_msgs( files, fname, msgs, nr_templates, nth )
|
||||
nth += 1
|
||||
try:
|
||||
pot_msgs = read_msgs( 'gramps.pot' )
|
||||
nr_templates = len( pot_msgs )
|
||||
nth = 0
|
||||
for fname in files:
|
||||
msgs = read_msgs( fname )
|
||||
analyze_msgs( files, fname, msgs, nr_templates, nth )
|
||||
nth += 1
|
||||
|
||||
except CheckException, e:
|
||||
print 'Oops.', e
|
||||
print 'Bailing out'
|
||||
except CheckException as e:
|
||||
print('Oops.', e)
|
||||
print('Bailing out')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
+888
-54
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,7 @@ if sys.version_info[0] < 3:
|
||||
import commands
|
||||
from stat import ST_MODE
|
||||
|
||||
VERSION = '4.0.0-alpha1'
|
||||
VERSION = '4.0.0-alpha3'
|
||||
ALL_LINGUAS = ('bg', 'ca', 'cs', 'da', 'de', 'el', 'en_GB', 'es', 'fi', 'fr', 'he',
|
||||
'hr', 'hu', 'it', 'ja', 'lt', 'nb', 'nl', 'nn', 'pl', 'pt_BR',
|
||||
'pt_PT', 'ru', 'sk', 'sl', 'sq', 'sv', 'uk', 'vi', 'zh_CN')
|
||||
@@ -87,8 +87,10 @@ def build_trans(build_cmd):
|
||||
data_files = build_cmd.distribution.data_files
|
||||
for lang in ALL_LINGUAS:
|
||||
po_file = os.path.join('po', lang + '.po')
|
||||
mo_file = os.path.join(build_cmd.build_base, 'mo', lang, 'gramps.mo')
|
||||
mo_file_unix = build_cmd.build_base + '/mo/' + lang + '/gramps.mo'
|
||||
mo_file = os.path.join(build_cmd.build_base, 'mo', lang, 'LC_MESSAGES',
|
||||
'gramps.mo')
|
||||
mo_file_unix = (build_cmd.build_base + '/mo/' + lang +
|
||||
'/LC_MESSAGES/gramps.mo')
|
||||
mo_dir = os.path.dirname(mo_file)
|
||||
if not(os.path.isdir(mo_dir) or os.path.islink(mo_dir)):
|
||||
os.makedirs(mo_dir)
|
||||
@@ -231,24 +233,24 @@ def write_gramps_script(install_cmd, build_scripts):
|
||||
log.info('changing mode of %s to %o', filename, mode)
|
||||
os.chmod(filename, mode)
|
||||
|
||||
def write_const_py(install_cmd):
|
||||
def write_const_py(command):
|
||||
'''
|
||||
Write the const.py file.
|
||||
'''
|
||||
const_py_in = os.path.join('gramps', 'gen', 'const.py.in')
|
||||
const_py = os.path.join('gramps', 'gen', 'const.py')
|
||||
if hasattr(install_cmd, 'install_data'):
|
||||
if hasattr(command, 'install_data'):
|
||||
#during install
|
||||
prefix = "'%s'" % install_cmd.install_data
|
||||
sysconfdir = "'%s'" % os.path.join(install_cmd.install_data, 'etc') # Is this correct?
|
||||
locale_dir = os.path.join(command.install_data, 'share', 'locale')
|
||||
else:
|
||||
#in build
|
||||
prefix = 'os.path.join(os.path.dirname(__file__), os.pardir)'
|
||||
sysconfdir = prefix + ' + "' + os.sep + 'etc"' # Is this correct?
|
||||
if 'install' in command.distribution.command_obj:
|
||||
# Prevent overwriting version created during install
|
||||
return
|
||||
locale_dir = os.path.join(command.build_base, 'mo')
|
||||
|
||||
subst_vars = (('@VERSIONSTRING@', VERSION),
|
||||
('"@prefix@"', prefix),
|
||||
('"@sysconfdir@"', sysconfdir))
|
||||
('@LOCALE_DIR@', locale_dir))
|
||||
|
||||
substitute_variables(const_py_in, const_py, subst_vars)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user