Compare commits
76 Commits
v5.1.3
...
v4.0.0-alpha3
| 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 | |||
| 7c6872c11a | |||
| 71f87a31b3 | |||
| eb2ca43ff6 | |||
| 71b951f31d | |||
| a542081e25 | |||
| 5b8da49bae | |||
| 4d7e1043ef | |||
| 2040716b9c | |||
| 8a3a477ea4 |
+2
-2
@@ -37,8 +37,8 @@ global-exclude *.pyo
|
||||
global-exclude *.bak
|
||||
|
||||
# Remove directories which should not be included in the distribution
|
||||
prune src/guiQML
|
||||
prune src/webapp
|
||||
prune gramps/guiQML
|
||||
prune gramps/webapp
|
||||
|
||||
# Remove Makefiles used by autotools
|
||||
global-exclude Makefile*
|
||||
|
||||
@@ -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:
|
||||
|
||||
+26
-17
@@ -1,24 +1,33 @@
|
||||
Gramps 3.2 Release Notes
|
||||
"UNSTABLE Gramps 4.0.0 Alpha2 release.
|
||||
|
||||
General Improvements
|
||||
This is a technology preview to allow plugin writers and packagers-installer
|
||||
writers to update their plugins and scripts. This release is not production
|
||||
ready, so use for testing!"
|
||||
|
||||
* New Plugin System
|
||||
In the Help Menu -> Menu Status, all available plugins are visible. All plugins can be hidden, saving resources and hiding options you do not need. Eg: You don't use the Pedigree View? Hide it in the Plugin Status, and it will not be present anymore. You don't use vcard export? Hide it in the Plugin Status, and it will not be offered anymore.
|
||||
It is recommended to use Gramps 4.0.0 with python 3.2 so as to be ready
|
||||
for the future (python 2.7 works though).
|
||||
|
||||
* Faster
|
||||
Many under the hood improvements have occurred that should improve perfamance enormously. Yes, new features are present to use all your processing power, but they are all implemented as plugins that can be hidden. Eg: Insert of a person in a 30000 people family tree took 4sec on 1.4Ghz PC in 3.1, Now it is done in milliseconds.
|
||||
The dependencies for Gramps 4.0.0 are _completely_ different than 3.4 due
|
||||
to the switch to GObject introspection, and the removal of autotools. So
|
||||
only install 4.0.0 if you are certain you can obtain the dependencies,
|
||||
see README and INSTALL.
|
||||
|
||||
*New Views
|
||||
There are new views, and some views have been greatly improved
|
||||
- People view can now be sorted on the columns
|
||||
- A Place treeview is present, nicely grouping your places under country groups
|
||||
- GeoView has left it's beta status behind and shows your data on an
|
||||
online map (Openstreetmap or google maps, fast internet connection required)
|
||||
- Help Menu -> Extra Reports/Tools open a webpage with downloadable extra views
|
||||
For linux, in Ubuntu 12.10 you can install 4.0.0, but you will need to
|
||||
compile and install osmgpsmap manually to have the maps working (see
|
||||
http://www.gramps-project.org/wiki/index.php?title=GEPS_029:_GTK3-GObject_introspection_Conversion#OsmGpsMap_for_Geography )
|
||||
|
||||
|
||||
Other Improvements
|
||||
Major enhancements in Gramps 4.0.0:
|
||||
|
||||
* Styled Notes now in most output formats that support styles, eg in the web report
|
||||
* New languages
|
||||
* Select language in which report should be created (only present now in some reports)
|
||||
* GEP 8: code reorganization: http://www.gramps-project.org/wiki/index.php?title=GEPS_008:_File_Organization
|
||||
|
||||
* GEP 26: Replace make: http://www.gramps-project.org/wiki/index.php?title=GEPS_026:_Replace_%27make%27_for_Gramps_build
|
||||
|
||||
* GEP 29: Gtk 3 :http://www.gramps-project.org/wiki/index.php?title=GEPS_029:_GTK3-GObject_introspection_Conversion
|
||||
|
||||
* GEP 31: Python 3 support: http://www.gramps-project.org/wiki/index.php?title=GEPS_031:_Python_3_support
|
||||
|
||||
More info in the manual
|
||||
http://www.gramps-project.org/wiki/index.php?title=Gramps_4.0_Wiki_Manual_-_What%27s_new%3F
|
||||
|
||||
Everybody is invited to update the manual to make it current!
|
||||
|
||||
+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@"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
|
||||
@@ -176,4 +176,4 @@ class DateDisplayNb(DateDisplay):
|
||||
# Register classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
register_datehandler(('nb_NO', 'nb', 'norsk', 'Norwegian'), DateParserNb, DateDisplayNb)
|
||||
register_datehandler(('nb_NO', 'nb', 'nn_NO', 'nn', 'norsk', 'Norwegian'), DateParserNb, DateDisplayNb)
|
||||
|
||||
@@ -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>
|
||||
|
||||
+437
-434
@@ -41,555 +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
|
||||
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()
|
||||
c.diag()
|
||||
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()
|
||||
|
||||
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()
|
||||
|
||||
+4832
-822
File diff suppressed because it is too large
Load Diff
@@ -396,7 +396,7 @@ msgid "Could not rename family tree"
|
||||
msgstr "Kunne ikke omdøpe fila"
|
||||
|
||||
#: ../gramps/cli/clidbman.py:406
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"ERROR: Wrong database path in Edit Menu->Preferences.\n"
|
||||
|
||||
@@ -12493,7 +12493,7 @@ msgid "Color"
|
||||
msgstr "Färg"
|
||||
|
||||
#: ../gramps/gui/plug/_guioptions.py:1513
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
msgid "Select color for %s"
|
||||
msgstr "Välj färg på teckensnitt"
|
||||
|
||||
@@ -12703,7 +12703,7 @@ msgstr ""
|
||||
"att återse alternativ."
|
||||
|
||||
#: ../gramps/gui/plug/export/_exportassistant.py:452
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
msgid ""
|
||||
"The data will be saved as follows:\n"
|
||||
"\n"
|
||||
@@ -19567,6 +19567,7 @@ msgstr "GEDCOM importrappport: %s fel hittades"
|
||||
msgid "Tag recognized but not supported"
|
||||
msgstr "Flagga upptäck, men stöds ej"
|
||||
|
||||
#, fuzzy
|
||||
#: ../gramps/plugins/lib/libgedcom.py:2840
|
||||
msgid "Line ignored as not understood"
|
||||
msgstr "Rad %d gick inte att förstå, så den ignorerades."
|
||||
@@ -27089,7 +27090,7 @@ msgid "Number of merges done"
|
||||
msgstr "Antal utförda sammanslagningar"
|
||||
|
||||
#: ../gramps/plugins/tool/mergecitations.py:226
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
msgid "%(num)d citation merged"
|
||||
msgid_plural "%(num)d citations merged"
|
||||
msgstr[0] "%d citering sammanslagen"
|
||||
|
||||
@@ -47,7 +47,7 @@ if sys.version_info[0] < 3:
|
||||
import commands
|
||||
from stat import ST_MODE
|
||||
|
||||
VERSION = '4.0.0'
|
||||
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)
|
||||
@@ -96,8 +98,15 @@ def build_trans(build_cmd):
|
||||
if newer(po_file, mo_file):
|
||||
cmd = 'msgfmt %s -o %s' % (po_file, mo_file)
|
||||
if os.system(cmd) != 0:
|
||||
os.remove(mo_file)
|
||||
msg = 'ERROR: Building language translation files failed.'
|
||||
raise SystemExit(msg)
|
||||
ask = msg + '\n Continue building y/n [n] '
|
||||
if sys.version_info[0] < 3:
|
||||
reply = raw_input(ask)
|
||||
else:
|
||||
reply = input(ask)
|
||||
if reply in ['n', 'N']:
|
||||
raise SystemExit(msg)
|
||||
|
||||
#linux specific piece:
|
||||
target = 'share/locale/' + lang + '/LC_MESSAGES'
|
||||
@@ -224,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