Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d080d15352 | |||
| f3c4314a89 | |||
| 2284694530 | |||
| 15edee3a26 | |||
| d0e698ffac | |||
| addfaa933f | |||
| e2fc32c4c0 | |||
| 46e8d865b1 | |||
| c208b91184 | |||
| ab6342af70 | |||
| 715ddbbab3 | |||
| cc936c589b | |||
| f554ffd57d | |||
| 46e9edaf59 | |||
| 29620a31ef | |||
| ca2fd738d0 | |||
| 821caa8a5f | |||
| 3a45e70f54 | |||
| 89f6c7d83e | |||
| ca73e01512 | |||
| bfcecc646d | |||
| 77f9760504 | |||
| 3a93d03a4a | |||
| 03851db458 | |||
| 9f87dfd54b | |||
| 711e25e5bb | |||
| f1eecb349d | |||
| 04baa6b50f |
+1
-1
@@ -152,7 +152,7 @@ gramps(1) @VERSION@ gramps(1)
|
||||
|
||||
|
||||
**Opération**
|
||||
Si le premie argument de la ligne de commande ne commence pas par un
|
||||
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.
|
||||
|
||||
@@ -172,7 +172,7 @@ 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
|
||||
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.
|
||||
|
||||
@@ -151,7 +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://gramps-addons.svn.sourceforge.net/viewvc/gramps-addons/branches/gramps40/")
|
||||
register('behavior.addons-url', "http://svn.code.sf.net/p/gramps-addons/code/branches/gramps40/")
|
||||
|
||||
register('export.proxy-order', [
|
||||
["privacy", 0],
|
||||
@@ -279,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')
|
||||
|
||||
+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"),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
+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.
|
||||
|
||||
+53
-18
@@ -327,13 +327,18 @@ class ConfigureDialog(ManagedWindow):
|
||||
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, 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)
|
||||
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):
|
||||
@@ -1101,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)
|
||||
@@ -1153,27 +1163,49 @@ class GrampsPreferences(ConfigureDialog):
|
||||
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"),
|
||||
@@ -1186,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"),
|
||||
@@ -1203,21 +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)
|
||||
|
||||
self.add_entry(table, _('Where to check'), 8, 'behavior.addons-url', col_attach=1)
|
||||
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, 9, 10, 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, 9, 10, yoptions=0)
|
||||
table.attach(button, 3, 4, current_line, current_line+1, yoptions=0)
|
||||
|
||||
return _('General'), table
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -120,7 +120,7 @@ if is_quartz():
|
||||
else:
|
||||
_GTKOSXAPPLICATION = False
|
||||
|
||||
_UNSUPPORTED = _("Unsupported")
|
||||
_UNSUPPORTED = ("Unsupported", _("Unsupported"))
|
||||
|
||||
UIDEFAULT = '''<ui>
|
||||
<menubar name="MenuBar">
|
||||
@@ -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)
|
||||
@@ -1804,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:
|
||||
@@ -1821,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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
+436
-436
@@ -41,558 +41,558 @@ all_coverage = {}
|
||||
all_template_coverage = {}
|
||||
|
||||
def strip_quotes(st):
|
||||
if len(st) >= 2 and st[0] == '"' and st[len(st)-1] == '"':
|
||||
st = st.strip()[1:-1]
|
||||
return st
|
||||
if len(st) >= 2 and st[0] == '"' and st[len(st)-1] == '"':
|
||||
st = st.strip()[1:-1]
|
||||
return st
|
||||
|
||||
class CheckException( Exception ):
|
||||
pass
|
||||
pass
|
||||
|
||||
# This is a base class for all checks
|
||||
class Check:
|
||||
def __init__( self ):
|
||||
self.msgs = []
|
||||
def diag( self ):
|
||||
if len( self.msgs ):
|
||||
print
|
||||
print self.diag_header
|
||||
for m in self.msgs:
|
||||
m.diag()
|
||||
def summary( self ):
|
||||
print "%-20s%d" % ( self.summary_text, len(self.msgs) )
|
||||
def __init__( self ):
|
||||
self.msgs = []
|
||||
def diag( self ):
|
||||
if len( self.msgs ):
|
||||
print
|
||||
print(self.diag_header)
|
||||
for m in self.msgs:
|
||||
m.diag()
|
||||
def summary( self ):
|
||||
print("%-20s%d" % ( self.summary_text, len(self.msgs) ))
|
||||
|
||||
class Check_fmt( Check ):
|
||||
def __init__( self, fmt ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %s mismatches --------------" % fmt
|
||||
self.summary_text = "%s mismatches:" % fmt
|
||||
self.fmt = fmt
|
||||
def __init__( self, fmt ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %s mismatches --------------" % fmt
|
||||
self.summary_text = "%s mismatches:" % fmt
|
||||
self.fmt = fmt
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
cnt1 = msgid.count( self.fmt )
|
||||
cnt2 = msgstr.count( self.fmt )
|
||||
if cnt1 != cnt2:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
cnt1 = msgid.count( self.fmt )
|
||||
cnt2 = msgstr.count( self.fmt )
|
||||
if cnt1 != cnt2:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_named_fmt( Check ):
|
||||
# A pattern to find all %()
|
||||
find_named_fmt_pat = re.compile('% \( \w+ \) \d* \D', re.VERBOSE)
|
||||
# A pattern to find all %()
|
||||
find_named_fmt_pat = re.compile('% \( \w+ \) \d* \D', re.VERBOSE)
|
||||
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() name mismatches --------------"
|
||||
self.summary_text = "%() name mismatches:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() name mismatches --------------"
|
||||
self.summary_text = "%() name mismatches:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Same number of named formats?
|
||||
fmts1 = self.find_named_fmt_pat.findall( msgid )
|
||||
fmts2 = self.find_named_fmt_pat.findall( msgstr )
|
||||
if len( fmts1 ) != len( fmts2 ):
|
||||
self.msgs.append( msg )
|
||||
else:
|
||||
# Do we have the same named formats?
|
||||
fmts1.sort()
|
||||
fmts2.sort()
|
||||
if fmts1 != fmts2:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Same number of named formats?
|
||||
fmts1 = self.find_named_fmt_pat.findall( msgid )
|
||||
fmts2 = self.find_named_fmt_pat.findall( msgstr )
|
||||
if len( fmts1 ) != len( fmts2 ):
|
||||
self.msgs.append( msg )
|
||||
else:
|
||||
# Do we have the same named formats?
|
||||
fmts1.sort()
|
||||
fmts2.sort()
|
||||
if fmts1 != fmts2:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_missing_sd( Check ):
|
||||
# A pattern to find %() without s or d
|
||||
# Here is a command to use for testing
|
||||
# print re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE).findall( '%(event_name)s: %(place)s%(endnotes)s. ' )
|
||||
find_named_fmt_pat2 = re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE)
|
||||
# A pattern to find %() without s or d
|
||||
# Here is a command to use for testing
|
||||
# print(re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE).findall( '%(event_name)s: %(place)s%(endnotes)s. ' ))
|
||||
find_named_fmt_pat2 = re.compile('% \( \w+ \) \d* (\D|$)', re.VERBOSE)
|
||||
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() without 's' or 'd' mismatches --------------"
|
||||
self.summary_text = "%() missing s/d:"
|
||||
def process( self, msg ):
|
||||
for msgstr in msg.msgstr:
|
||||
fmts = self.find_named_fmt_pat2.findall( msgstr )
|
||||
for f in fmts:
|
||||
if not f in ('s', 'd'):
|
||||
self.msgs.append( msg )
|
||||
break
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- %() without 's' or 'd' mismatches --------------"
|
||||
self.summary_text = "%() missing s/d:"
|
||||
def process( self, msg ):
|
||||
for msgstr in msg.msgstr:
|
||||
fmts = self.find_named_fmt_pat2.findall( msgstr )
|
||||
for f in fmts:
|
||||
if not f in ('s', 'd'):
|
||||
self.msgs.append( msg )
|
||||
break
|
||||
|
||||
class Check_runaway( Check ):
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- Runaway context in translation ---------"
|
||||
self.summary_text = "Runaway context:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- Runaway context in translation ---------"
|
||||
self.summary_text = "Runaway context:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Runaway context. In the translated part we only to see
|
||||
# the translation of the word after the |
|
||||
if msgid.count('|') > 0 and msgstr.count('|') > 0 and msgid != msgstr:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
# Runaway context. In the translated part we only to see
|
||||
# the translation of the word after the |
|
||||
if msgid.count('|') > 0 and msgstr.count('|') > 0 and msgid != msgstr:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_xml_chars( Check ):
|
||||
# Special XML characters
|
||||
# It is not allowed to have a quote, an ampersand or an angle bracket
|
||||
xml_chars_pat = re.compile( r'<(?!(b>|/b>|i>|/i>|br/>)) | (?<=!(<b|/b|<i|/i|r/))> | " | & (?!(quot|nbsp|gt|amp);)', re.VERBOSE )
|
||||
# Special XML characters
|
||||
# It is not allowed to have a quote, an ampersand or an angle bracket
|
||||
xml_chars_pat = re.compile( r'<(?!(b>|/b>|i>|/i>|br/>)) | (?<=!(<b|/b|<i|/i|r/))> | " | & (?!(quot|nbsp|gt|amp);)', re.VERBOSE )
|
||||
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- unescaped XML special characters ---------"
|
||||
self.summary_text = "XML special chars:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- unescaped XML special characters ---------"
|
||||
self.summary_text = "XML special chars:"
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
|
||||
# XML errors
|
||||
# Only look at messages in the tips.xml
|
||||
if msg.is_tips_xml:
|
||||
if self.xml_chars_pat.search( msgstr ):
|
||||
self.msgs.append( msg )
|
||||
# XML errors
|
||||
# Only look at messages in the tips.xml
|
||||
if msg.is_tips_xml:
|
||||
if self.xml_chars_pat.search( msgstr ):
|
||||
self.msgs.append( msg )
|
||||
|
||||
class Check_last_char( Check ):
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- last character not identical ---------"
|
||||
self.summary_text = "Last character:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- last character not identical ---------"
|
||||
self.summary_text = "Last character:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
msgid_last = msgid[-1:]
|
||||
msgstr_last = msgstr[-1:]
|
||||
if msgid_last.isspace() != msgstr_last.isspace():
|
||||
self.msgs.append( msg )
|
||||
elif (msgid_last == '.') != (msgstr_last == '.'):
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
msgid_last = msgid[-1:]
|
||||
msgstr_last = msgstr[-1:]
|
||||
if msgid_last.isspace() != msgstr_last.isspace():
|
||||
self.msgs.append( msg )
|
||||
elif (msgid_last == '.') != (msgstr_last == '.'):
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
# Last character of msgid? White space? Period?
|
||||
if msg.is_fuzzy:
|
||||
return
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
# Last character of msgid? White space? Period?
|
||||
if msg.is_fuzzy:
|
||||
return
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Check_shortcut_trans( Check ):
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- shortcut key in translation ---------"
|
||||
self.summary_text = "Shortcut in msgstr:"
|
||||
def __init__( self ):
|
||||
Check.__init__( self )
|
||||
self.diag_header = "-------- shortcut key in translation ---------"
|
||||
self.summary_text = "Shortcut in msgstr:"
|
||||
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
if msgid.count('_') == 0 and msgstr.count('_') > 0:
|
||||
self.msgs.append( msg )
|
||||
def __process( self, msg, msgid, msgstr ):
|
||||
if msgid.count('_') == 0 and msgstr.count('_') > 0:
|
||||
self.msgs.append( msg )
|
||||
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
def process( self, msg ):
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr[0]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
if msg.msgidp and len(msg.msgstr) >= 2:
|
||||
msgid = msg.msgidp
|
||||
msgstr = msg.msgstr[1]
|
||||
self.__process( msg, msgid, msgstr )
|
||||
|
||||
class Msgid:
|
||||
fuzzy_pat = re.compile( 'fuzzy' )
|
||||
tips_xml_pat = re.compile( r'tips\.xml' )
|
||||
def __init__( self, msgnr, lineno ):
|
||||
self._msgid = [] # For debugging purpose the original text
|
||||
self._msgidp = [] # For debugging purpose the original text
|
||||
self._msgstr = [] # For debugging purpose the original text
|
||||
self.msgid = ''
|
||||
self.msgidp = ''
|
||||
self.msgstr = [] # This is a list to support plural
|
||||
self._cmnt = []
|
||||
self.nr = msgnr
|
||||
self.lineno = lineno
|
||||
self.is_fuzzy = 0
|
||||
self.is_tips_xml = 0
|
||||
fuzzy_pat = re.compile( 'fuzzy' )
|
||||
tips_xml_pat = re.compile( r'tips\.xml' )
|
||||
def __init__( self, msgnr, lineno ):
|
||||
self._msgid = [] # For debugging purpose the original text
|
||||
self._msgidp = [] # For debugging purpose the original text
|
||||
self._msgstr = [] # For debugging purpose the original text
|
||||
self.msgid = ''
|
||||
self.msgidp = ''
|
||||
self.msgstr = [] # This is a list to support plural
|
||||
self._cmnt = []
|
||||
self.nr = msgnr
|
||||
self.lineno = lineno
|
||||
self.is_fuzzy = 0
|
||||
self.is_tips_xml = 0
|
||||
|
||||
def diag( self ):
|
||||
print
|
||||
print "msg nr: %d, lineno: %d%s" % ( self.nr, self.lineno, self.is_fuzzy and " (fuzzy)" or "" )
|
||||
sys.stdout.write( ''.join( self._msgid ) )
|
||||
sys.stdout.write( ''.join( self._msgidp ) )
|
||||
sys.stdout.write( ''.join( self._msgstr ) )
|
||||
def diag( self ):
|
||||
print
|
||||
print("msg nr: %d, lineno: %d%s" % ( self.nr, self.lineno, self.is_fuzzy and " (fuzzy)" or "" ))
|
||||
sys.stdout.write( ''.join( self._msgid ) )
|
||||
sys.stdout.write( ''.join( self._msgidp ) )
|
||||
sys.stdout.write( ''.join( self._msgstr ) )
|
||||
|
||||
def add_msgid( self, line, lineno ):
|
||||
self._msgid.append( line )
|
||||
line = re.sub( r'msgid\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print "ERROR at line %d: Missing quote." % lineno
|
||||
line = strip_quotes( line )
|
||||
self.msgid += line
|
||||
def add_msgid( self, line, lineno ):
|
||||
self._msgid.append( line )
|
||||
line = re.sub( r'msgid\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print("ERROR at line %d: Missing quote." % lineno)
|
||||
line = strip_quotes( line )
|
||||
self.msgid += line
|
||||
|
||||
def add_msgidp( self, line, lineno ):
|
||||
self._msgidp.append( line )
|
||||
line = re.sub( r'msgid_plural\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print "ERROR at line %d: Missing quote." % lineno
|
||||
line = strip_quotes( line )
|
||||
self.msgidp += line
|
||||
def add_msgidp( self, line, lineno ):
|
||||
self._msgidp.append( line )
|
||||
line = re.sub( r'msgid_plural\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print("ERROR at line %d: Missing quote." % lineno)
|
||||
line = strip_quotes( line )
|
||||
self.msgidp += line
|
||||
|
||||
def add_new_msgstr( self, line, lineno ):
|
||||
self.msgstr.append( '' ) # Start a new msgstr
|
||||
self.add_msgstr( line, lineno )
|
||||
def add_new_msgstr( self, line, lineno ):
|
||||
self.msgstr.append( '' ) # Start a new msgstr
|
||||
self.add_msgstr( line, lineno )
|
||||
|
||||
def add_msgstr( self, line, lineno ):
|
||||
self._msgstr.append( line )
|
||||
line = re.sub( r'msgstr(\[\d\])?\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print "ERROR at line %d: Missing quote." % lineno
|
||||
line = strip_quotes( line )
|
||||
self.msgstr[-1] += line
|
||||
def add_msgstr( self, line, lineno ):
|
||||
self._msgstr.append( line )
|
||||
line = re.sub( r'msgstr(\[\d\])?\s+', '', line )
|
||||
line = line.strip()
|
||||
if line[0] != '"' or line[-1:] != '"':
|
||||
print("ERROR at line %d: Missing quote." % lineno)
|
||||
line = strip_quotes( line )
|
||||
self.msgstr[-1] += line
|
||||
|
||||
def add_cmnt( self, line ):
|
||||
self._cmnt.append( line )
|
||||
if not self.is_fuzzy and self.fuzzy_pat.search( line ):
|
||||
self.is_fuzzy = 1
|
||||
if not self.is_tips_xml and self.tips_xml_pat.search( line ):
|
||||
self.is_tips_xml = 1
|
||||
def add_cmnt( self, line ):
|
||||
self._cmnt.append( line )
|
||||
if not self.is_fuzzy and self.fuzzy_pat.search( line ):
|
||||
self.is_fuzzy = 1
|
||||
if not self.is_tips_xml and self.tips_xml_pat.search( line ):
|
||||
self.is_tips_xml = 1
|
||||
|
||||
def create_new_Msgid( msgs, lineno ):
|
||||
msg = Msgid( len(msgs), lineno )
|
||||
msgs.append( msg )
|
||||
return msg
|
||||
msg = Msgid( len(msgs), lineno )
|
||||
msgs.append( msg )
|
||||
return msg
|
||||
|
||||
def read_msgs( fname ):
|
||||
empty_pat = re.compile( r'^ \s* $', re.VERBOSE )
|
||||
comment_pat = re.compile( r'\#', re.VERBOSE )
|
||||
msgid_pat = re.compile( r'msgid \s+ "', re.VERBOSE )
|
||||
msgid_plural_pat = re.compile( r'msgid_plural \s+ "', re.VERBOSE )
|
||||
msgstr_pat = re.compile( r'msgstr (\[\d\])? \s+ "', re.VERBOSE )
|
||||
str_pat = re.compile( r'"', re.VERBOSE )
|
||||
old_pat = re.compile( r'\#~ \s+ ', re.VERBOSE )
|
||||
empty_pat = re.compile( r'^ \s* $', re.VERBOSE )
|
||||
comment_pat = re.compile( r'\#', re.VERBOSE )
|
||||
msgid_pat = re.compile( r'msgid \s+ "', re.VERBOSE )
|
||||
msgid_plural_pat = re.compile( r'msgid_plural \s+ "', re.VERBOSE )
|
||||
msgstr_pat = re.compile( r'msgstr (\[\d\])? \s+ "', re.VERBOSE )
|
||||
str_pat = re.compile( r'"', re.VERBOSE )
|
||||
old_pat = re.compile( r'\#~ \s+ ', re.VERBOSE )
|
||||
|
||||
f = open( fname )
|
||||
lines = f.readlines()
|
||||
|
||||
# parse it like a statemachine
|
||||
NONE = 'NONE' # Nothing detected, yet
|
||||
CMNT = 'CMNT' # Inside comment part
|
||||
MSGID = 'msgid' # Inside msgid part
|
||||
MSGIDP = 'msgid_plural' # Inside msgid_plural part
|
||||
MSGSTR = 'msgstr' # Inside msgstr part
|
||||
STR = 'STR' # A continuation string
|
||||
OLD = 'OLD' # An old pattern with #~
|
||||
f = open( fname )
|
||||
lines = f.readlines()
|
||||
|
||||
global msgs
|
||||
state = NONE
|
||||
msg = None
|
||||
# parse it like a statemachine
|
||||
NONE = 'NONE' # Nothing detected, yet
|
||||
CMNT = 'CMNT' # Inside comment part
|
||||
MSGID = 'msgid' # Inside msgid part
|
||||
MSGIDP = 'msgid_plural' # Inside msgid_plural part
|
||||
MSGSTR = 'msgstr' # Inside msgstr part
|
||||
STR = 'STR' # A continuation string
|
||||
OLD = 'OLD' # An old pattern with #~
|
||||
|
||||
msgs = []
|
||||
for ix, line in enumerate( lines ): # Use line numbers for messages
|
||||
lineno = ix + 1
|
||||
global msgs
|
||||
state = NONE
|
||||
msg = None
|
||||
|
||||
m = empty_pat.match( line )
|
||||
if m:
|
||||
continue # Empty lines are not interesting
|
||||
msgs = []
|
||||
for ix, line in enumerate( lines ): # Use line numbers for messages
|
||||
lineno = ix + 1
|
||||
|
||||
# What's the next state?
|
||||
if old_pat.match( line ):
|
||||
next_state = OLD
|
||||
elif comment_pat.match( line ):
|
||||
next_state = CMNT
|
||||
elif msgid_pat.match( line ):
|
||||
next_state = MSGID
|
||||
elif msgid_plural_pat.match( line ):
|
||||
next_state = MSGIDP
|
||||
elif msgstr_pat.match( line ):
|
||||
next_state = MSGSTR
|
||||
elif str_pat.match( line ):
|
||||
next_state = STR
|
||||
else:
|
||||
print 'WARNING: Unexpected input at %(fname)s:%(lineno)d' % vars()
|
||||
next_state = NONE
|
||||
m = empty_pat.match( line )
|
||||
if m:
|
||||
continue # Empty lines are not interesting
|
||||
|
||||
#print "%(state)d->%(next_state)d\t%(line)s" % vars()
|
||||
if state == NONE:
|
||||
# expect msgid or comment or old stuff
|
||||
if next_state == CMNT:
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_cmnt( line )
|
||||
# What's the next state?
|
||||
if old_pat.match( line ):
|
||||
next_state = OLD
|
||||
elif comment_pat.match( line ):
|
||||
next_state = CMNT
|
||||
elif msgid_pat.match( line ):
|
||||
next_state = MSGID
|
||||
elif msgid_plural_pat.match( line ):
|
||||
next_state = MSGIDP
|
||||
elif msgstr_pat.match( line ):
|
||||
next_state = MSGSTR
|
||||
elif str_pat.match( line ):
|
||||
next_state = STR
|
||||
else:
|
||||
print('WARNING: Unexpected input at %(fname)s:%(lineno)d' % vars())
|
||||
next_state = NONE
|
||||
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
#print("%(state)d->%(next_state)d\t%(line)s" % vars())
|
||||
if state == NONE:
|
||||
# expect msgid or comment or old stuff
|
||||
if next_state == CMNT:
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_cmnt( line )
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
print 'WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars()
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
print 'WARNING: Wild string at %(fname)s:%(lineno)d' % vars()
|
||||
elif next_state == MSGSTR:
|
||||
print('WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars())
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
print('WARNING: Wild string at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
pass # Just skip
|
||||
|
||||
elif state == CMNT:
|
||||
# Expect more comment, or msgid. If msgstr or string it is flagged as error.
|
||||
if next_state == CMNT:
|
||||
if msg:
|
||||
msg.add_cmnt( line )
|
||||
else:
|
||||
# Note. We may need to do something about these comments
|
||||
# Skip for now
|
||||
pass
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
if not msg:
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
elif state == CMNT:
|
||||
# Expect more comment, or msgid. If msgstr or string it is flagged as error.
|
||||
if next_state == CMNT:
|
||||
if msg:
|
||||
msg.add_cmnt( line )
|
||||
else:
|
||||
# Note. We may need to do something about these comments
|
||||
# Skip for now
|
||||
pass
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
if not msg:
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
print 'WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars()
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
print 'WARNING: Wild string at %(fname)s:%(lineno)d' % vars()
|
||||
elif next_state == MSGSTR:
|
||||
print('WARNING: Wild msgstr at %(fname)s:%(lineno)d' % vars())
|
||||
state = MSGSTR
|
||||
msg = create_new_Msgid( msgs, lineno ) # Start with an empty new item
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
print('WARNING: Wild string at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
elif state == MSGID:
|
||||
# Expect msgstr or msgid_plural or string
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print 'WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars()
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif state == MSGID:
|
||||
# Expect msgstr or msgid_plural or string
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print('WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
state = MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
state = MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid, stay in state MSGID
|
||||
msg.add_msgid( line, lineno )
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid, stay in state MSGID
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
elif state == MSGIDP:
|
||||
# Expect msgstr or string or comment
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print 'WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars()
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif state == MSGIDP:
|
||||
# Expect msgstr or string or comment
|
||||
if next_state == CMNT:
|
||||
# Hmmm. A comment here?
|
||||
print('WARNING: Unexpted comment at %(fname)s:%(lineno)d' % vars())
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid_plural, stay in state MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
elif next_state == MSGSTR:
|
||||
state = MSGSTR
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
# Continuation of msgid_plural, stay in state MSGIDP
|
||||
msg.add_msgidp( line, lineno )
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
elif state == MSGSTR:
|
||||
# Expect comment, or msgid, or string.
|
||||
if next_state == CMNT:
|
||||
# A comment probably starts a new item
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_cmnt( line )
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_msgid( line, lineno )
|
||||
elif state == MSGSTR:
|
||||
# Expect comment, or msgid, or string.
|
||||
if next_state == CMNT:
|
||||
# A comment probably starts a new item
|
||||
state = CMNT
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_cmnt( line )
|
||||
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
elif next_state == MSGID:
|
||||
state = MSGID
|
||||
msg = create_new_Msgid( msgs, lineno )
|
||||
msg.add_msgid( line, lineno )
|
||||
|
||||
elif next_state == MSGSTR:
|
||||
# New msgstr, probably for plural form
|
||||
# Stay in MSGSTR state
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
elif next_state == MSGIDP:
|
||||
raise CheckException( 'Unexpected %(next_state)s at %(fname)s:%(lineno)d' % vars() )
|
||||
|
||||
elif next_state == STR:
|
||||
msg.add_msgstr( line, lineno )
|
||||
elif next_state == MSGSTR:
|
||||
# New msgstr, probably for plural form
|
||||
# Stay in MSGSTR state
|
||||
msg.add_new_msgstr( line, lineno )
|
||||
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
elif next_state == STR:
|
||||
msg.add_msgstr( line, lineno )
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
elif next_state == OLD:
|
||||
msg = None
|
||||
pass # Just skip
|
||||
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
# Strip items with just comments. (Can this happen?)
|
||||
msgs1 = []
|
||||
for m in msgs:
|
||||
if not m.msgid and not m.msgstr:
|
||||
#print "INFO: No msgid or msgstr at %s:%s" % ( fname, m.lineno )
|
||||
pass
|
||||
else:
|
||||
msgs1.append( m )
|
||||
msgs = msgs1
|
||||
return msgs
|
||||
else:
|
||||
raise CheckException( 'Unexpected state in po parsing (state = %(state)s)' % vars() )
|
||||
|
||||
# Strip items with just comments. (Can this happen?)
|
||||
msgs1 = []
|
||||
for m in msgs:
|
||||
if not m.msgid and not m.msgstr:
|
||||
#print("INFO: No msgid or msgstr at %s:%s" % ( fname, m.lineno ))
|
||||
pass
|
||||
else:
|
||||
msgs1.append( m )
|
||||
msgs = msgs1
|
||||
return msgs
|
||||
|
||||
def analyze_msgs( args, fname, msgs, nr_templates = None, nth = 0 ):
|
||||
nr_fuzzy = 0
|
||||
nr_untranslated = 0
|
||||
nr_fuzzy = 0
|
||||
nr_untranslated = 0
|
||||
|
||||
checks = []
|
||||
checks.append( Check_fmt( '%s' ) )
|
||||
checks.append( Check_fmt( '%d' ) )
|
||||
checks.append( Check_named_fmt() )
|
||||
checks.append( Check_missing_sd() )
|
||||
checks.append( Check_runaway() )
|
||||
checks.append( Check_xml_chars() )
|
||||
checks.append( Check_last_char() )
|
||||
checks.append( Check_shortcut_trans() )
|
||||
checks = []
|
||||
checks.append( Check_fmt( '%s' ) )
|
||||
checks.append( Check_fmt( '%d' ) )
|
||||
checks.append( Check_named_fmt() )
|
||||
checks.append( Check_missing_sd() )
|
||||
checks.append( Check_runaway() )
|
||||
checks.append( Check_xml_chars() )
|
||||
checks.append( Check_last_char() )
|
||||
checks.append( Check_shortcut_trans() )
|
||||
|
||||
for msg in msgs:
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr
|
||||
#print
|
||||
#print "msgid: %(msgid)s" % vars()
|
||||
#print "msgstr: %(msgstr)s" % vars()
|
||||
for msg in msgs:
|
||||
msgid = msg.msgid
|
||||
msgstr = msg.msgstr
|
||||
#print
|
||||
#print("msgid: %(msgid)s" % vars())
|
||||
#print("msgstr: %(msgstr)s" % vars())
|
||||
|
||||
if ''.join(msgstr) == '':
|
||||
nr_untranslated += 1
|
||||
continue
|
||||
if ''.join(msgstr) == '':
|
||||
nr_untranslated += 1
|
||||
continue
|
||||
|
||||
if msg.is_fuzzy:
|
||||
nr_fuzzy += 1
|
||||
continue
|
||||
if msg.is_fuzzy:
|
||||
nr_fuzzy += 1
|
||||
continue
|
||||
|
||||
for c in checks:
|
||||
c.process( msg )
|
||||
for c in checks:
|
||||
c.process( msg )
|
||||
|
||||
nr_msgs = len(msgs)
|
||||
if nth > 0:
|
||||
print
|
||||
print "====================================="
|
||||
print "%-20s%s" % ( "File:", fname )
|
||||
print "%-20s%d" % ( "Template total:", nr_templates )
|
||||
print "%-20s%d" % ( "PO total:", nr_msgs )
|
||||
print "%-20s%d" % ( "Fuzzy:", nr_fuzzy )
|
||||
print "%-20s%d" % ( "Untranslated:", nr_untranslated )
|
||||
nr_msgs = len(msgs)
|
||||
if nth > 0:
|
||||
print
|
||||
print("=====================================")
|
||||
print("%-20s%s" % ( "File:", fname ))
|
||||
print("%-20s%d" % ( "Template total:", nr_templates ))
|
||||
print("%-20s%d" % ( "PO total:", nr_msgs ))
|
||||
print("%-20s%d" % ( "Fuzzy:", nr_fuzzy ))
|
||||
print("%-20s%d" % ( "Untranslated:", nr_untranslated ))
|
||||
|
||||
for c in checks:
|
||||
c.summary()
|
||||
for c in checks:
|
||||
c.summary()
|
||||
|
||||
po_coverage = (1.0 - (float(nr_untranslated) / float(nr_msgs))) * 100
|
||||
print "%-20s%5.2f%%" % ( "PO Coverage:", po_coverage )
|
||||
po_coverage = (1.0 - (float(nr_untranslated) / float(nr_msgs))) * 100
|
||||
print("%-20s%5.2f%%" % ( "PO Coverage:", po_coverage ))
|
||||
|
||||
template_coverage = po_coverage * float(nr_msgs) / float(nr_templates)
|
||||
print "%-20s%5.2f%%" % ( "Template Coverage:", template_coverage )
|
||||
template_coverage = po_coverage * float(nr_msgs) / float(nr_templates)
|
||||
print("%-20s%5.2f%%" % ( "Template Coverage:", template_coverage ))
|
||||
|
||||
not_displayed = nr_untranslated + nr_fuzzy
|
||||
translation = (1.0 - (float(not_displayed) / float(nr_templates))) * 100
|
||||
text = "%-20s%5.2f%%" % ( "Localized at:", translation)
|
||||
not_displayed = nr_untranslated + nr_fuzzy
|
||||
translation = (1.0 - (float(not_displayed) / float(nr_templates))) * 100
|
||||
text = "%-20s%5.2f%%" % ( "Localized at:", translation)
|
||||
|
||||
if int(template_coverage*1000) == int(po_coverage*1000):
|
||||
print text
|
||||
else:
|
||||
print text + ' (previous gramps.pot)'
|
||||
if int(template_coverage*1000) == int(po_coverage*1000):
|
||||
print(text)
|
||||
else:
|
||||
print(text + ' (previous gramps.pot)')
|
||||
|
||||
for c in checks:
|
||||
c.diag()
|
||||
for c in checks:
|
||||
c.diag()
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
parser = ArgumentParser( description='This program validates a PO file for GRAMPS.')
|
||||
|
||||
|
||||
parser.add_argument("-s", dest="summary",
|
||||
choices=[file for file in os.listdir('.') if file.endswith('.po')],
|
||||
choices=[file for file in os.listdir('.') if file.endswith('.po')],
|
||||
default=False, help="the summary of check, and if need, it gives details")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
if args.summary:
|
||||
files = sys.argv[2:]
|
||||
|
||||
try:
|
||||
pot_msgs = read_msgs( 'gramps.pot' )
|
||||
nr_templates = len( pot_msgs )
|
||||
nth = 0
|
||||
for fname in files:
|
||||
msgs = read_msgs( fname )
|
||||
analyze_msgs( files, fname, msgs, nr_templates, nth )
|
||||
nth += 1
|
||||
try:
|
||||
pot_msgs = read_msgs( 'gramps.pot' )
|
||||
nr_templates = len( pot_msgs )
|
||||
nth = 0
|
||||
for fname in files:
|
||||
msgs = read_msgs( fname )
|
||||
analyze_msgs( files, fname, msgs, nr_templates, nth )
|
||||
nth += 1
|
||||
|
||||
except CheckException, e:
|
||||
print 'Oops.', e
|
||||
print 'Bailing out'
|
||||
except CheckException as e:
|
||||
print('Oops.', e)
|
||||
print('Bailing out')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
+585
-136
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,7 @@ if sys.version_info[0] < 3:
|
||||
import commands
|
||||
from stat import ST_MODE
|
||||
|
||||
VERSION = '4.0.0-alpha2'
|
||||
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')
|
||||
@@ -244,7 +244,7 @@ def write_const_py(command):
|
||||
locale_dir = os.path.join(command.install_data, 'share', 'locale')
|
||||
else:
|
||||
#in build
|
||||
if os.access(const_py, os.F_OK):
|
||||
if 'install' in command.distribution.command_obj:
|
||||
# Prevent overwriting version created during install
|
||||
return
|
||||
locale_dir = os.path.join(command.build_base, 'mo')
|
||||
|
||||
Reference in New Issue
Block a user