Merge remote-tracking branch 'upstream/master' into test_imports

This commit is contained in:
prculley 2016-05-30 08:50:02 -05:00
commit 5182055c1f
15 changed files with 2310 additions and 2192 deletions

View File

@ -38,35 +38,36 @@ import time
from urllib.parse import urlparse
from urllib.request import urlopen, url2pathname
import tempfile
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
LOG = logging.getLogger(".clidbman")
from gramps.gen.db.dbconst import DBLOGNAME
_LOG = logging.getLogger(DBLOGNAME)
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
from gramps.gen.plug import BasePluginManager
from gramps.gen.config import config
from gramps.gen.constfunc import win
from gramps.gen.db.dbconst import DBLOGNAME
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
LOG = logging.getLogger(".clidbman")
_LOG = logging.getLogger(DBLOGNAME)
#-------------------------------------------------------------------------
#
# constants
#
#-------------------------------------------------------------------------
DEFAULT_TITLE = _("Family Tree")
NAME_FILE = "name.txt"
META_NAME = "meta_data.db"
NAME_FILE = "name.txt"
META_NAME = "meta_data.db"
#-------------------------------------------------------------------------
#
@ -78,8 +79,8 @@ def _errordialog(title, errormessage):
Show the error. A title for the error and an errormessage
"""
print(_('ERROR: %(title)s \n %(message)s') % {
'title': title,
'message': errormessage})
'title': title,
'message': errormessage})
sys.exit()
#-------------------------------------------------------------------------
@ -98,19 +99,19 @@ class CLIDbManager:
IND_TVAL_STR = 3
IND_TVAL = 4
IND_USE_ICON_BOOL = 5
IND_STOCK_ID =6
IND_STOCK_ID = 6
ICON_NONE = 0
ICON_NONE = 0
ICON_RECOVERY = 1
ICON_LOCK = 2
ICON_OPEN = 3
ICON_LOCK = 2
ICON_OPEN = 3
ICON_MAP = {
ICON_NONE : None,
ICON_RECOVERY : None,
ICON_LOCK : None,
ICON_OPEN : None,
}
ICON_NONE : None,
ICON_RECOVERY : None,
ICON_LOCK : None,
ICON_OPEN : None,
}
ERROR = _errordialog
def __init__(self, dbstate):
@ -118,7 +119,7 @@ class CLIDbManager:
self.msg = None
if dbstate:
self.active = dbstate.db.get_save_path()
self.active = dbstate.db.get_save_path()
else:
self.active = None
@ -155,7 +156,8 @@ class CLIDbManager:
dbid = "bsddb"
dbid_path = os.path.join(dirpath, "database.txt")
if os.path.isfile(dbid_path):
dbid = open(dbid_path).read().strip()
with open(dbid_path) as file:
dbid = file.read().strip()
if not self.is_locked(dirpath):
try:
database = self.dbstate.make_database(dbid)
@ -171,7 +173,7 @@ class CLIDbManager:
_("Database"): dbid,
_("Last accessed"): time_val(dirpath)[1],
_("Locked?"): self.is_locked(dirpath),
})
})
return retval
def print_family_tree_summaries(self, database_names=None):
@ -183,9 +185,9 @@ class CLIDbManager:
(name, dirpath, path_name, last,
tval, enable, stock_id, backend_type, version) = item
if (database_names is None or
any([(re.match("^" + dbname + "$", name) or
dbname == name)
for dbname in database_names])):
any([(re.match("^" + dbname + "$", name) or
dbname == name)
for dbname in database_names])):
summary = self.get_dbdir_summary(dirpath, name)
print(_("Family Tree \"%s\":") % summary[_("Family Tree")])
for item in sorted(summary):
@ -193,7 +195,7 @@ class CLIDbManager:
# translators: needed for French, ignore otherwise
print(_(" %(item)s: %(summary)s") % {
'item' : item,
'summary' : summary[item] } )
'summary' : summary[item]})
def family_tree_summary(self, database_names=None):
"""
@ -205,11 +207,11 @@ class CLIDbManager:
(name, dirpath, path_name, last,
tval, enable, stock_id, backend_type, version) = item
if (database_names is None or
any([(re.match("^" + dbname + "$", name) or
dbname == name)
for dbname in database_names])):
any([(re.match("^" + dbname + "$", name) or
dbname == name)
for dbname in database_names])):
retval = self.get_dbdir_summary(dirpath, name)
summary_list.append( retval )
summary_list.append(retval)
return summary_list
def _populate_cli(self):
@ -226,11 +228,13 @@ class CLIDbManager:
dirpath = os.path.join(dbdir, dpath)
path_name = os.path.join(dirpath, NAME_FILE)
try:
backend_type = open(os.path.join(dirpath, "database.txt")).read()
with open(os.path.join(dirpath, "database.txt")) as file:
backend_type = file.read()
except:
backend_type = "bsddb"
try:
version = open(os.path.join(dirpath, "bdbversion.txt")).read()
with open(os.path.join(dirpath, "bdbversion.txt")) as file:
version = file.read()
except:
version = "(0, 0, 0)"
try:
@ -242,10 +246,10 @@ class CLIDbManager:
name = file.readline().strip()
(tval, last) = time_val(dirpath)
(enable, stock_id) = self.icon_values(dirpath, self.active,
self.dbstate.db.is_open())
(enable, stock_id) = self.icon_values(
dirpath, self.active, self.dbstate.db.is_open())
if (stock_id == 'gramps-lock'):
if stock_id == 'gramps-lock':
last = find_locker_name(dirpath)
self.current_names.append(
@ -293,7 +297,7 @@ class CLIDbManager:
path_name = os.path.join(new_path, NAME_FILE)
if title is None:
name_list = [ name[0] for name in self.current_names ]
name_list = [name[0] for name in self.current_names]
title = find_next_db_name(name_list)
with open(path_name, "w", encoding='utf8') as name_file:
@ -352,9 +356,9 @@ class CLIDbManager:
# write locally:
temp_fp.write(data)
url_fp.close()
from gen.db.dbconst import BDBVERSFN
from gramps.gen.db.dbconst import BDBVERSFN
versionpath = os.path.join(name, BDBVERSFN)
_LOG.debug("Write bsddb version %s" % str(dbase.version()))
_LOG.debug("Write bsddb version %s", str(dbase.version()))
with open(versionpath, "w") as version_file:
version_file.write(str(dbase.version()))
temp_fp.close()
@ -389,7 +393,7 @@ class CLIDbManager:
"""
Returns True if there is a lock file in the dirpath
"""
if os.path.isfile(os.path.join(dbpath,"lock")):
if os.path.isfile(os.path.join(dbpath, "lock")):
return True
return False
@ -397,7 +401,7 @@ class CLIDbManager:
"""
Returns True if the database in dirpath needs recovery
"""
if os.path.isfile(os.path.join(dbpath,"need_recover")):
if os.path.isfile(os.path.join(dbpath, "need_recover")):
return True
return False
@ -441,12 +445,11 @@ class CLIDbManager:
"""
try:
with open(filepath, "r", encoding='utf8') as name_file:
old_text=name_file.read()
old_text = name_file.read()
with open(filepath, "w", encoding='utf8') as name_file:
name_file.write(new_text)
except (OSError, IOError) as msg:
CLIDbManager.ERROR(_("Could not rename Family Tree"),
str(msg))
CLIDbManager.ERROR(_("Could not rename Family Tree"), str(msg))
return None, None
return old_text, new_text
@ -462,11 +465,11 @@ class CLIDbManager:
If the directory path is the active path, then return values
that indicate to use the icon, and which icon to use.
"""
if os.path.isfile(os.path.join(dirpath,"need_recover")):
if os.path.isfile(os.path.join(dirpath, "need_recover")):
return (True, self.ICON_MAP[self.ICON_RECOVERY])
elif dirpath == active and is_open:
return (True, self.ICON_MAP[self.ICON_OPEN])
elif os.path.isfile(os.path.join(dirpath,"lock")):
elif os.path.isfile(os.path.join(dirpath, "lock")):
return (True, self.ICON_MAP[self.ICON_LOCK])
else:
return (False, self.ICON_MAP[self.ICON_NONE])
@ -481,7 +484,8 @@ def make_dbdir(dbdir):
except (IOError, OSError) as msg:
LOG.error(_("\nERROR: Wrong database path in Edit Menu->Preferences.\n"
"Open preferences and set correct database path.\n\n"
"Details: Could not make database directory:\n %s\n\n") % msg)
"Details: Could not make database directory:\n %s\n\n"),
str(msg))
return False
return True

View File

@ -289,7 +289,7 @@ class Gramplet:
"""
The main interface for running the :meth:`main` method.
"""
from gi.repository import GObject, GLib
from gi.repository import GLib
if ((not self.active) and
not self.gui.force_update):
self.dirty = True
@ -307,7 +307,7 @@ class Gramplet:
self._generator = self.main()
self._pause = False
self._idle_id = GLib.idle_add(self._updater,
priority=GObject.PRIORITY_LOW - 10)
priority=GLib.PRIORITY_LOW - 10)
def _updater(self):
"""
@ -353,10 +353,10 @@ class Gramplet:
"""
Resume the :meth:`main` method that has previously paused.
"""
from gi.repository import GObject, GLib
from gi.repository import GLib
self._pause = False
self._idle_id = GLib.idle_add(self._updater,
priority=GObject.PRIORITY_LOW - 10)
priority=GLib.PRIORITY_LOW - 10)
def update_all(self, *args):
"""

View File

@ -336,11 +336,32 @@ class LivingProxyDb(ProxyDbBase):
"""
handle_itr = self.db.find_backlink_handles(handle, include_classes)
for (class_name, handle) in handle_itr:
if class_name == 'Person':
if not self.get_person_from_handle(handle):
continue
yield (class_name, handle)
return
if self.mode == self.MODE_INCLUDE_ALL:
yield (class_name, handle)
elif class_name == 'Person':
## Don't get backlinks to living people at all
person = self.db.get_person_from_handle(handle)
if person and not self.__is_living(person):
yield (class_name, handle)
elif class_name == 'Family':
father = mother = None
family = self.db.get_family_from_handle(handle)
father_handle = family.get_father_handle()
mother_handle = family.get_mother_handle()
if father_handle:
father = self.db.get_person_from_handle(father_handle)
if mother_handle:
mother = self.db.get_person_from_handle(mother_handle)
father_not_living = father and not self.__is_living(father)
mother_not_living = mother and not self.__is_living(mother)
if ((father is None and mother is None) or # shouldn't happen
(father is None and mother_not_living) or # could
(mother is None and father_not_living) or # could
(father_not_living and mother_not_living) # could
):
yield (class_name, handle)
else:
yield (class_name, handle)
def __is_living(self, person):
"""

View File

@ -1104,44 +1104,66 @@ class GrampsPreferences(ConfigureDialog):
return _('Display'), grid
def add_places_panel(self, configdialog):
row = 0
grid = Gtk.Grid()
grid.set_border_width(12)
grid.set_column_spacing(6)
grid.set_row_spacing(6)
self.add_checkbox(grid, _("Enable automatic place title generation"),
row, 'preferences.place-auto', stop=3)
auto = self.add_checkbox(grid,
_("Enable automatic place title generation"),
0, 'preferences.place-auto',
extra_callback=self.auto_title_changed)
row = 0
grid2 = Gtk.Grid()
grid2.set_border_width(12)
grid2.set_column_spacing(6)
grid2.set_row_spacing(6)
grid.attach(grid2, 1, 1, 1, 1)
self.place_widgets = []
cbox = self.add_checkbox(grid2, _("Suppress comma after house number"),
row, 'preferences.place-number', start=0)
self.place_widgets.append(cbox)
row += 1
self.add_checkbox(grid, _("Suppress comma after house number"),
row, 'preferences.place-number', stop=3)
row += 1
self.add_checkbox(grid, _("Reverse display order"),
row, 'preferences.place-reverse', stop=3)
cbox = self.add_checkbox(grid2, _("Reverse display order"),
row, 'preferences.place-reverse', start=0)
self.place_widgets.append(cbox)
row += 1
# Place restriction
obox = Gtk.ComboBoxText()
formats = [_("Full place name"),
_("-> Hamlet/VillageTown/City"),
_("Hamlet/VillageTown/City ->")]
_("-> Hamlet/Village/Town/City"),
_("Hamlet/Village/Town/City ->")]
list(map(obox.append_text, formats))
active = config.get('preferences.place-restrict')
obox.set_active(active)
obox.connect('changed', self.place_restrict_changed)
lwidget = BasicLabel("%s: " % _('Restrict'))
grid.attach(lwidget, 0, row, 1, 1)
grid.attach(obox, 1, row, 2, 1)
grid2.attach(lwidget, 0, row, 1, 1)
grid2.attach(obox, 1, row, 2, 1)
self.place_widgets.append(obox)
row += 1
self.add_entry(grid, _("Language"),
row, 'preferences.place-lang')
entry = self.add_entry(grid2, _("Language"),
row, 'preferences.place-lang')
self.place_widgets.append(entry)
row += 1
self.auto_title_changed(auto)
return _('Places'), grid
def auto_title_changed(self, obj):
"""
Update sensitivity of place configuration widgets.
"""
active = obj.get_active()
for widget in self.place_widgets:
widget.set_sensitive(active)
def add_text_panel(self, configdialog):
row = 0
grid = Gtk.Grid()

View File

@ -35,23 +35,7 @@ import time
import copy
import subprocess
from urllib.parse import urlparse
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
LOG = logging.getLogger(".DbManager")
from gramps.gen.constfunc import win
if win():
_RCS_FOUND = os.system("rcs -V >nul 2>nul") == 0
if _RCS_FOUND and "TZ" not in os.environ:
# RCS requires the "TZ" variable be set.
os.environ["TZ"] = str(time.timezone)
else:
_RCS_FOUND = os.system("rcs -V >/dev/null 2>/dev/null") == 0
#-------------------------------------------------------------------------
#
@ -67,9 +51,6 @@ from gi.repository import Pango
# gramps modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.plug import BasePluginManager
_ = glocale.translation.gettext
from gramps.gui.display import display_help
from gramps.gen.const import URL_WIKISTRING, URL_MANUAL_PAGE
from .user import User
@ -83,37 +64,55 @@ from .glade import Glade
from gramps.gen.db.exceptions import DbException
from gramps.gen.config import config
from gramps.gui.listmodel import ListModel
from gramps.gen.constfunc import win
from gramps.gen.plug import BasePluginManager
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
_RETURN = Gdk.keyval_from_name("Return")
_KP_ENTER = Gdk.keyval_from_name("KP_Enter")
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
LOG = logging.getLogger(".DbManager")
#-------------------------------------------------------------------------
#
# constants
#
#-------------------------------------------------------------------------
if win():
_RCS_FOUND = os.system("rcs -V >nul 2>nul") == 0
if _RCS_FOUND and "TZ" not in os.environ:
# RCS requires the "TZ" variable be set.
os.environ["TZ"] = str(time.timezone)
else:
_RCS_FOUND = os.system("rcs -V >/dev/null 2>/dev/null") == 0
_RETURN = Gdk.keyval_from_name("Return")
_KP_ENTER = Gdk.keyval_from_name("KP_Enter")
WIKI_HELP_PAGE = _('%s_-_Manage_Family_Trees') % URL_MANUAL_PAGE
WIKI_HELP_SEC = _('Family_Trees_manager_window')
ARCHIVE = "rev.gramps"
ARCHIVE_V = "rev.gramps,v"
ARCHIVE = "rev.gramps"
ARCHIVE_V = "rev.gramps,v"
NAME_COL = 0
PATH_COL = 1
FILE_COL = 2
DATE_COL = 3
NAME_COL = 0
PATH_COL = 1
FILE_COL = 2
DATE_COL = 3
DSORT_COL = 4
OPEN_COL = 5
OPEN_COL = 5
ICON_COL = 6
BACKEND_COL = 7
RCS_BUTTON = { True : _('_Extract'), False : _('_Archive') }
RCS_BUTTON = {True : _('_Extract'), False : _('_Archive')}
class Information(ManagedWindow):
def __init__(self, uistate, data, parent):
super().__init__(uistate, [], self)
self.window = Gtk.Dialog('Gramp')
self.window = Gtk.Dialog()
self.set_window(self.window, None, _("Database Information"))
self.window.set_modal(True)
self.ok = self.window.add_button(_('_OK'), Gtk.ResponseType.OK)
@ -122,8 +121,8 @@ class Information(ManagedWindow):
self.window.set_default_size(600, 400)
s = Gtk.ScrolledWindow()
titles = [
(_('Setting'),0,150),
(_('Value'),1,400)
(_('Setting'), 0, 150),
(_('Value'), 1, 400)
]
treeview = Gtk.TreeView()
model = ListModel(treeview, titles)
@ -147,11 +146,11 @@ class DbManager(CLIDbManager):
create, rename, delete and open databases.
"""
ICON_MAP = {
CLIDbManager.ICON_NONE : None,
CLIDbManager.ICON_RECOVERY : 'dialog-error',
CLIDbManager.ICON_LOCK : 'gramps-lock',
CLIDbManager.ICON_OPEN : 'document-open',
}
CLIDbManager.ICON_NONE : None,
CLIDbManager.ICON_RECOVERY : 'dialog-error',
CLIDbManager.ICON_LOCK : 'gramps-lock',
CLIDbManager.ICON_OPEN : 'document-open',
}
ERROR = ErrorDialog
@ -174,7 +173,7 @@ class DbManager(CLIDbManager):
setattr(self, attr, self.glade.get_object(attr))
self.model = None
self.column = None
self.column = None
self.lock_file = None
self.data_to_delete = None
@ -227,15 +226,14 @@ class DbManager(CLIDbManager):
self.top.connect('drag_data_received', self.__drag_data_received)
self.top.connect('drag_motion', drag_motion)
self.top.connect('drag_drop', drop_cb)
self.define_help_button(self.glade.get_object('help'),
WIKI_HELP_PAGE, WIKI_HELP_SEC)
self.define_help_button(
self.glade.get_object('help'), WIKI_HELP_PAGE, WIKI_HELP_SEC)
if _RCS_FOUND:
self.rcs.connect('clicked', self.__rcs)
def define_help_button(self, button, webpage='', section=''):
button.connect('clicked', lambda x: display_help(webpage,
section))
button.connect('clicked', lambda x: display_help(webpage, section))
def __button_press(self, obj, event):
"""
@ -307,7 +305,8 @@ class DbManager(CLIDbManager):
self.close.set_sensitive(False)
backend_name = self.get_backend_name_from_dbid("bsddb")
if (store.get_value(node, ICON_COL) in [None, ""] and
store.get_value(node, BACKEND_COL).startswith(backend_name)):
store.get_value(node,
BACKEND_COL).startswith(backend_name)):
self.convert.set_sensitive(True)
else:
self.convert.set_sensitive(False)
@ -378,7 +377,8 @@ class DbManager(CLIDbManager):
# build the backend column
render = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(_('Database Type'), render, text=BACKEND_COL)
column = Gtk.TreeViewColumn(_('Database Type'), render,
text=BACKEND_COL)
column.set_sort_column_id(BACKEND_COL)
column.set_sort_indicator(True)
column.set_resizable(True)
@ -411,7 +411,8 @@ class DbManager(CLIDbManager):
data = list(items[:8])
backend_type = self.get_backend_name_from_dbid(data[BACKEND_COL])
version = str(".".join([str(v) for v in items[8]]))
node = self.model.append(None, data[:-1] + [backend_type + ", " + version])
node = self.model.append(None, data[:-1] + [backend_type + ", "
+ version])
# For already loaded database, set current_node:
if self.dbstate.db and self.dbstate.db.get_save_path() == data[1]:
self._current_node = node
@ -433,7 +434,7 @@ class DbManager(CLIDbManager):
If skippath given, the name of skippath is not considered
"""
iter = self.model.get_iter_first()
while (iter):
while iter:
path = self.model.get_path(iter)
if path == skippath:
pass
@ -493,8 +494,8 @@ class DbManager(CLIDbManager):
def __really_break_lock(self):
"""
Deletes the lock file associated with the selected database, then updates
the display appropriately.
Deletes the lock file associated with the selected database,
then updates the display appropriately.
"""
try:
self.break_lock(self.lock_file)
@ -548,7 +549,7 @@ class DbManager(CLIDbManager):
self.before_change = old_text
self.after_change = new_text
if not old_text.strip() == new_text.strip():
if len(path.get_indices()) > 1 :
if len(path.get_indices()) > 1:
self.__rename_revision(path, new_text)
else:
self.__rename_database(path, new_text)
@ -569,9 +570,9 @@ class DbManager(CLIDbManager):
rev = self.model.get_value(node, PATH_COL)
archive = os.path.join(db_dir, ARCHIVE_V)
cmd = [ "rcs", "-x,v", "-m%s:%s" % (rev, new_text), archive ]
cmd = ["rcs", "-x,v", "-m%s:%s" % (rev, new_text), archive]
proc = subprocess.Popen(cmd, stderr = subprocess.PIPE)
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
status = proc.wait()
message = "\n".join(proc.stderr.readlines())
proc.stderr.close()
@ -598,11 +599,12 @@ class DbManager(CLIDbManager):
node = self.model.get_iter(path)
filename = self.model.get_value(node, FILE_COL)
if self.existing_name(new_text, skippath=path):
DbManager.ERROR(_("Could not rename the Family Tree."),
_("Family Tree already exists, choose a unique name."))
DbManager.ERROR(
_("Could not rename the Family Tree."),
_("Family Tree already exists, choose a unique name."))
return
old_text, new_text = self.rename_database(filename, new_text)
if not (old_text is None):
if old_text is not None:
rename_filename(old_text, new_text)
self.model.set_value(node, NAME_COL, new_text)
#scroll to new position
@ -664,7 +666,8 @@ class DbManager(CLIDbManager):
if len(path.get_indices()) == 1:
QuestionDialog(
_("Remove the '%s' Family Tree?") % self.data_to_delete[0],
_("Removing this Family Tree will permanently destroy the data."),
_("Removing this Family Tree will permanently destroy "
"the data."),
_("Remove Family Tree"),
self.__really_delete_db, parent=self.top)
else:
@ -698,7 +701,7 @@ class DbManager(CLIDbManager):
filename = self.model.get_value(node, FILE_COL)
try:
with open(filename, "r") as name_file:
file_name_to_delete=name_file.read()
file_name_to_delete = name_file.read()
remove_filename(file_name_to_delete)
directory = self.data_to_delete[1]
for (top, dirs, files) in os.walk(directory):
@ -722,9 +725,9 @@ class DbManager(CLIDbManager):
rev = self.data_to_delete[PATH_COL]
archive = os.path.join(db_dir, ARCHIVE_V)
cmd = [ "rcs", "-x,v", "-o%s" % rev, "-q", archive ]
cmd = ["rcs", "-x,v", "-o%s" % rev, "-q", archive]
proc = subprocess.Popen(cmd, stderr = subprocess.PIPE)
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
status = proc.wait()
message = "\n".join(proc.stderr.readlines())
proc.stderr.close()
@ -764,7 +767,8 @@ class DbManager(CLIDbManager):
except:
ErrorDialog(
_("Opening the '%s' database") % name,
_("An attempt to convert the database failed. Perhaps it needs updating."))
_("An attempt to convert the database failed. "
"Perhaps it needs updating."))
return
plugin_manager = GuiPluginManager.get_instance()
export_function = None
@ -858,8 +862,7 @@ class DbManager(CLIDbManager):
#First ask user if he is really sure :-)
yes_no = QuestionDialog2(
_("Repair Family Tree?"),
_(
"If you click %(bold_start)sProceed%(bold_end)s, Gramps will "
_("If you click %(bold_start)sProceed%(bold_end)s, Gramps will "
"attempt to recover your Family Tree from the last good "
"backup. There are several ways this can cause unwanted "
"effects, so %(bold_start)sbackup%(bold_end)s the "
@ -884,12 +887,12 @@ class DbManager(CLIDbManager):
"If this is the case, you can disable the repair button "
"by removing the file %(recover_file)s in the "
"Family Tree directory."
) % { 'bold_start' : '<b>' ,
'bold_end' : '</b>' ,
'recover_file' : '<i>need_recover</i>' ,
'gramps_wiki_recover_url' :
URL_WIKISTRING + 'Recover_corrupted_family_tree',
'dirname' : dirname },
) % {'bold_start': '<b>',
'bold_end': '</b>',
'recover_file': '<i>need_recover</i>',
'gramps_wiki_recover_url':
URL_WIKISTRING + 'Recover_corrupted_family_tree',
'dirname': dirname},
_("Proceed, I have taken a backup"),
_("Stop"))
prompt = yes_no.run()
@ -934,7 +937,7 @@ class DbManager(CLIDbManager):
"""
self.msg.set_label(msg)
self.top.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))
while (Gtk.events_pending()):
while Gtk.events_pending():
Gtk.main_iteration()
def __end_cursor(self):
@ -997,7 +1000,8 @@ class DbManager(CLIDbManager):
# Allow any type of URL ("file://", "http://", etc):
if drag_value and urlparse(drag_value).scheme != "":
fname, title = [], []
for treename in [v.strip() for v in drag_value.split("\n") if v.strip() != '']:
for treename in [v.strip() for v in drag_value.split("\n")
if v.strip() != '']:
f, t = self.import_new_db(treename, self.user)
fname.append(f)
title.append(t)
@ -1023,15 +1027,15 @@ def find_revisions(name):
"""
import re
rev = re.compile("\s*revision\s+([\d\.]+)")
rev = re.compile("\s*revision\s+([\d\.]+)")
date = re.compile("date:\s+(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)[-+]\d\d;")
if not os.path.isfile(name) or not _RCS_FOUND:
return []
rlog = [ "rlog", "-x,v", "-zLT" , name ]
rlog = ["rlog", "-x,v", "-zLT", name]
proc = subprocess.Popen(rlog, stdout = subprocess.PIPE)
proc = subprocess.Popen(rlog, stdout=subprocess.PIPE)
proc.wait()
revlist = []
@ -1051,9 +1055,9 @@ def find_revisions(name):
continue
match = date.match(line)
if match:
date_str = time.strftime('%x %X',
time.strptime(match.groups()[0], '%Y-%m-%d %H:%M:%S'))
date_str = time.strftime(
'%x %X', time.strptime(match.groups()[0],
'%Y-%m-%d %H:%M:%S'))
get_next = True
continue
if get_next:
@ -1071,10 +1075,10 @@ def check_out(dbase, rev, path, user):
Checks out the revision from rcs, and loads the resulting XML file
into the database.
"""
co_cmd = [ "co", "-x,v", "-q%s" % rev] + [ os.path.join(path, ARCHIVE),
os.path.join(path, ARCHIVE_V)]
co_cmd = ["co", "-x,v", "-q%s" % rev] + [os.path.join(path, ARCHIVE),
os.path.join(path, ARCHIVE_V)]
proc = subprocess.Popen(co_cmd, stderr = subprocess.PIPE)
proc = subprocess.Popen(co_cmd, stderr=subprocess.PIPE)
status = proc.wait()
message = "\n".join(proc.stderr.readlines())
proc.stderr.close()
@ -1097,12 +1101,12 @@ def check_out(dbase, rev, path, user):
rdr(dbase, xml_file, user)
os.unlink(xml_file)
def check_in(dbase, filename, user, cursor_func = None):
def check_in(dbase, filename, user, cursor_func=None):
"""
Checks in the specified file into RCS
"""
init = [ "rcs", '-x,v', '-i', '-U', '-q', '-t-"Gramps database"' ]
ci_cmd = [ "ci", '-x,v', "-q", "-f" ]
init = ["rcs", '-x,v', '-i', '-U', '-q', '-t-"Gramps database"']
ci_cmd = ["ci", '-x,v', "-q", "-f"]
archive_name = filename + ",v"
glade = Glade(toplevel='comment')
@ -1114,8 +1118,7 @@ def check_in(dbase, filename, user, cursor_func = None):
if not os.path.isfile(archive_name):
cmd = init + [archive_name]
proc = subprocess.Popen(cmd,
stderr = subprocess.PIPE)
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
status = proc.wait()
message = "\n".join(proc.stderr.readlines())
proc.stderr.close()
@ -1140,9 +1143,8 @@ def check_in(dbase, filename, user, cursor_func = None):
if cursor_func:
cursor_func(_("Saving archive..."))
cmd = ci_cmd + ['-m%s' % comment, filename, archive_name ]
proc = subprocess.Popen(cmd,
stderr = subprocess.PIPE)
cmd = ci_cmd + ['-m%s' % comment, filename, archive_name]
proc = subprocess.Popen(cmd, stderr=subprocess.PIPE)
status = proc.wait()
message = "\n".join(proc.stderr.readlines())

View File

@ -358,7 +358,6 @@ class ViewManager(CLIManager):
self.window = Gtk.Window()
self.window.set_icon_from_file(ICON)
self.window.set_has_resize_grip(True)
self.window.set_default_size(width, height)
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)

View File

@ -171,13 +171,13 @@ class SelectionWidget(Gtk.ScrolledWindow):
"""
__gsignals__ = {
"region-modified": (GObject.SIGNAL_RUN_FIRST, None, ()),
"region-created": (GObject.SIGNAL_RUN_FIRST, None, ()),
"region-selected": (GObject.SIGNAL_RUN_FIRST, None, ()),
"selection-cleared": (GObject.SIGNAL_RUN_FIRST, None, ()),
"right-button-clicked": (GObject.SIGNAL_RUN_FIRST, None, ()),
"zoomed-in": (GObject.SIGNAL_RUN_FIRST, None, ()),
"zoomed-out": (GObject.SIGNAL_RUN_FIRST, None, ())
"region-modified": (GObject.SignalFlags.RUN_FIRST, None, ()),
"region-created": (GObject.SignalFlags.RUN_FIRST, None, ()),
"region-selected": (GObject.SignalFlags.RUN_FIRST, None, ()),
"selection-cleared": (GObject.SignalFlags.RUN_FIRST, None, ()),
"right-button-clicked": (GObject.SignalFlags.RUN_FIRST, None, ()),
"zoomed-in": (GObject.SignalFlags.RUN_FIRST, None, ()),
"zoomed-out": (GObject.SignalFlags.RUN_FIRST, None, ())
}
def __init__(self):

View File

@ -4,7 +4,7 @@
#
# Copyright (C) 2008-2011 Reinhard Müller
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2013-2015 Paul Franklin
# Copyright (C) 2013-2016 Paul Franklin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -39,6 +39,7 @@ from gramps.gen.lib import (ChildRefType, Date, Span, Name, StyledText,
StyledTextTag, StyledTextTagType)
from gramps.gen.display.name import displayer as name_displayer
from gramps.gen.utils.alive import probably_alive
from gramps.gen.proxy import LivingProxyDb
#------------------------------------------------------------------------
#
@ -93,15 +94,24 @@ def _find_death_date(db, person):
return None
def find_records(db, filter, top_size, callname,
trans_text=glocale.translation.sgettext, name_format=None):
trans_text=glocale.translation.sgettext, name_format=None,
living_mode=LivingProxyDb.MODE_INCLUDE_ALL):
"""
@param trans_text: allow deferred translation of strings
@type trans_text: a GrampsLocale sgettext instance
trans_text is a defined keyword (see po/update_po.py, po/genpot.sh)
:param name_format: optional format to control display of person's name
:type name_format: None or int
:param living_mode: enable optional control of living people's records
:type living_mode: int
"""
def get_unfiltered_person_from_handle(person_handle):
if living_mode == LivingProxyDb.MODE_INCLUDE_ALL:
return db.get_person_from_handle(person_handle)
else: # we are in the proxy so get the person before proxy changes
return db.get_unfiltered_person(person_handle)
today = datetime.date.today()
today_date = Date(today.year, today.month, today.day)
@ -126,6 +136,7 @@ def find_records(db, filter, top_size, callname,
for person_handle in person_handle_list:
person = db.get_person_from_handle(person_handle)
unfil_person = get_unfiltered_person_from_handle(person_handle)
if person is None:
continue
@ -150,7 +161,7 @@ def find_records(db, filter, top_size, callname,
name_format=name_format)
if death_date is None:
if probably_alive(person, db):
if probably_alive(unfil_person, db):
# Still living, look for age records
_record(person_youngestliving, person_oldestliving,
today_date - birth_date, name, 'Person', person_handle,
@ -231,6 +242,9 @@ def find_records(db, filter, top_size, callname,
for family in db.iter_families():
#family = db.get_family_from_handle(family_handle)
if living_mode != LivingProxyDb.MODE_INCLUDE_ALL:
# FIXME no iter_families method in LivingProxyDb so do it this way
family = db.get_family_from_handle(family.get_handle())
father_handle = family.get_father_handle()
if not father_handle:
@ -245,9 +259,11 @@ def find_records(db, filter, top_size, callname,
continue
father = db.get_person_from_handle(father_handle)
unfil_father = get_unfiltered_person_from_handle(father_handle)
if father is None:
continue
mother = db.get_person_from_handle(mother_handle)
unfil_mother = get_unfiltered_person_from_handle(mother_handle)
if mother is None:
continue
@ -259,9 +275,12 @@ def find_records(db, filter, top_size, callname,
trans_text=trans_text,
name_format=name_format)}
_record(None, family_mostchildren,
len(family.get_child_ref_list()),
name, 'Family', family.handle, top_size)
if (living_mode == LivingProxyDb.MODE_INCLUDE_ALL
or (not probably_alive(unfil_father, db) and
not probably_alive(unfil_mother, db))):
_record(None, family_mostchildren,
len(family.get_child_ref_list()),
name, 'Family', family.handle, top_size)
father_birth_ref = father.get_birth_ref()
if father_birth_ref:
@ -311,11 +330,13 @@ def find_records(db, filter, top_size, callname,
# Divorced but date unknown or inexact
continue
if not probably_alive(father, db) and not _good_date(father_death_date):
if (not probably_alive(unfil_father, db)
and not _good_date(father_death_date)):
# Father died but death date unknown or inexact
continue
if not probably_alive(mother, db) and not _good_date(mother_death_date):
if (not probably_alive(unfil_mother, db)
and not _good_date(mother_death_date)):
# Mother died but death date unknown or inexact
continue
@ -323,7 +344,8 @@ def find_records(db, filter, top_size, callname,
and father_death_date is None
and mother_death_date is None):
# Still married and alive
if probably_alive(father, db) and probably_alive(mother, db):
if (probably_alive(unfil_father, db)
and probably_alive(unfil_mother, db)):
_record(family_youngestmarried, family_oldestmarried,
today_date - marriage_date,
name, 'Family', family.handle, top_size)

View File

@ -100,6 +100,7 @@ class AncestorReport(Report):
stdoptions.run_private_data_option(self, menu)
stdoptions.run_living_people_option(self, menu, rlocale)
self.database = CacheProxyDb(self.database)
self.max_generations = menu.get_option_by_name('maxgen').get_value()
self.pgbrk = menu.get_option_by_name('pagebbg').get_value()
@ -111,8 +112,6 @@ class AncestorReport(Report):
stdoptions.run_name_format_option(self, menu)
self.database = CacheProxyDb(self.database)
self.__narrator = Narrator(self.database, use_fulldate=True,
nlocale=rlocale)

View File

@ -8,7 +8,7 @@
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2012 Mathieu MD
# Copyright (C) 2013-2015 Paul Franklin
# Copyright (C) 2013-2016 Paul Franklin
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -25,6 +25,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
""" Complete Individual Report """
#------------------------------------------------------------------------
#
# standard python modules
@ -45,7 +47,6 @@ from gramps.gen.plug.docgen import (IndexMark, FontStyle, ParagraphStyle,
TableStyle, TableCellStyle,
FONT_SANS_SERIF, INDEX_TYPE_TOC,
PARA_ALIGN_CENTER, PARA_ALIGN_RIGHT)
from gramps.gen.datehandler import get_date
from gramps.gen.display.place import displayer as place_displayer
from gramps.gen.plug.menu import (BooleanOption, FilterOption, PersonOption,
BooleanListOption)
@ -107,10 +108,15 @@ class IndivCompleteReport(Report):
returning the list of filters.
cites - Whether or not to include source information.
sort - Whether or not to sort events into chronological order.
grampsid - Whether or not to include any Gramps IDs
images - Whether or not to include images.
sections - Which event groups should be given separate sections.
name_format - Preferred format to display names
incl_private - Whether to include private data
incl_attrs - Whether to include attributes
incl_census - Whether to include census events
incl_notes - Whether to include person and family notes
incl_tags - Whether to include tags
living_people - How to handle living people
years_past_death - Consider as living this many years after death
"""
@ -128,22 +134,30 @@ class IndivCompleteReport(Report):
self._db = self.database
self.use_pagebreak = menu.get_option_by_name('pageben').get_value()
self.use_srcs = menu.get_option_by_name('cites').get_value()
self.use_srcs_notes = menu.get_option_by_name('incsrcnotes').get_value()
self.sort = menu.get_option_by_name('sort').get_value()
self.use_images = menu.get_option_by_name('images').get_value()
self.use_attrs = menu.get_option_by_name('incl_attrs').get_value()
self.use_census = menu.get_option_by_name('incl_census').get_value()
self.use_gramps_id = menu.get_option_by_name('grampsid').get_value()
self.use_images = menu.get_option_by_name('images').get_value()
self.use_notes = menu.get_option_by_name('incl_notes').get_value()
self.use_srcs = menu.get_option_by_name('cites').get_value()
self.use_src_notes = menu.get_option_by_name('incsrcnotes').get_value()
self.use_tags = menu.get_option_by_name('incl_tags').get_value()
filter_option = options.menu.get_option_by_name('filter')
self.filter = filter_option.get_filter()
self.bibli = None
self.section_list = menu.get_option_by_name('sections').get_selected()
stdoptions.run_name_format_option(self, menu)
self.bibli = None
self.family_notes_list = []
self.mime0 = None
self.person = None
def write_fact(self, event_ref, event, show_type=True):
"""
Writes a single event.
@ -160,7 +174,7 @@ class IndivCompleteReport(Report):
place_name = place_displayer.display_event(self._db, event)
place_endnote = self._cite_endnote(place)
# make sure it's translated, so it can be used below, in "combine"
ignore1 = _('%(str1)s in %(str2)s. ') % {'str1':'', 'str2':''}
ignore = _('%(str1)s in %(str2)s. ') % {'str1':'', 'str2':''}
date_place = self.combine('%(str1)s in %(str2)s. ', '%s. ',
date, place_name)
@ -171,7 +185,7 @@ class IndivCompleteReport(Report):
column_1 = column_1 + ' (' + self._(role.xml_str()) + ')'
# translators: needed for Arabic, ignore otherwise
# make sure it's translated, so it can be used below, in "combine"
ignore2 = _('%(str1)s, %(str2)s') % {'str1':'', 'str2':''}
ignore = _('%(str1)s, %(str2)s') % {'str1':'', 'str2':''}
column_2 = self.combine('%(str1)s, %(str2)s', '%s',
description, date_place)
else:
@ -179,7 +193,7 @@ class IndivCompleteReport(Report):
column_1 = date
# translators: needed for Arabic, ignore otherwise
# make sure it's translated, so it can be used below, in "combine"
ignore3 = _('%(str1)s, %(str2)s') % {'str1':'', 'str2':''}
ignore = _('%(str1)s, %(str2)s') % {'str1':'', 'str2':''}
column_2 = self.combine('%(str1)s, %(str2)s', '%s',
description, place_name)
@ -197,37 +211,41 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
self.do_attributes(event.get_attribute_list() +
event_ref.get_attribute_list() )
event_ref.get_attribute_list())
for notehandle in event.get_note_list():
note = self._db.get_note_from_handle(notehandle)
text = note.get_styledtext()
note_format = note.get_format()
self.doc.write_styled_note(text, note_format, 'IDS-Normal',
contains_html= note.get_type() == NoteType.HTML_CODE)
self.doc.write_styled_note(
text, note_format, 'IDS-Normal',
contains_html=(note.get_type() == NoteType.HTML_CODE))
self.doc.end_cell()
self.doc.end_row()
def write_p_entry(self, label, parent_name, rel_type, pmark=None):
""" write parent entry """
self.doc.start_row()
self.write_cell(label)
if parent_name:
# for example (a stepfather): John Smith, relationship: Step
text = self._('%(parent-name)s, relationship: %(rel-type)s') % {
'parent-name' : parent_name,
'rel-type' : self._(rel_type)}
text = self._(
'%(parent-name)s, relationship: %(rel-type)s') % {
'parent-name' : parent_name,
'rel-type' : self._(rel_type)}
self.write_cell(text, mark=pmark)
else:
self.write_cell('')
self.doc.end_row()
def write_note(self):
""" write a note """
notelist = self.person.get_note_list()
notelist += self.family_notes_list
if not notelist:
if not notelist or not self.use_notes:
return
self.doc.start_table('note','IDS-IndTable')
self.doc.start_table('note', 'IDS-IndTable')
self.doc.start_row()
self.doc.start_cell('IDS-TableHead', 2)
self.write_paragraph(self._('Notes'), style='IDS-TableTitle')
@ -240,8 +258,9 @@ class IndivCompleteReport(Report):
note_format = note.get_format()
self.doc.start_row()
self.doc.start_cell('IDS-NormalCell', 2)
self.doc.write_styled_note(text, note_format, 'IDS-Normal',
contains_html= note.get_type() == NoteType.HTML_CODE)
self.doc.write_styled_note(
text, note_format, 'IDS-Normal',
contains_html=(note.get_type() == NoteType.HTML_CODE))
self.doc.end_cell()
self.doc.end_row()
@ -251,12 +270,13 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_alt_parents(self):
""" write any alternate parents """
family_handle_list = self.person.get_parent_family_handle_list()
if len(family_handle_list) < 2:
return
self.doc.start_table("altparents","IDS-IndTable")
self.doc.start_table("altparents", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Alternate Parents'),
@ -265,8 +285,7 @@ class IndivCompleteReport(Report):
self.doc.end_row()
for family_handle in family_handle_list:
if (family_handle ==
self.person.get_main_parents_family_handle()):
if family_handle == self.person.get_main_parents_family_handle():
continue
family = self._db.get_family_from_handle(family_handle)
@ -304,19 +323,21 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def get_name(self, person):
""" prepare the name to display """
name = self._name_display.display(person)
if self.use_gramps_id:
return '%(name)s [%(gid)s]' % { 'name': name,
'gid': person.get_gramps_id()}
return '%(name)s [%(gid)s]' % {'name': name,
'gid': person.get_gramps_id()}
else:
return name
def write_alt_names(self):
""" write any alternate names of the person """
if len(self.person.get_alternate_names()) < 1:
return
self.doc.start_table("altnames","IDS-IndTable")
self.doc.start_table("altnames", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Alternate Names'),
@ -337,13 +358,14 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_addresses(self):
""" write any addresses of the person """
alist = self.person.get_address_list()
if len(alist) == 0:
return
self.doc.start_table("addresses","IDS-IndTable")
self.doc.start_table("addresses", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Addresses'), style='IDS-TableTitle')
@ -363,11 +385,12 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_associations(self):
""" write any associations of the person """
if len(self.person.get_person_ref_list()) < 1:
return
self.doc.start_table("associations","IDS-IndTable")
self.doc.start_table("associations", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Associations'), style='IDS-TableTitle')
@ -387,13 +410,14 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_attributes(self):
""" write any attributes of the person """
attr_list = self.person.get_attribute_list()
if len(attr_list) == 0:
if len(attr_list) == 0 or not self.use_attrs:
return
self.doc.start_table("attributes","IDS-IndTable")
self.doc.start_table("attributes", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Attributes'), style='IDS-TableTitle')
@ -413,13 +437,14 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_LDS_ordinances(self):
""" write any LDS ordinances of the person """
ord_list = self.person.get_lds_ord_list()
if len(ord_list) == 0:
return
self.doc.start_table("ordinances","IDS-IndTable")
self.doc.start_table("ordinances", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('LDS Ordinance'), style='IDS-TableTitle')
@ -427,7 +452,7 @@ class IndivCompleteReport(Report):
self.doc.end_row()
self.doc.end_table()
self.doc.start_table("ordinances3","IDS-OrdinanceTable")
self.doc.start_table("ordinances3", "IDS-OrdinanceTable")
self.doc.start_row()
self.write_cell(self._('Type'), style='IDS-Section')
self.write_cell(self._('Date'), style='IDS-Section')
@ -437,7 +462,7 @@ class IndivCompleteReport(Report):
self.doc.end_row()
for lds_ord in ord_list:
type = self._(lds_ord.type2str())
otype = self._(lds_ord.type2str())
date = self._get_date(lds_ord.get_date_object())
status = self._(lds_ord.status2str())
temple = TEMPLES.name(lds_ord.get_temple())
@ -450,7 +475,7 @@ class IndivCompleteReport(Report):
place_endnote = self._cite_endnote(place)
endnotes = self._cite_endnote(lds_ord, prior=place_endnote)
self.doc.start_row()
self.write_cell(type, endnotes)
self.write_cell(otype, endnotes)
self.write_cell(date)
self.write_cell(status)
self.write_cell(temple)
@ -461,13 +486,14 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_tags(self):
""" write any tags the person has """
thlist = self.person.get_tag_list()
if len(thlist) == 0:
if len(thlist) == 0 or not self.use_tags:
return
tags = []
self.doc.start_table("tags","IDS-IndTable")
self.doc.start_table("tags", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Tags'), style='IDS-TableTitle')
@ -485,6 +511,7 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_images(self):
""" write any images the person has """
media_list = self.person.get_media_list()
if (not self.use_images) or (not media_list):
@ -504,10 +531,10 @@ class IndivCompleteReport(Report):
# will be shown up at the top, so there's no reason to show it here;
# but if there's only one image and it is not the first Gallery
# item (maybe the first is a PDF, say), then we need to show it
if ((i_total == 1) and self.mime0 and self.mime0.startswith("image")):
if (i_total == 1) and self.mime0 and self.mime0.startswith("image"):
return
self.doc.start_table("images","IDS-GalleryTable")
self.doc.start_table("images", "IDS-GalleryTable")
cells = 3 # the GalleryTable has 3 cells
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", cells)
@ -516,7 +543,7 @@ class IndivCompleteReport(Report):
self.doc.end_row()
media_count = 0
image_count = 0
while ( media_count < len(media_list) ):
while media_count < len(media_list):
media_ref = media_list[media_count]
media_handle = media_ref.get_reference_handle()
media = self._db.get_media_from_handle(media_handle)
@ -536,7 +563,7 @@ class IndivCompleteReport(Report):
ReportUtils.insert_image(self._db, self.doc, media_ref, self._user,
align='center', w_cm=5.0, h_cm=5.0)
self.do_attributes(media.get_attribute_list() +
media_ref.get_attribute_list() )
media_ref.get_attribute_list())
self.doc.end_cell()
if image_count % cells == cells - 1:
self.doc.end_row()
@ -549,12 +576,13 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_families(self):
""" write any families the person has """
family_handle_list = self.person.get_family_handle_list()
if not len(family_handle_list):
return
self.doc.start_table("three","IDS-IndTable")
self.doc.start_table("three", "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._('Families'),
@ -564,7 +592,7 @@ class IndivCompleteReport(Report):
self.doc.end_table()
for family_handle in family_handle_list:
self.doc.start_table("three","IDS-IndTable")
self.doc.start_table("three", "IDS-IndTable")
family = self._db.get_family_from_handle(family_handle)
self.family_notes_list += family.get_note_list()
if self.person.get_handle() == family.get_father_handle():
@ -606,7 +634,7 @@ class IndivCompleteReport(Report):
self.doc.end_row()
attr_list = family.get_attribute_list()
if len(attr_list):
if len(attr_list) and self.use_attrs:
self.doc.start_row()
self.write_cell(self._("Attributes"))
self.doc.start_cell("IDS-ListCell")
@ -618,7 +646,7 @@ class IndivCompleteReport(Report):
ord_list = family.get_lds_ord_list()
if len(ord_list):
self.doc.start_table("ordinances2","IDS-OrdinanceTable2")
self.doc.start_table("ordinances2", "IDS-OrdinanceTable2")
self.doc.start_row()
self.write_cell(self._('LDS Ordinance'))
self.write_cell(self._('Type'), style='IDS-Section')
@ -629,7 +657,7 @@ class IndivCompleteReport(Report):
self.doc.end_row()
for lds_ord in ord_list:
type = self._(lds_ord.type2str())
otype = self._(lds_ord.type2str())
date = self._get_date(lds_ord.get_date_object())
status = self._(lds_ord.status2str())
temple = TEMPLES.name(lds_ord.get_temple())
@ -638,12 +666,13 @@ class IndivCompleteReport(Report):
place_handle = lds_ord.get_place_handle()
if place_handle:
place = self._db.get_place_from_handle(place_handle)
place_name = place_displayer.display_event(self._db, lds_ord)
place_name = place_displayer.display_event(self._db,
lds_ord)
place_endnote = self._cite_endnote(place)
endnotes = self._cite_endnote(lds_ord, prior=place_endnote)
self.doc.start_row()
self.write_cell('')
self.write_cell(type, endnotes)
self.write_cell(otype, endnotes)
self.write_cell(date)
self.write_cell(status)
self.write_cell(temple)
@ -664,6 +693,9 @@ class IndivCompleteReport(Report):
if event_ref:
event = self._db.get_event_from_handle(event_ref.ref)
if event:
if (event.get_type() == EventType.CENSUS
and not self.use_census):
continue
sort_value = event.get_date_object().get_sort_value()
#first sort on date, equal dates, then sort as in GUI.
event_list.append((str(sort_value) + "%04i" % ind,
@ -674,14 +706,14 @@ class IndivCompleteReport(Report):
return [(item[1], item[2]) for item in event_list]
def write_section(self, event_ref_list, event_group):
def write_section(self, event_ref_list, event_group_sect):
"""
Writes events in a single event group.
"""
self.doc.start_table(event_group,"IDS-IndTable")
self.doc.start_table(event_group_sect, "IDS-IndTable")
self.doc.start_row()
self.doc.start_cell("IDS-TableHead", 2)
self.write_paragraph(self._(event_group), style='IDS-TableTitle')
self.write_paragraph(self._(event_group_sect), style='IDS-TableTitle')
self.doc.end_cell()
self.doc.end_row()
@ -716,12 +748,14 @@ class IndivCompleteReport(Report):
def write_cell(self, text,
endnotes=None, mark=None, style='IDS-Normal', span=1):
""" write a cell """
self.doc.start_cell('IDS-NormalCell', span)
self.write_paragraph(text, endnotes=endnotes, mark=mark, style=style)
self.doc.end_cell()
def write_paragraph(self, text,
endnotes=None, mark=None, style='IDS-Normal'):
""" write a paragraph """
self.doc.start_paragraph(style)
self.doc.write_text(text, mark)
if endnotes:
@ -731,6 +765,7 @@ class IndivCompleteReport(Report):
self.doc.end_paragraph()
def write_report(self):
""" write the report """
plist = self._db.get_person_handles(sort_handles=True)
if self.filter:
ind_list = self.filter.apply(self._db, plist)
@ -739,20 +774,27 @@ class IndivCompleteReport(Report):
for count, person_handle in enumerate(ind_list):
self.person = self._db.get_person_from_handle(person_handle)
if self.person is None:
continue
self.family_notes_list = []
self.write_person(count)
def write_person(self, count):
""" write a person """
if count != 0:
self.doc.page_break()
self.bibli = Bibliography(Bibliography.MODE_DATE|Bibliography.MODE_PAGE)
self.bibli = Bibliography(
Bibliography.MODE_DATE|Bibliography.MODE_PAGE)
text = self._name_display.display(self.person)
# feature request 2356: avoid genitive form
title = self._("Complete Individual Report: %s") % text
mark = IndexMark(title, INDEX_TYPE_TOC, 1)
title1 = self._("Complete Individual Report")
text2 = self._name_display.display(self.person)
mark1 = IndexMark(title1, INDEX_TYPE_TOC, 1)
mark2 = IndexMark(text2, INDEX_TYPE_TOC, 2)
self.doc.start_paragraph("IDS-Title")
self.doc.write_text(title, mark)
self.doc.write_text(title1, mark1)
self.doc.end_paragraph()
self.doc.start_paragraph("IDS-Title")
self.doc.write_text(text2, mark2)
self.doc.end_paragraph()
self.doc.start_paragraph("IDS-Normal")
@ -805,16 +847,16 @@ class IndivCompleteReport(Report):
else:
self._user.warn(_("Could not add photo to page"),
# translators: for French, else ignore
_("%(str1)s: %(str2)s") %
{'str1' : image_filename,
'str2' : _('File does not exist') } )
_("%(str1)s: %(str2)s") % {
'str1' : image_filename,
'str2' : _('File does not exist')})
self.doc.start_table('person', p_style)
self.doc.start_row()
self.doc.start_cell('IDS-NormalCell')
# translators: needed for French, ignore otherwise
ignore4 = self._("%s:")
ignore = self._("%s:")
self.doc.start_cell('IDS-NormalCell')
self.write_paragraph(self._("%s:") % self._("Name"))
self.write_paragraph(self._("%s:") % self._("Gender"))
self.write_paragraph(self._("%s:") % self._("Father"))
@ -836,18 +878,19 @@ class IndivCompleteReport(Report):
if p_style == 'IDS-PersonTable':
self.doc.start_cell('IDS-NormalCell')
self.doc.add_media(image_filename, "right", 4.0, 4.0,
crop=media0.get_rectangle())
crop=media0.get_rectangle())
endnotes = self._cite_endnote(media0)
attr_list = media0.get_attribute_list()
if len(attr_list) == 0:
if len(attr_list) == 0 or not self.use_attrs:
text = _('(image)')
else:
for attr in attr_list:
attr_type = attr.get_type().type2base()
# translators: needed for French, ignore otherwise
text = self._("%(str1)s: %(str2)s") % {
'str1' : self._(attr_type),
'str2' : attr.get_value() }
text = self._(
"%(str1)s: %(str2)s") % {
'str1' : self._(attr_type),
'str2' : attr.get_value()}
endnotes = self._cite_endnote(attr, prior=endnotes)
self.write_paragraph("(%s)" % text,
endnotes=endnotes,
@ -879,7 +922,7 @@ class IndivCompleteReport(Report):
if self.use_pagebreak and self.bibli.get_citation_count():
self.doc.page_break()
Endnotes.write_endnotes(self.bibli, self._db, self.doc,
printnotes=self.use_srcs_notes,
printnotes=self.use_src_notes,
elocale=self._locale)
def combine(self, format_both, format_single, str1, str2):
@ -894,6 +937,7 @@ class IndivCompleteReport(Report):
return text
def _cite_endnote(self, obj, prior=''):
""" cite any endnotes the person has """
if not self.use_srcs:
return ""
if not obj:
@ -908,12 +952,16 @@ class IndivCompleteReport(Report):
return txt
def do_attributes(self, attr_list):
""" a convenience method """
if not self.use_attrs:
return
for attr in attr_list:
attr_type = attr.get_type().type2base()
# translators: needed for French, ignore otherwise
text = self._("%(type)s: %(value)s") % {
'type' : self._(attr_type),
'value' : attr.get_value() }
text = self._(
"%(type)s: %(value)s") % {
'type' : self._(attr_type),
'value' : attr.get_value()}
endnotes = self._cite_endnote(attr)
self.write_paragraph(text, endnotes)
@ -930,6 +978,9 @@ class IndivCompleteOptions(MenuReportOptions):
self.__db = dbase
self.__pid = None
self.__filter = None
self.__cites = None
self.__incsrcnotes = None
self._nf = None
MenuReportOptions.__init__(self, name, dbase)
def add_menu_options(self, menu):
@ -939,7 +990,7 @@ class IndivCompleteOptions(MenuReportOptions):
self.__filter = FilterOption(_("Filter"), 0)
self.__filter.set_help(
_("Select the filter to be applied to the report."))
_("Select the filter to be applied to the report."))
menu.add_option(category_name, "filter", self.__filter)
self.__filter.connect('value-changed', self.__filter_changed)
@ -961,9 +1012,9 @@ class IndivCompleteOptions(MenuReportOptions):
sort.set_help(_("Whether to sort events into chronological order."))
menu.add_option(category_name, "sort", sort)
pageben = BooleanOption(_("Page break before end notes"),False)
pageben = BooleanOption(_("Page break before end notes"), False)
pageben.set_help(
_("Whether to start a new page before the end notes."))
_("Whether to start a new page before the end notes."))
menu.add_option(category_name, "pageben", pageben)
stdoptions.add_localization_option(menu, category_name)
@ -972,23 +1023,43 @@ class IndivCompleteOptions(MenuReportOptions):
category_name = _("Include")
################################
cites = BooleanOption(_("Include Source Information"), True)
cites.set_help(_("Whether to cite sources."))
menu.add_option(category_name, "cites", cites)
self.__cites = BooleanOption(_("Include Source Information"), True)
self.__cites.set_help(_("Whether to cite sources."))
menu.add_option(category_name, "cites", self.__cites)
self.__cites.connect('value-changed', self.__sources_changed)
incsrcnotes = BooleanOption(_("Include sources notes"), False)
incsrcnotes.set_help(_("Whether to include source notes in the "
"Endnotes section. Only works if Include sources is selected."))
menu.add_option(category_name, "incsrcnotes", incsrcnotes)
self.__incsrcnotes = BooleanOption(_("Include sources notes"), False)
self.__incsrcnotes.set_help(
_("Whether to include source notes in the Endnotes section. "
"Only works if Include sources is selected."))
menu.add_option(category_name, "incsrcnotes", self.__incsrcnotes)
self.__incsrcnotes.connect('value-changed', self.__sources_changed)
self.__sources_changed()
images = BooleanOption(_("Include Photo/Images from Gallery"), True)
images.set_help(_("Whether to include images."))
menu.add_option(category_name, "images", images)
attributes = BooleanOption(_("Include Attributes"), True)
attributes.set_help(_("Whether to include attributes."))
menu.add_option(category_name, "incl_attrs", attributes)
census = BooleanOption(_("Include Census Events"), True)
census.set_help(_("Whether to include Census Events."))
menu.add_option(category_name, "incl_census", census)
grampsid = BooleanOption(_("Include Gramps ID"), False)
grampsid.set_help(_("Whether to include Gramps ID next to names."))
menu.add_option(category_name, "grampsid", grampsid)
incl_notes = BooleanOption(_("Include Notes"), True)
incl_notes.set_help(_("Whether to include Person and Family Notes."))
menu.add_option(category_name, "incl_notes", incl_notes)
tags = BooleanOption(_("Include Tags"), True)
tags.set_help(_("Whether to include tags."))
menu.add_option(category_name, "incl_tags", tags)
################################
category_name = _("Sections")
################################
@ -1026,6 +1097,16 @@ class IndivCompleteOptions(MenuReportOptions):
# The rest don't
self.__pid.set_available(False)
def __sources_changed(self):
"""
If Endnotes are not enabled, disable sources in the Endnotes.
"""
cites_value = self.__cites.get_value()
if cites_value:
self.__incsrcnotes.set_available(True)
else:
self.__incsrcnotes.set_available(False)
def make_default_style(self, default_style):
"""Make the default output style for the Individual Complete Report."""
# Paragraph Styles
@ -1133,37 +1214,37 @@ class IndivCompleteOptions(MenuReportOptions):
tbl = TableStyle()
tbl.set_width(100)
tbl.set_columns(3)
tbl.set_column_width(0,20)
tbl.set_column_width(1,50)
tbl.set_column_width(2,30)
tbl.set_column_width(0, 20)
tbl.set_column_width(1, 50)
tbl.set_column_width(2, 30)
default_style.add_table_style('IDS-PersonTable', tbl)
tbl = TableStyle()
tbl.set_width(100)
tbl.set_columns(2)
tbl.set_column_width(0,20)
tbl.set_column_width(1,80)
tbl.set_column_width(0, 20)
tbl.set_column_width(1, 80)
default_style.add_table_style('IDS-PersonTable2', tbl)
tbl = TableStyle()
tbl.set_width(100)
tbl.set_columns(5)
tbl.set_column_width(0,22) # Type
tbl.set_column_width(1,22) # Date
tbl.set_column_width(2,16) # Status
tbl.set_column_width(3,22) # Temple
tbl.set_column_width(4,18) # Place
tbl.set_column_width(0, 22) # Type
tbl.set_column_width(1, 22) # Date
tbl.set_column_width(2, 16) # Status
tbl.set_column_width(3, 22) # Temple
tbl.set_column_width(4, 18) # Place
default_style.add_table_style('IDS-OrdinanceTable', tbl)
tbl = TableStyle()
tbl.set_width(100)
tbl.set_columns(6)
tbl.set_column_width(0,20) # empty
tbl.set_column_width(1,18) # Type
tbl.set_column_width(2,18) # Date
tbl.set_column_width(3,14) # Status
tbl.set_column_width(4,18) # Temple
tbl.set_column_width(5,12) # Place
tbl.set_column_width(0, 20) # empty
tbl.set_column_width(1, 18) # Type
tbl.set_column_width(2, 18) # Date
tbl.set_column_width(3, 14) # Status
tbl.set_column_width(4, 18) # Temple
tbl.set_column_width(5, 12) # Place
default_style.add_table_style('IDS-OrdinanceTable2', tbl)
tbl = TableStyle()

View File

@ -77,6 +77,7 @@ class RecordsReport(Report):
stdoptions.run_private_data_option(self, menu)
living_opt = stdoptions.run_living_people_option(self, menu,
self._locale)
self.database = CacheProxyDb(self.database)
self._lv = menu.get_option_by_name('living_people').get_value()
for (value, description) in living_opt.get_items(xml_items=True):
@ -100,8 +101,6 @@ class RecordsReport(Report):
self._nf = stdoptions.run_name_format_option(self, menu)
self.database = CacheProxyDb(self.database)
def write_report(self):
"""
Build the actual report.
@ -109,7 +108,8 @@ class RecordsReport(Report):
records = find_records(self.database, self.filter,
self.top_size, self.callname,
trans_text=self._, name_format=self._nf)
trans_text=self._, name_format=self._nf,
living_mode=self._lv)
self.doc.start_paragraph('REC-Title')
title = self._("Records")

View File

@ -88,6 +88,7 @@ class TagReport(Report):
stdoptions.run_private_data_option(self, menu)
living_opt = stdoptions.run_living_people_option(self, menu, rlocale)
self.database = CacheProxyDb(self.database)
self._lv = menu.get_option_by_name('living_people').get_value()
for (value, description) in living_opt.get_items(xml_items=True):
@ -104,8 +105,6 @@ class TagReport(Report):
stdoptions.run_name_format_option(self, menu)
self.database = CacheProxyDb(self.database)
def write_report(self):
self.doc.start_paragraph("TR-Title")
# feature request 2356: avoid genitive form

View File

@ -23,22 +23,6 @@
"Find unused objects and remove with the user's permission."
#-------------------------------------------------------------------------
#
# python modules
#
#-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
log = logging.getLogger(".RemoveUnused")
#-------------------------------------------------------------------------
#
# gtk modules
@ -62,6 +46,8 @@ from gramps.gen.updatecallback import UpdateCallback
from gramps.gui.plug import tool
from gramps.gui.glade import Glade
from gramps.gen.filters import GenericFilterFactory, rules
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
#-------------------------------------------------------------------------
#
@ -69,10 +55,10 @@ from gramps.gen.filters import GenericFilterFactory, rules
#
#-------------------------------------------------------------------------
class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
MARK_COL = 0
OBJ_ID_COL = 1
OBJ_NAME_COL = 2
OBJ_TYPE_COL = 3
MARK_COL = 0
OBJ_ID_COL = 1
OBJ_NAME_COL = 2
OBJ_TYPE_COL = 3
OBJ_HANDLE_COL = 4
def __init__(self, dbstate, user, options_class, name, callback=None):
@ -84,55 +70,55 @@ class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
if self.db.readonly:
return
ManagedWindow.__init__(self, uistate,[], self.__class__)
ManagedWindow.__init__(self, uistate, [], self.__class__)
UpdateCallback.__init__(self, self.uistate.pulse_progressbar)
self.dbstate = dbstate
self.uistate = uistate
self.tables = {
'events' : {'get_func': self.db.get_event_from_handle,
'remove' : self.db.remove_event,
'get_text': self.get_event_text,
'editor' : 'EditEvent',
'icon' : 'gramps-event',
'name_ix' : 4},
'sources' : {'get_func': self.db.get_source_from_handle,
'remove' : self.db.remove_source,
'get_text': None,
'editor' : 'EditSource',
'icon' : 'gramps-source',
'name_ix' : 2},
'citations' : {'get_func': self.db.get_citation_from_handle,
'remove' : self.db.remove_citation,
'get_text': None,
'editor' : 'EditCitation',
'icon' : 'gramps-citation',
'name_ix' : 3},
'places' : {'get_func': self.db.get_place_from_handle,
'remove' : self.db.remove_place,
'get_text': None,
'editor' : 'EditPlace',
'icon' : 'gramps-place',
'name_ix' : 2},
'media' : {'get_func': self.db.get_media_from_handle,
'remove' : self.db.remove_media,
'get_text': None,
'editor' : 'EditMedia',
'icon' : 'gramps-media',
'name_ix' : 4},
'repos' : {'get_func': self.db.get_repository_from_handle,
'remove' : self.db.remove_repository,
'get_text': None,
'editor' : 'EditRepository',
'icon' : 'gramps-repository',
'name_ix' : 3},
'notes' : {'get_func': self.db.get_note_from_handle,
'remove' : self.db.remove_note,
'get_text': self.get_note_text,
'editor' : 'EditNote',
'icon' : 'gramps-notes',
'name_ix' : 2},
'events': {'get_func': self.db.get_event_from_handle,
'remove': self.db.remove_event,
'get_text': self.get_event_text,
'editor': 'EditEvent',
'icon': 'gramps-event',
'name_ix': 4},
'sources': {'get_func': self.db.get_source_from_handle,
'remove': self.db.remove_source,
'get_text': None,
'editor': 'EditSource',
'icon': 'gramps-source',
'name_ix': 2},
'citations': {'get_func': self.db.get_citation_from_handle,
'remove': self.db.remove_citation,
'get_text': None,
'editor': 'EditCitation',
'icon': 'gramps-citation',
'name_ix': 3},
'places': {'get_func': self.db.get_place_from_handle,
'remove': self.db.remove_place,
'get_text': None,
'editor': 'EditPlace',
'icon': 'gramps-place',
'name_ix': 2},
'media': {'get_func': self.db.get_media_from_handle,
'remove': self.db.remove_media,
'get_text': None,
'editor': 'EditMedia',
'icon': 'gramps-media',
'name_ix': 4},
'repos': {'get_func': self.db.get_repository_from_handle,
'remove': self.db.remove_repository,
'get_text': None,
'editor': 'EditRepository',
'icon': 'gramps-repository',
'name_ix': 3},
'notes': {'get_func': self.db.get_note_from_handle,
'remove': self.db.remove_note,
'get_text': self.get_note_text,
'editor': 'EditNote',
'icon': 'gramps-notes',
'name_ix': 2},
}
self.init_gui()
@ -192,12 +178,12 @@ class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
# Add mark column
mark_column = Gtk.TreeViewColumn(_('Mark'), self.bool_renderer,
active=RemoveUnused.MARK_COL)
active=RemoveUnused.MARK_COL)
mark_column.set_sort_column_id(RemoveUnused.MARK_COL)
self.warn_tree.append_column(mark_column)
# Add image column
img_column = Gtk.TreeViewColumn(None, self.img_renderer )
img_column = Gtk.TreeViewColumn(None, self.img_renderer)
img_column.set_cell_data_func(self.img_renderer, self.get_image)
self.warn_tree.append_column(img_column)
@ -236,13 +222,13 @@ class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
def find(self, obj):
self.options.handler.options_dict.update(
events = self.events_box.get_active(),
sources = self.sources_box.get_active(),
citations = self.citations_box.get_active(),
places = self.places_box.get_active(),
media = self.media_box.get_active(),
repos = self.repos_box.get_active(),
notes = self.notes_box.get_active(),
events=self.events_box.get_active(),
sources=self.sources_box.get_active(),
citations=self.citations_box.get_active(),
places=self.places_box.get_active(),
media=self.media_box.get_active(),
repos=self.repos_box.get_active(),
notes=elf.notes_box.get_active(),
)
for item in self.sensitive_list:
@ -364,8 +350,7 @@ class RemoveUnused(tool.Tool, ManagedWindow, UpdateCallback):
try:
obj = self.tables[the_type]['get_func'](handle)
editor_str = 'from gramps.gui.editors import %s as editor' % (
self.tables[the_type]['editor']
)
self.tables[the_type]['editor'])
exec(editor_str, globals())
editor(self.dbstate, self.uistate, [], obj)
except WindowActiveError:
@ -458,34 +443,34 @@ class CheckOptions(tool.ToolOptions):
# Options specific for this report
self.options_dict = {
'events' : 1,
'sources' : 1,
'citations' : 1,
'places' : 1,
'media' : 1,
'repos' : 1,
'notes' : 1,
'events': 1,
'sources': 1,
'citations': 1,
'places': 1,
'media': 1,
'repos': 1,
'notes': 1,
}
self.options_help = {
'events' : ("=0/1","Whether to use check for unused events",
["Do not check events","Check events"],
True),
'sources' : ("=0/1","Whether to use check for unused sources",
["Do not check sources","Check sources"],
True),
'citations' : ("=0/1","Whether to use check for unused citations",
["Do not check citations","Check citations"],
True),
'places' : ("=0/1","Whether to use check for unused places",
["Do not check places","Check places"],
True),
'media' : ("=0/1","Whether to use check for unused media",
["Do not check media","Check media"],
True),
'repos' : ("=0/1","Whether to use check for unused repositories",
["Do not check repositories","Check repositories"],
True),
'notes' : ("=0/1","Whether to use check for unused notes",
["Do not check notes","Check notes"],
'events': ("=0/1", "Whether to use check for unused events",
["Do not check events", "Check events"],
True),
'sources': ("=0/1", "Whether to use check for unused sources",
["Do not check sources", "Check sources"],
True),
'citations': ("=0/1", "Whether to use check for unused citations",
["Do not check citations", "Check citations"],
True),
'places': ("=0/1", "Whether to use check for unused places",
["Do not check places", "Check places"],
True),
'media': ("=0/1", "Whether to use check for unused media",
["Do not check media", "Check media"],
True),
'repos': ("=0/1", "Whether to use check for unused repositories",
["Do not check repositories", "Check repositories"],
True),
'notes': ("=0/1", "Whether to use check for unused notes",
["Do not check notes", "Check notes"],
True),
}

View File

@ -441,9 +441,10 @@ class GeoClose(GeoGraphyView):
if father:
descr1 = "%s - " % _nd.display(father)
handle = fam.get_mother_handle()
mother = dbstate.db.get_person_from_handle(handle)
if mother:
descr1 = "%s%s" % (descr1, _nd.display(mother))
if handle:
mother = dbstate.db.get_person_from_handle(handle)
if mother:
descr1 = "%s%s" % (descr1, _nd.display(mother))
for event_ref in family.get_event_ref_list():
if event_ref:
event = dbstate.db.get_event_from_handle(

File diff suppressed because it is too large Load Diff