This commit is contained in:
romjerome 2017-02-17 16:11:07 +01:00
commit 64208cf9b9
55 changed files with 8644 additions and 7541 deletions

View File

@ -194,9 +194,9 @@ class CLIDbManager:
for item in sorted(summary):
if item != "Family Tree":
# translators: needed for French, ignore otherwise
print(_(" %(item)s: %(summary)s") % {
'item' : item,
'summary' : summary[item]})
print(' ' + _("%(str1)s: %(str2)s"
) % {'str1' : item,
'str2' : summary[item]})
def family_tree_summary(self, database_names=None):
"""

View File

@ -43,7 +43,7 @@ from .proxy.proxybase import ProxyDbBase
from .utils.callback import Callback
from .config import config
from gramps.gen.db.dbconst import DBLOGNAME
from gramps.gen.db.utils import make_database
from gramps.gen.db.dummydb import DummyDb
#-------------------------------------------------------------------------
#
@ -69,7 +69,7 @@ class DbState(Callback):
place holder until a real DB is assigned.
"""
Callback.__init__(self)
self.db = make_database("dummydb")
self.db = DummyDb()
self.open = False # Deprecated - use DbState.is_open()
self.stack = []
@ -135,7 +135,7 @@ class DbState(Callback):
self.emit('no-database', ())
if self.is_open():
self.db.close()
self.db = make_database("dummydb")
self.db = DummyDb()
self.open = False
self.emit('database-changed', (self.db, ))

View File

@ -109,6 +109,7 @@ from ._matchidof import MatchIdOf
from ._regexpidof import RegExpIdOf
from ._changedsince import ChangedSince
from ._isrelatedwith import IsRelatedWith
from ._hassoundexname import HasSoundexName
#-------------------------------------------------------------------------
#
@ -189,5 +190,6 @@ editor_rule_list = [
Disconnected,
ChangedSince,
IsRelatedWith,
HasSoundexName,
]

View File

@ -106,6 +106,8 @@ def find_deep_relations(db, user, person, path, seen, target_people):
if handle in seen:
return []
seen.append(handle)
if user:
user.step_progress()
return_paths = []
person_path = path + [handle]
@ -118,8 +120,6 @@ def find_deep_relations(db, user, person, path, seen, target_people):
for family_person in family_people:
pers = db.get_person_from_handle(family_person)
return_paths += find_deep_relations(db, user, pers, person_path, seen, target_people)
if user:
user.step_progress()
return return_paths

View File

@ -64,12 +64,20 @@ class HasCommonAncestorWithFilterMatch(HasCommonAncestorWith):
self.with_people = []
filt = MatchesFilter(self.list)
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for handle in db.iter_person_handles():
person = db.get_person_from_handle(handle)
if user:
user.step_progress()
if person and filt.apply(db, person):
#store all people in the filter so as to compare later
self.with_people.append(person.handle)
#fill list of ancestor of person if not present yet
if handle not in self.ancestor_cache:
self.add_ancs(db, person)
if user:
user.end_progress()
filt.requestreset()

View File

@ -0,0 +1,86 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2017 Paul Culley <paulr2787_at_gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from ....const import GRAMPS_LOCALE as glocale
_ = glocale.translation.sgettext
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from .. import Rule
from ....lib.nameorigintype import NameOriginType
from gramps.gen.soundex import soundex
#-------------------------------------------------------------------------
#
# HasNameOf
#
#-------------------------------------------------------------------------
class HasSoundexName(Rule):
"""Rule that checks for full or partial name matches"""
labels = [_('Name:')]
name = _('Soundex match of People with the <name>')
description = _("Soundex Match of people with a specified name. First "
"name, Surname, Call name, and Nickname are searched in "
"primary and alternate names.")
category = _('General filters')
allow_regex = False
def apply(self, db, person):
self.sndx = soundex(self.list[0])
for name in [person.get_primary_name()] + person.get_alternate_names():
if self._match_name(name):
return True
return False
def _match_name(self, name):
if self.list[0]:
if soundex(str(name.get_first_name())) == self.sndx:
return True
elif soundex(str(name.get_surname())) == self.sndx:
return True
elif soundex(str(name.get_call_name())) == self.sndx:
return True
elif soundex(str(name.get_nick_name())) == self.sndx:
return True
elif soundex(str(name.get_family_nick_name())) == self.sndx:
return True
else:
for surn in name.get_surname_list():
if self._match_surname(surn):
return True
return False
def _match_surname(self, surn):
if soundex(str(surn.get_surname())) == self.sndx:
return True
if surn.get_origintype().value == NameOriginType.PATRONYMIC:
if soundex(str(surn.get_surname())) == self.sndx:
return True
return False

View File

@ -62,9 +62,17 @@ class IsAncestorOfFilterMatch(IsAncestorOf):
filt = MatchesFilter(self.list[0:1])
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for person in db.iter_people():
if user:
user.step_progress()
if filt.apply(db, person):
self.init_ancestor_list(db, person, first)
if user:
user.end_progress()
filt.requestreset()
def reset(self):

View File

@ -53,9 +53,17 @@ class IsChildOfFilterMatch(Rule):
self.map = set()
filt = MatchesFilter(self.list)
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for person in db.iter_people():
if user:
user.step_progress()
if filt.apply(db, person):
self.init_list(person)
if user:
user.end_progress()
filt.requestreset()
def reset(self):

View File

@ -55,8 +55,16 @@ class IsDescendantFamilyOfFilterMatch(IsDescendantFamilyOf):
filt = MatchesFilter(self.list[0:1])
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for person in db.iter_people():
if user:
user.step_progress()
if filt.apply(db, person):
self.add_matches(person)
if user:
user.end_progress()
filt.requestreset()

View File

@ -62,9 +62,17 @@ class IsDescendantOfFilterMatch(IsDescendantOf):
filt = MatchesFilter(self.list[0:1])
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for person in db.iter_people():
if user:
user.step_progress()
if filt.apply(db, person):
self.init_list(person, first)
if user:
user.end_progress()
filt.requestreset()
def reset(self):

View File

@ -53,9 +53,17 @@ class IsParentOfFilterMatch(Rule):
self.map = set()
filt = MatchesFilter(self.list)
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for person in db.iter_people():
if user:
user.step_progress()
if filt.apply(db, person):
self.init_list(person)
if user:
user.end_progress()
filt.requestreset()
def reset(self):

View File

@ -52,9 +52,17 @@ class IsSiblingOfFilterMatch(Rule):
self.map = set()
filt = MatchesFilter(self.list)
filt.requestprepare(db, user)
if user:
user.begin_progress(self.category,
_('Retrieving all sub-filter matches'),
db.get_number_of_people())
for person in db.iter_people():
if user:
user.step_progress()
if filt.apply (db, person):
self.init_list (person)
if user:
user.end_progress()
filt.requestreset()
def reset(self):
@ -67,8 +75,9 @@ class IsSiblingOfFilterMatch(Rule):
if not person:
return
fam_id = person.get_main_parents_family_handle()
fam = self.db.get_family_from_handle(fam_id)
if fam:
self.map.update(child_ref.ref
for child_ref in fam.get_child_ref_list()
if fam_id:
fam = self.db.get_family_from_handle(fam_id)
if fam:
self.map.update(
child_ref.ref for child_ref in fam.get_child_ref_list()
if child_ref and child_ref.ref != person.handle)

View File

@ -36,7 +36,7 @@ from gramps.gen.filters.rules.person import (
IsDuplicatedAncestorOf, IsRelatedWith, HasIdOf, IsDefaultPerson, IsFemale,
IsMale, MissingParent, MultipleMarriages, NeverMarried, NoBirthdate,
NoDeathdate, PeoplePrivate, PeoplePublic, PersonWithIncompleteEvent,
RelationshipPathBetweenBookmarks)
RelationshipPathBetweenBookmarks, HasNameOf, HasSoundexName)
TEST_DIR = os.path.abspath(os.path.join(DATA_DIR, "tests"))
EXAMPLE = os.path.join(TEST_DIR, "example.gramps")
@ -564,6 +564,22 @@ class BaseTest(unittest.TestCase):
b'D3WJQCCGV58IP8PNHZ', b'Q8HKQC3VMRM1M6M7ES',
]))
def test_hassoundexname(self):
"""
Test HasSoundexName rule.
"""
rule = HasSoundexName(['garner'])
self.assertEqual(len(self.filter_with_rule(rule)), 73)
def test_hasnameof(self):
"""
Test HasNameOf rule.
"""
rule = HasNameOf(['Lewis', 'Garner', 'Dr.', 'Sr', 'Anderson',
'Big Louie', 'von', 'Zieliński', None, None, None])
self.assertEqual(self.filter_with_rule(rule), set([
b'GNUJQCL9MD64AM56OH']))
if __name__ == "__main__":
unittest.main()

View File

@ -39,7 +39,7 @@ import os
import sys
import re
import logging
LOG = logging.getLogger('.' + __name__)
LOG = logging.getLogger('._manager')
LOG.progagate = True
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
@ -100,8 +100,8 @@ class BasePluginManager:
self.__modules = {}
self.__pgr = PluginRegister.get_instance()
self.__registereddir_set = set()
self.__loaded_plugins = {}
self.__scanned_dirs = []
def reg_plugins(self, direct, dbstate=None, uistate=None,
load_on_reg=False):
@ -112,23 +112,24 @@ class BasePluginManager:
If a relationship calculator for env var LANG is present, it is
immediately loaded so it is available for all.
"""
# if the directory does not exist, do nothing
if not os.path.isdir(direct):
return False # return value is True for error
# if we've already scanned this directory or if the directory does not
# exist, we are done. Should only happen in tests.
for (dirpath, dirnames, filenames) in os.walk(direct):
root, subdir = os.path.split(dirpath)
if subdir.startswith("."):
dirnames[:] = []
continue
for dirname in dirnames:
# Skip hidden and system directories:
if dirname.startswith(".") or dirname in ["po", "locale"]:
dirnames.remove(dirname)
# if the path has not already been loaded, save it in the
# registereddir_list list for use on reloading.
self.__registereddir_set.add(dirpath)
self.__pgr.scan_dir(dirpath, uistate=uistate)
# LOG.warning("\nPlugin manager registration: %s, load_on_reg=%s,"
# " been_here=%s, pahte exists:%s", direct, load_on_reg,
# direct in self.__scanned_dirs, os.path.isdir(direct))
if os.path.isdir(direct) and direct not in self.__scanned_dirs:
self.__scanned_dirs.append(direct)
for (dirpath, dirnames, filenames) in os.walk(direct,
topdown=True):
for dirname in dirnames[:]:
# Skip hidden and system directories:
if dirname.startswith(".") or dirname in ["po", "locale",
"__pycache__"]:
dirnames.remove(dirname)
# LOG.warning("Plugin dir scanned: %s", dirpath)
self.__pgr.scan_dir(dirpath, filenames, uistate=uistate)
if load_on_reg:
# Run plugins that request to be loaded on startup and
@ -136,6 +137,7 @@ class BasePluginManager:
# first, remove hidden
plugins_to_load = []
for plugin in self.__pgr.filter_load_on_reg():
# LOG.warning("\nFound %s at registration", plugin.id)
if plugin.id in config.get("plugin.hiddenplugins"):
continue
plugins_to_load.append(plugin)
@ -146,6 +148,8 @@ class BasePluginManager:
max_count = len(plugins_to_load)
while plugins_to_load:
for plugin in plugins_to_load[:]: # copy of list
# LOG.warning("\nDependencies for %s at registration",
# plugin.id)
delay = False
for depend in plugin.depends_on:
if depend not in [p.id for p in plugins_sorted]:
@ -167,8 +171,12 @@ class BasePluginManager:
break
# now load them:
for plugin in plugins_sorted:
# next line shouldn't be necessary, but this gets called a lot
# of times during Travis test; so avoid multiple copies
plugin.data = []
mod = self.load_plugin(plugin)
if hasattr(mod, "load_on_reg"):
# LOG.warning("\nRun %s at registration", plugin.id)
try:
results = mod.load_on_reg(dbstate, uistate, plugin)
except:
@ -496,6 +504,8 @@ class BasePluginManager:
retval.extend(data)
except:
retval.append(data)
# LOG.warning("Process plugin data=%s, %s, items=%s",
# process is not None, category, len(retval))
if process:
return process(retval)
return retval

View File

@ -43,6 +43,8 @@ from gramps.version import VERSION as GRAMPSVERSION, VERSION_TUPLE
from ..const import IMAGE_DIR
from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
import logging
LOG = logging.getLogger('._manager')
#-------------------------------------------------------------------------
#
@ -1104,11 +1106,16 @@ class PluginRegister:
if __debug__:
self.stable_only = False
self.__plugindata = []
self.__id_to_pdata = {}
def add_plugindata(self, plugindata):
""" This is used to add an entry to the registration list. The way it
is used, this entry is not yet filled in, so we cannot use the id to
add to the __id_to_pdata dict at this time. """
self.__plugindata.append(plugindata)
def scan_dir(self, dir, uistate=None):
def scan_dir(self, dir, filenames, uistate=None):
"""
The dir name will be scanned for plugin registration code, which will
be loaded in :class:`PluginData` objects if they satisfy some checks.
@ -1123,9 +1130,8 @@ class PluginRegister:
extlen = -len(ext)
pymod = re.compile(r"^(.*)\.py$")
for filename in os.listdir(dir):
name = os.path.split(filename)[1]
if not name[extlen:] == ext:
for filename in filenames:
if not filename[extlen:] == ext:
continue
lenpd = len(self.__plugindata)
full_filename = os.path.join(dir, filename)
@ -1150,9 +1156,14 @@ class PluginRegister:
else:
local_gettext = glocale.translation.gettext
try:
#execfile(full_filename,
exec (compile(stream, filename, 'exec'),
make_environment(_=local_gettext), {'uistate': uistate})
for pdata in self.__plugindata[lenpd:]:
# should not be duplicate IDs in different plugins
assert pdata.id not in self.__id_to_pdata
# if pdata.id in self.__id_to_pdata:
# print("Error: %s is duplicated!" % pdata.id)
self.__id_to_pdata[pdata.id] = pdata
except ValueError as msg:
print(_('ERROR: Failed reading plugin registration %(filename)s') % \
{'filename' : filename})
@ -1170,6 +1181,7 @@ class PluginRegister:
rmlist = []
ind = lenpd-1
for plugin in self.__plugindata[lenpd:]:
#LOG.warning("\nPlugin scanned %s at registration", plugin.id)
ind += 1
plugin.directory = dir
if not valid_plugin_version(plugin.gramps_target_version):
@ -1211,19 +1223,20 @@ class PluginRegister:
module = match.groups()[0]
plugin.mod_name = module
plugin.fpath = dir
#LOG.warning("\nPlugin added %s at registration", plugin.id)
rmlist.reverse()
for ind in rmlist:
del self.__id_to_pdata[self.__plugindata[ind].id]
del self.__plugindata[ind]
def get_plugin(self, id):
"""
Return the :class:`PluginData` for the plugin with id
"""
matches = [x for x in self.__plugindata if x.id == id]
matches.sort(key=lambda x: version(x.version))
if len(matches) > 0:
return matches[-1]
return None
assert(len(self.__id_to_pdata) == len(self.__plugindata))
# if len(self.__id_to_pdata) != len(self.__plugindata):
# print(len(self.__id_to_pdata), len(self.__plugindata))
return self.__id_to_pdata.get(id, None)
def type_plugins(self, ptype):
"""

View File

@ -36,7 +36,7 @@ from ..docgen import StyleSheetList
# StyleOption class
#
#-------------------------------------------------------------------------
class StyleOption(EnumeratedListOption):
class StyleOption(EnumeratedListOption): # TODO this is likely dead code
"""
This class describes an option that allows the use to select a style sheet.
"""

View File

@ -45,6 +45,7 @@ class Report:
def __init__(self, database, options_class, user):
self.database = database
self.options_class = options_class
self._user = user
self.doc = options_class.get_document()

View File

@ -484,7 +484,8 @@ class DbManager(CLIDbManager, ManagedWindow):
else:
del self.selection
del self.name_renderer
self.close()
if value != Gtk.ResponseType.DELETE_EVENT:
self.close()
return None
def __ask_to_break_lock(self, store, node):

View File

@ -307,7 +307,8 @@ class EditName(EditSecondary):
def build_menu_names(self, name):
if name:
ntext = name_displayer.display_name(name)
submenu_label = '%s: %s' % (_('Name'), ntext)
submenu_label = _('%(str1)s: %(str2)s') % {'str1' : _('Name'),
'str2' : ntext}
else:
submenu_label = _('New Name')
menu_label = _('Name Editor')

View File

@ -174,6 +174,26 @@ class EditPlace(EditPrimary):
#force validation now with initial entry
self.top.get_object("lat_entry").validate(force=True)
self.latlon = MonitoredEntry(
self.top.get_object("latlon_entry"),
self.set_latlongitude, self.get_latlongitude,
self.db.readonly)
def set_latlongitude(self, value):
try:
coma = value.index(',')
self.longitude.set_text(value[coma+1:])
self.latitude.set_text(value[:coma])
self.top.get_object("lat_entry").validate(force=True)
self.top.get_object("lon_entry").validate(force=True)
self.obj.set_latitude(self.latitude.get_value())
self.obj.set_longitude(self.longitude.get_value())
except:
pass
def get_latlongitude(self):
return ""
def _validate_coordinate(self, widget, text, typedeg):
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
return ValidationError(_("Invalid latitude (syntax: 18\u00b09'") +
@ -279,7 +299,6 @@ class EditPlace(EditPrimary):
def save(self, *obj):
self.ok_button.set_sensitive(False)
if self.obj.get_name().get_value().strip() == '':
msg1 = _("Cannot save place. Name not entered.")
msg2 = _("You must enter a name before saving.")

View File

@ -167,6 +167,26 @@ class EditPlaceRef(EditReference):
#force validation now with initial entry
self.top.get_object("lat_entry").validate(force=True)
self.latlon = MonitoredEntry(
self.top.get_object("latlon_entry"),
self.set_latlongitude, self.get_latlongitude,
self.db.readonly)
def set_latlongitude(self, value):
try:
coma = value.index(',')
self.longitude.set_text(value[coma+1:])
self.latitude.set_text(value[:coma])
self.top.get_object("lat_entry").validate(force=True)
self.top.get_object("lon_entry").validate(force=True)
self.obj.set_latitude(self.latitude.get_value())
self.obj.set_longitude(self.longitude.get_value())
except:
pass
def get_latlongitude(self):
return ""
def _validate_coordinate(self, widget, text, typedeg):
if (typedeg == 'lat') and not conv_lat_lon(text, "0", "ISO-D"):
return ValidationError(_("Invalid latitude (syntax: 18\u00b09'") +

View File

@ -97,11 +97,25 @@
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="comment1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Either use the two fields below to enter coordinates(latitude and longitude),</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label249">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="halign">center</property>
<property name="label" translatable="yes">L_atitude:</property>
<property name="use_underline">True</property>
<property name="justify">center</property>
@ -109,7 +123,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -124,7 +138,7 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -152,7 +166,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -167,7 +181,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -182,7 +196,59 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkBox" id="copypaste">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="comment2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">or use copy/paste from your favorite map provider (format : latitude,longitude) in the following field:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="width">4</property>
</packing>
</child>
<child>
<object class="GtkBox" id="paste_field">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="ValidatableMaskedEntry" id="latlon_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Field used to paste info from a web page like google, openstreetmap, ... </property>
<property name="hexpand">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
<property name="width">4</property>
</packing>
</child>
<child>
@ -236,7 +302,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -266,7 +332,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">3</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
@ -277,7 +343,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -332,7 +398,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -344,7 +410,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>

View File

@ -220,6 +220,20 @@
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="comment1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Either use the two fields below to enter coordinates(latitude and longitude),</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label504">
<property name="visible">True</property>
@ -233,7 +247,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -246,7 +260,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -291,7 +305,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="top_attach">8</property>
<property name="width">5</property>
</packing>
</child>
@ -320,7 +334,59 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkBox" id="copypaste">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="comment2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">or use copy/paste from your favorite map provider (format : latitude,longitude) in the following field:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="width">4</property>
</packing>
</child>
<child>
<object class="GtkBox" id="paste_field">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="ValidatableMaskedEntry" id="latlon_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Field used to paste info from a web page like google, openstreetmap, ... </property>
<property name="hexpand">True</property>
<property name="invisible_char">●</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
<property name="width">4</property>
</packing>
</child>
<child>
@ -369,7 +435,7 @@
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -398,7 +464,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -413,7 +479,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">3</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
@ -467,7 +533,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -479,7 +545,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -491,7 +557,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">3</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>
@ -502,7 +568,7 @@ You can set these values via the Geography View by searching the place, or via a
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">4</property>
<property name="top_attach">7</property>
</packing>
</child>
<child>

View File

@ -90,7 +90,7 @@
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="destroy_passed_object" object="editor" swapped="yes"/>
<signal name="clicked" handler="on_cancel_style_clicked" object="editor" swapped="yes"/>
</object>
<packing>
<property name="expand">False</property>
@ -1705,8 +1705,6 @@
</object>
<object class="GtkDialog" id="styles">
<property name="can_focus">False</property>
<property name="default_width">400</property>
<property name="default_height">300</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
@ -1727,6 +1725,7 @@
<property name="can_default">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_cancel_clicked" object="styles" swapped="yes"/>
</object>
<packing>
<property name="expand">False</property>

View File

@ -488,7 +488,9 @@ class ManagedWindow:
self.window.set_modal(True)
# The following makes sure that we only have one modal window open;
# if more the older ones get temporarily made non-modal.
self.other_modal_window = self.uistate.gwm.find_modal_window(window)
if self.uistate:
self.other_modal_window = self.uistate.gwm.find_modal_window(
window)
if self.other_modal_window:
self.other_modal_window.set_modal(False)
self.window.set_modal(True)
@ -623,7 +625,8 @@ class ManagedWindow:
def setup_configs(self, config_base,
default_width, default_height,
default_horiz_position=None, default_vert_position=None):
default_horiz_position=None, default_vert_position=None,
p_width=None, p_height=None): # for fullscreen
"""
Helper method to setup the window's configuration settings
@ -634,13 +637,18 @@ class ManagedWindow:
@param default_horiz_position, default_vert_position: if either is None
then that position is centered on the parent, else explicitly set
@type default_horiz_position, default_vert_position: int or None
@param p_width, p_height: the parent's width and height
@type p_width, p_height: int or None
"""
self.width_key = config_base + '-width'
self.height_key = config_base + '-height'
self.horiz_position_key = config_base + '-horiz-position'
self.vert_position_key = config_base + '-vert-position'
(p_width, p_height) = self.parent_window.get_size()
(p_horiz, p_vert) = self.parent_window.get_position()
if p_width is None and p_height is None: # default case
(p_width, p_height) = self.parent_window.get_size()
(p_horiz, p_vert) = self.parent_window.get_position()
else:
p_horiz = p_vert = 0 # fullscreen
if default_horiz_position is None:
default_horiz_position = p_horiz + ((p_width - default_width) // 2)
if default_vert_position is None:

View File

@ -1790,7 +1790,7 @@ class GuiDestinationOption(Gtk.Box):
# GuiStyleOption class
#
#-------------------------------------------------------------------------
class GuiStyleOption(GuiEnumeratedListOption):
class GuiStyleOption(GuiEnumeratedListOption): # TODO this is likely dead code
"""
This class displays a StyleOption.
"""
@ -1808,6 +1808,8 @@ class GuiStyleOption(GuiEnumeratedListOption):
self.__button.connect('clicked', self.__on_style_edit_clicked)
self.pack_end(self.__button, False, False)
self.uistate = uistate
self.track = track
def __on_style_edit_clicked(self, *obj):
"""The user has clicked on the 'Edit Styles' button. Create a
@ -1817,7 +1819,7 @@ class GuiStyleOption(GuiEnumeratedListOption):
from .report._styleeditor import StyleListDisplay
style_list = StyleSheetList(self.__option.get_style_file(),
self.__option.get_default_style())
StyleListDisplay(style_list, None, None)
StyleListDisplay(style_list, self.uistate, self.track)
new_items = []
for style_name in style_list.get_style_names():

View File

@ -1111,9 +1111,9 @@ class UpdateAddons(ManagedWindow):
last_category = None
for (status,plugin_url,plugin_dict) in addon_update_list:
count = get_count(addon_update_list, plugin_dict["t"])
category = _("%(adjective)s: %(addon)s") % {
"adjective": status,
"addon": _(plugin_dict["t"])}
# translators: needed for French, ignore otherwise
category = _("%(str1)s: %(str2)s") % {'str1' : status,
'str2' : _(plugin_dict["t"])}
if last_category != category:
last_category = category
node = self.list.add([False, # initially selected?

View File

@ -58,7 +58,7 @@ class DisplayBuf(ManagedWindow):
ManagedWindow.__init__(self, document.uistate, track, document)
dialog = Gtk.Dialog(title="", destroy_with_parent=True)
dialog.add_button(_('_Close'), Gtk.ResponseType.CLOSE)
self.set_window(dialog, None, title, True)
self.set_window(dialog, None, title)
self.setup_configs('interface.' + title.lower().replace(' ', ''),
600, 400)
scrolled_window = Gtk.ScrolledWindow()

View File

@ -588,8 +588,8 @@ class ReportDialog(ManagedWindow):
style sheet editor object and let them play. When they are
done, the previous routine will be called to update the dialog
menu for selecting a style."""
StyleListDisplay(self.style_sheet_list, self.build_style_menu,
self.window)
StyleListDisplay(self.style_sheet_list, self.uistate, self.track,
callback=self.build_style_menu)
#----------------------------------------------------------------------
#

View File

@ -55,63 +55,73 @@ from gramps.gen.plug.docgen import (StyleSheet, FONT_SERIF, FONT_SANS_SERIF,
PARA_ALIGN_JUSTIFY, ParagraphStyle, TableStyle, TableCellStyle,
GraphicsStyle)
from ...listmodel import ListModel
from ...managedwindow import set_titles
from ...managedwindow import ManagedWindow
from ...glade import Glade
from ...dialog import ErrorDialog
#------------------------------------------------------------------------
#
# StyleListDisplay class
#
#------------------------------------------------------------------------
class StyleListDisplay:
class StyleListDisplay(ManagedWindow):
"""
Shows the available paragraph/font styles. Allows the user to select,
add, edit, and delete styles from a StyleSheet.
add, edit, and delete styles from a StyleSheetList.
"""
def __init__(self, stylesheetlist, callback, parent_window):
def __init__(self, stylesheetlist, uistate, track, callback=None):
"""
Create a StyleListDisplay object that displays the styles in the
StyleSheet.
StyleSheetList.
stylesheetlist - styles that can be editied
callback - task called with an object has been added.
stylesheetlist - styles for editing: a :class:`.StyleSheetList` instance
callback - task called when an object has been added.
"""
ManagedWindow.__init__(self, uistate, track, self.__class__, modal=True)
# the self.window.run() below makes Gtk make it modal, so any change
# to the previous line's "modal" would require that line to be changed
self.callback = callback
self.sheetlist = stylesheetlist
self.parent_window = parent_window
self.top = Glade(toplevel='styles')
self.window = self.top.toplevel
set_titles(self.window, self.top.get_object('title'),
_('Document Styles'))
self.set_window(self.top.toplevel, self.top.get_object('title'),
_('Document Styles'))
self.setup_configs('interface.stylelistdisplay', 400, 300)
self.show()
self.top.connect_signals({
"destroy_passed_object" : self.__close,
"on_ok_clicked" : self.on_ok_clicked,
"on_add_clicked" : self.on_add_clicked,
"on_delete_clicked" : self.on_delete_clicked,
"on_button_press" : self.on_button_press,
"on_edit_clicked" : self.on_edit_clicked,
"on_cancel_clicked" : self.__cancel,
"on_cancel_style_clicked" : dummy_callback,
"on_save_style_clicked" : dummy_callback,
})
self.list = ListModel(self.top.get_object("list"),
[(_('Style'), -1, 10)], )
self.redraw()
if parent_window:
self.window.set_transient_for(parent_window)
# the self.window.run() makes Gtk make it modal, so any change to that
# line would require the ManagedWindow.__init__ to be changed also
self.window.run()
self.window.destroy()
if self.opened:
self.close()
def __close(self, obj):
self.top.destroy()
def build_menu_names(self, obj): # meaningless while it's modal
"""Override :class:`.ManagedWindow` method."""
return (_('Document Styles'), ' ')
def __cancel(self, obj):
pass
def redraw(self):
"""Redraws the list of styles that are current available"""
"""Redraws the list of styles that are currently available"""
self.list.model.clear()
self.list.add([_("default")])
@ -124,22 +134,21 @@ class StyleListDisplay:
index += 1
def on_add_clicked(self, obj):
"""Called with the ADD button is clicked. Invokes the StyleEditor to
"""Called when the ADD button is clicked. Invokes the StyleEditor to
create a new style"""
style = self.sheetlist.get_style_sheet("default")
StyleEditor(_("New Style"), style, self)
def on_ok_clicked(self, obj):
"""Called with the OK button is clicked; Calls the callback task,
"""Called when the OK button is clicked; Calls the callback task,
then saves the stylesheet."""
if self.callback is not None:
self.callback()
try:
self.sheetlist.save()
except IOError as msg:
from ...dialog import ErrorDialog
ErrorDialog(_("Error saving stylesheet"), str(msg),
parent=self.parent_window)
parent=self.window)
except:
log.error("Failed to save stylesheet", exc_info=True)
@ -149,11 +158,13 @@ class StyleListDisplay:
def on_edit_clicked(self, obj):
"""
Called with the EDIT button is clicked.
Called when the EDIT button is clicked.
Calls the StyleEditor to edit the selected style.
"""
store, node = self.list.selection.get_selected()
if not node:
ErrorDialog(_("Missing information"), _("Select a style"),
parent=self.window)
return
name = str(self.list.model.get_value(node, 0))
@ -166,6 +177,8 @@ class StyleListDisplay:
"""Deletes the selected style."""
store, node = self.list.selection.get_selected()
if not node:
ErrorDialog(_("Missing information"), _("Select a style"),
parent=self.window)
return
name = str(self.list.model.get_value(node, 0))
if name == _('default'): # the default style cannot be removed
@ -178,7 +191,7 @@ class StyleListDisplay:
# StyleEditor class
#
#------------------------------------------------------------------------
class StyleEditor:
class StyleEditor(ManagedWindow):
"""
Edits the current style definition. Presents a dialog allowing the values
of the paragraphs in the style to be altered.
@ -189,20 +202,30 @@ class StyleEditor:
Create the StyleEditor.
name - name of the style that is to be edited
style - style object that is to be edited
style - style object to be edited: a :class:`.StyleSheet` instance
parent - StyleListDisplay object that called the editor
"""
ManagedWindow.__init__(self, parent.uistate, parent.track,
self.__class__, modal=True)
# the self.window.run() below makes Gtk make it modal, so any change
# to the previous line's "modal" would require that line to be changed
self.current_style = None
self.current_name = None
self.style = StyleSheet(style)
self.parent = parent
self.top = Glade(toplevel='editor')
self.window = self.top.toplevel
self.set_window(self.top.toplevel, self.top.get_object('title'),
_('Style editor'))
self.setup_configs('interface.styleeditor', 550, 610)
self.show()
self.top.connect_signals({
"on_save_style_clicked" : self.on_save_style_clicked,
"destroy_passed_object" : self.__close,
"on_cancel_style_clicked" : self.__cancel,
"on_cancel_clicked" : dummy_callback,
"on_ok_clicked" : dummy_callback,
"on_add_clicked" : dummy_callback,
"on_delete_clicked" : dummy_callback,
@ -226,8 +249,6 @@ class StyleEditor:
self.line_style.pack_start(renderer_text, True)
self.line_style.add_attribute(renderer_text, "text", 1)
set_titles(self.window, self.top.get_object('title'),
_('Style editor'))
self.top.get_object("label6").set_text(_("point size|pt"))
titles = [(_('Style'), 0, 130)]
@ -261,13 +282,18 @@ class StyleEditor:
self.plist.add([d_name], self.style.get_draw_style(d_name))
self.plist.select_row(0)
if self.parent:
self.window.set_transient_for(parent.window)
# the self.window.run() makes Gtk make it modal, so any change to that
# line would require the ManagedWindow.__init__ to be changed also
self.window.run()
self.window.destroy()
if self.opened:
self.close()
def __close(self, obj):
self.window.destroy()
def build_menu_names(self, obj): # meaningless while it's modal
"""Override :class:`.ManagedWindow` method."""
return (_('Style editor'), None)
def __cancel(self, obj):
pass
def show_pages(self, show_pages):
"""
@ -525,7 +551,6 @@ class StyleEditor:
self.style.set_name(name)
self.parent.sheetlist.set_style_sheet(name, self.style)
self.parent.redraw()
self.window.destroy()
def change_display(self, obj):
"""

View File

@ -587,7 +587,8 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel, BaseModel):
self.__total += items
assert not skip
if dfilter:
for handle in dfilter.apply(self.db, user=User()):
for handle in dfilter.apply(self.db,
user=User(parent=self.uistate.window)):
status_ppl.heartbeat()
data = data_map(handle)
add_func(handle, data)

View File

@ -236,8 +236,9 @@ class GrampletWindow(ManagedWindow):
Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_Close'), Gtk.ResponseType.CLOSE)),
None, self.title)
self.window.set_size_request(gramplet.detached_width,
gramplet.detached_height)
cfg_name = gramplet.gname.replace(' ', '').lower() + '-gramplet'
self.setup_configs('interface.' + cfg_name,
gramplet.detached_width, gramplet.detached_height)
self.window.add_button(_('_Help'), Gtk.ResponseType.HELP)
# add gramplet:
if self.gramplet.pui:
@ -1585,20 +1586,6 @@ class GrampletPane(Gtk.ScrolledWindow):
"%s.height" % gramplet.title,
self._config.set,
config=self._config)
# Detached height
configdialog.add_pos_int_entry(grid,
_('Detached width'),
3,
"%s.detached_width" % gramplet.title,
self._config.set,
config=self._config)
# Detached width
configdialog.add_pos_int_entry(grid,
_('Detached height'),
4,
"%s.detached_height" % gramplet.title,
self._config.set,
config=self._config)
# Options:
options = gramplet.make_gui_options()
if options:

View File

@ -144,7 +144,7 @@ class MonitoredEntry:
def force_value(self, value):
self.obj.set_text(value)
def get_value(self, value):
def get_value(self):
return str(self.obj.get_text())
def enable(self, value):

View File

@ -51,7 +51,7 @@ from .undoablebuffer import Stack
class UndoableInsertEntry:
"""something that has been inserted into our Gtk.editable"""
def __init__(self, text, length, position, editable):
def __init__(self, text, length, position):
self.offset = position
self.text = text
#unicode char can have length > 1 as it points in the buffer
@ -80,7 +80,7 @@ class UndoableDeleteEntry:
else:
self.mergeable = True
class UndoableEntry(Gtk.Entry):
class UndoableEntry(Gtk.Entry, Gtk.Editable):
"""
The UndoableEntry is an Entry subclass with additional features.
@ -102,7 +102,6 @@ class UndoableEntry(Gtk.Entry):
self.not_undoable_action = False
self.undo_in_progress = False
self.connect('insert-text', self._on_insert_text)
self.connect('delete-text', self._on_delete_text)
self.connect('key-press-event', self._on_key_press_event)
@ -134,7 +133,7 @@ class UndoableEntry(Gtk.Entry):
def __empty_redo_stack(self):
self.redo_stack = []
def _on_insert_text(self, editable, text, length, positionptr):
def do_insert_text(self, text, length, position):
def can_be_merged(prev, cur):
"""
see if we can merge multiple inserts here
@ -159,26 +158,27 @@ class UndoableEntry(Gtk.Entry):
if not self.undo_in_progress:
self.__empty_redo_stack()
if self.not_undoable_action:
return
undo_action = self.insertclass(text, length, editable.get_position(),
editable)
try:
prev_insert = self.undo_stack.pop()
except IndexError:
self.undo_stack.append(undo_action)
return
if not isinstance(prev_insert, self.insertclass):
self.undo_stack.append(prev_insert)
self.undo_stack.append(undo_action)
return
if can_be_merged(prev_insert, undo_action):
prev_insert.length += undo_action.length
prev_insert.text += undo_action.text
self.undo_stack.append(prev_insert)
else:
self.undo_stack.append(prev_insert)
self.undo_stack.append(undo_action)
while not self.not_undoable_action:
undo_action = self.insertclass(text, length, self.get_position())
try:
prev_insert = self.undo_stack.pop()
except IndexError:
self.undo_stack.append(undo_action)
break
if not isinstance(prev_insert, self.insertclass):
self.undo_stack.append(prev_insert)
self.undo_stack.append(undo_action)
break
if can_be_merged(prev_insert, undo_action):
prev_insert.length += undo_action.length
prev_insert.text += undo_action.text
self.undo_stack.append(prev_insert)
else:
self.undo_stack.append(prev_insert)
self.undo_stack.append(undo_action)
break
self.get_buffer().insert_text(position, text, length)
return position + length
def _on_delete_text(self, editable, start, end):
def can_be_merged(prev, cur):

View File

@ -1,36 +0,0 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2016 Tim G L Lyons
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
from gramps.gen.plug._pluginreg import register, STABLE, DATABASE
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.gettext
register(DATABASE,
id = 'dummydb',
name = _("Dummy database"),
name_accell = _("Dummy Database"),
description = _("Dummy Database"),
version = '1.0.0',
gramps_target_version = "5.0",
status = STABLE,
fname = 'dummydb.py',
databaseclass = 'DummyDb',
authors=['Tim Lyons'],
authors_email=[""],
)

View File

@ -144,6 +144,7 @@ class CalcItems:
"""
def __init__(self, dbase):
_gui = GUIConnect()
self._gui = _gui
#calculate the printed lines for each box
#str = ""
@ -172,12 +173,14 @@ class CalcItems:
working_lines = ""
if index[1] % 2 == 0 or (index[1] == 1 and self.center_use == 0):
if indi_handle == fams_handle == None:
working_lines = self.__blank_father
working_lines = self.__calc_l.calc_lines(
None, None, self._gui.get_val("father_disp"))
else:
working_lines = self.disp_father
else:
if indi_handle == fams_handle == None:
working_lines = self.__blank_mother
working_lines = self.__calc_l.calc_lines(
None, None, self._gui.get_val("mother_disp"))
else:
working_lines = self.disp_mother
@ -230,9 +233,11 @@ class MakeAncestorTree(AscendPerson):
myself.text = self.calc_items.calc_person(index,
indi_handle, fams_handle)
# myself.text[0] = myself.text[0] + ' ' + repr(index) # for debugging
myself.add_mark(self.database,
self.database.get_person_from_handle(indi_handle))
if indi_handle is not None: # None is legal for an empty box
myself.add_mark(self.database,
self.database.get_person_from_handle(indi_handle))
self.canvas.add_box(myself)

View File

@ -401,9 +401,7 @@ class CSVWriter:
birth = self.db.get_event_from_handle(birth_ref.ref)
if birth:
birthdate = self.format_date( birth)
place_handle = birth.get_place_handle()
if place_handle:
birthplace = _pd.display_event(self.db, birth)
birthplace = self.format_place(birth)
birthsource = get_primary_source_title(self.db, birth)
# Baptism:
baptismdate = ""
@ -415,9 +413,7 @@ class CSVWriter:
baptism = self.db.get_event_from_handle(baptism_ref.ref)
if baptism:
baptismdate = self.format_date( baptism)
place_handle = baptism.get_place_handle()
if place_handle:
baptismplace = _pd.display_event(self.db, baptism)
baptismplace = self.format_place(baptism)
baptismsource = get_primary_source_title(self.db, baptism)
# Death:
deathdate = ""
@ -428,9 +424,7 @@ class CSVWriter:
death = self.db.get_event_from_handle(death_ref.ref)
if death:
deathdate = self.format_date( death)
place_handle = death.get_place_handle()
if place_handle:
deathplace = _pd.display_event(self.db, death)
deathplace = self.format_place(death)
deathsource = get_primary_source_title(self.db, death)
# Burial:
burialdate = ""
@ -442,9 +436,7 @@ class CSVWriter:
burial = self.db.get_event_from_handle(burial_ref.ref)
if burial:
burialdate = self.format_date( burial)
place_handle = burial.get_place_handle()
if place_handle:
burialplace = _pd.display_event(self.db, burial)
burialplace = self.format_place(burial)
burialsource = get_primary_source_title(self.db, burial)
# Write it out:
self.write_csv(grampsid_ref, surname, first_name, callname,
@ -502,10 +494,8 @@ class CSVWriter:
event = self.db.get_event_from_handle(event_ref.ref)
if event.get_type() == EventType.MARRIAGE:
mdate = self.format_date( event)
place_handle = event.get_place_handle()
if place_handle:
mplace = _pd.display_event(self.db, event)
source = get_primary_source_title(self.db, event)
mplace = self.format_place(event)
source = get_primary_source_title(self.db, event)
note = ''
self.write_csv(marriage_id, father_id, mother_id, mdate,
mplace, source, note)
@ -537,3 +527,18 @@ class CSVWriter:
def format_date(self, date):
return get_date(date)
def format_place(self, event):
"""
If places are included in the export return a link, else return a
formatted place for the given event.
"""
if self.include_places:
place_handle = event.get_place_handle()
if place_handle:
place = self.db.get_place_from_handle(place_handle)
if place:
return "[%s]" % place.get_gramps_id()
return ""
else:
return _pd.display_event(self.db, event)

View File

@ -489,9 +489,10 @@ class WhatNextGramplet(Gramplet):
missingbits.append(_("place unknown"))
if missingbits:
return [_("%(type)s: %(list)s") % {
'type': event.get_type(),
'list': _(", ").join(missingbits)}]
# translators: needed for French, ignore otherwise
return [_("%(str1)s: %(str2)s"
) % {'str1' : event.get_type(),
'str2' : _(", ").join(missingbits)}]
else:
return []

View File

@ -193,8 +193,14 @@ class RelGraphReport(Report):
self._db.iter_person_handles())
if len(person_handles) > 1:
if self._user:
self._user.begin_progress(_("Relationship Graph"),
_("Generating report"),
len(person_handles) * 2)
self.add_persons_and_families(person_handles)
self.add_child_links_to_families(person_handles)
if self._user:
self._user.end_progress()
def add_child_links_to_families(self, person_handles):
"""
@ -205,6 +211,8 @@ class RelGraphReport(Report):
person_dict = dict([handle, 1] for handle in person_handles)
for person_handle in person_handles:
if self._user:
self._user.step_progress()
person = self._db.get_person_from_handle(person_handle)
p_id = person.get_gramps_id()
for fam_handle in person.get_parent_family_handle_list():
@ -261,6 +269,8 @@ class RelGraphReport(Report):
# so we don't do it twice
families_done = {}
for person_handle in person_handles:
if self._user:
self._user.step_progress()
# determine per person if we use HTML style label
if self.includeimg:
self.use_html_output = True

View File

@ -446,13 +446,13 @@ class AscendPerson(_StopRecurse, _PersonSeen):
# Recursively call the function. It is okay if the handle is None,
# since routine handles a handle of None
self.__fill(index*2, generation+1, mx_fill-1)
self.__fill(generation+1, index*2, mx_fill-1)
if mx_fill > 1: # marriage of parents
self.add_marriage((generation+1, index*2), None, None)
if not self.can_recurse():
self.continue_recursion()
return
self.__fill((index*2)+1, generation+1, mx_fill-1)
self.__fill(generation+1, (index*2)+1, mx_fill-1)
def __iterate(self, generation, index, person_handle, full_family_handle):
"""

View File

@ -12,6 +12,7 @@
# Copyright (C) 2011 Tim G L Lyons
# Copyright (C) 2013-2014 Paul Franklin
# Copyright (C) 2014 Gerald Kunzmann <g.kunzmann@arcor.de>
# Copyright (C) 2017 Robert Carnell <bertcarnell_at_gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -96,6 +97,7 @@ class DetAncestorReport(Report):
firstName - Whether to use first names instead of pronouns.
fulldate - Whether to use full dates instead of just year.
listchildren - Whether to list children.
list_children_spouses - Whether to list the spouses of the children
includenotes - Whether to include notes.
incattrs - Whether to include attributes
blankplace - Whether to replace missing Places with ___________.
@ -136,6 +138,7 @@ class DetAncestorReport(Report):
self.fulldate = get_value('fulldates')
use_fulldate = self.fulldate
self.listchildren = get_value('listc')
self.list_children_spouses = get_value('listc_spouses')
self.includenotes = get_value('incnotes')
use_call = get_value('usecall')
blankplace = get_value('repplace')
@ -362,10 +365,10 @@ class DetAncestorReport(Report):
self.doc.start_paragraph('DAR-MoreDetails')
atype = self._get_type(alt_name.get_type())
self.doc.write_text_citation(
self._('%(name_kind)s: %(name)s%(endnotes)s'
) % {'name_kind' : self._(atype),
'name' : alt_name.get_regular_name(),
'endnotes' : self.endnotes(alt_name)})
self._('%(type)s: %(value)s%(endnotes)s'
) % {'type' : self._(atype),
'value' : alt_name.get_regular_name(),
'endnotes' : self.endnotes(alt_name)})
self.doc.end_paragraph()
if self.inc_events:
@ -556,7 +559,10 @@ class DetAncestorReport(Report):
is_first = False
def write_children(self, family):
""" List children.
"""
List children.
:param family: Family
:return:
"""
if not family.get_child_ref_list():
@ -614,6 +620,25 @@ class DetAncestorReport(Report):
self.doc.write_text_citation(
self.__narrator.get_died_string() or
self.__narrator.get_buried_string())
# if the list_children_spouses option is selected:
if self.list_children_spouses:
# get the family of the child that contains the spouse
# of the child. There may be more than one spouse for each
# child
family_handle_list = child.get_family_handle_list()
# for the first spouse, this is true.
# For subsequent spouses, make it false
is_first_family = True
for family_handle in family_handle_list:
child_family = self.database.get_family_from_handle(
family_handle
)
self.doc.write_text_citation(
self.__narrator.get_married_string(
child_family, is_first_family, self._name_display
)
)
is_first_family = False
self.doc.end_paragraph()
def write_family_events(self, family):
@ -692,7 +717,7 @@ class DetAncestorReport(Report):
if self.addimages and len(plist) > 0:
photo = plist[0]
utils.insert_image(self._db, self.doc,
photo, self._user)
photo, self._user)
name = self._nd.display(ind)
if not name:
@ -773,6 +798,9 @@ class DetAncestorOptions(MenuReportOptions):
return _nd.display(person)
def add_menu_options(self, menu):
"""
Add Menu Options
"""
from functools import partial
# Report Options
@ -818,6 +846,11 @@ class DetAncestorOptions(MenuReportOptions):
listc.set_help(_("Whether to list children."))
addopt("listc", listc)
listc_spouses = BooleanOption(_("List Spouses of Children"), False)
listc_spouses.set_help(
_("Whether to list the spouses of the children."))
addopt("listc_spouses", listc_spouses)
computeage = BooleanOption(_("Compute death age"), True)
computeage.set_help(_("Whether to compute a person's age at death."))
addopt("computeage", computeage)

View File

@ -15,6 +15,7 @@
# Copyright (C) 2012 lcc <lcc@6zap.com>
# Copyright (C) 2013-2014 Paul Franklin
# Copyright (C) 2015 Craig J. Anderson
# Copyright (C) 2017 Robert Carnell <bertcarnell_at_gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -98,6 +99,7 @@ class DetDescendantReport(Report):
pageben - Whether to include page break before End Notes.
fulldates - Whether to use full dates instead of just year.
listc - Whether to list children.
list_children_spouses - Whether to list the spouses of the children
incnotes - Whether to include notes.
usecall - Whether to use the call name as the first name.
repplace - Whether to replace missing Places with ___________.
@ -151,6 +153,7 @@ class DetDescendantReport(Report):
self.fulldate = get_value('fulldates')
use_fulldate = self.fulldate
self.listchildren = get_value('listc')
self.list_children_spouses = get_value('listc_spouses')
self.inc_notes = get_value('incnotes')
use_call = get_value('usecall')
blankplace = get_value('repplace')
@ -665,6 +668,8 @@ class DetDescendantReport(Report):
def __write_children(self, family):
"""
List the children for the given family.
:param family: Family
:return:
"""
if not family.get_child_ref_list():
return
@ -724,6 +729,25 @@ class DetDescendantReport(Report):
self.doc.write_text_citation(
self.__narrator.get_died_string() or
self.__narrator.get_buried_string())
# if the list_children_spouses option is selected:
if self.list_children_spouses:
# get the family of the child that contains the spouse
# of the child. There may be more than one spouse for each
# child
family_handle_list = child.get_family_handle_list()
# for the first spouse, this is true.
# For subsequent spouses, make it false
is_first_family = True
for family_handle in family_handle_list:
child_family = self.database.get_family_from_handle(
family_handle
)
self.doc.write_text_citation(
self.__narrator.get_married_string(
child_family, is_first_family, self._name_display
)
)
is_first_family = False
self.doc.end_paragraph()
def __write_family_notes(self, family):
@ -871,10 +895,10 @@ class DetDescendantReport(Report):
atype = self._get_type(alt_name.get_type())
aname = alt_name.get_regular_name()
self.doc.write_text_citation(
self._('%(name_kind)s: %(name)s%(endnotes)s'
) % {'name_kind' : self._(atype),
'name' : aname,
'endnotes' : self.endnotes(alt_name)})
self._('%(type)s: %(value)s%(endnotes)s'
) % {'type' : self._(atype),
'value' : aname,
'endnotes' : self.endnotes(alt_name)})
self.doc.end_paragraph()
if self.inc_events:
@ -1029,6 +1053,11 @@ class DetDescendantOptions(MenuReportOptions):
listc.set_help(_("Whether to list children."))
add_option("listc", listc)
listc_spouses = BooleanOption(_("List Spouses of Children"), False)
listc_spouses.set_help(
_("Whether to list the spouses of the children."))
add_option("listc_spouses", listc_spouses)
computeage = BooleanOption(_("Compute death age"), True)
computeage.set_help(_("Whether to compute a person's age at death."))
add_option("computeage", computeage)

View File

@ -812,12 +812,21 @@ class IndivCompleteReport(Report):
raise ReportError(_('Empty report'),
_('You did not specify anybody'))
if self._user:
self._user.begin_progress(_("Complete Individual Report"),
_("Generating report"),
len(ind_list))
for count, person_handle in enumerate(ind_list):
if self._user:
self._user.step_progress()
self.person = self._db.get_person_from_handle(person_handle)
if self.person is None:
continue
self.family_notes_list = []
self.write_person(count)
if self._user:
self._user.end_progress()
def write_person(self, count):
""" write a person """

View File

@ -98,7 +98,13 @@ class NoteLinkReport(Report):
self.doc.end_row()
if self._user:
self._user.begin_progress(_("Note Link Check Report"),
_("Generating report"),
self.database.get_number_of_notes())
for note in self.database.iter_notes():
if self._user:
self._user.step_progress()
for (ldomain, ltype, lprop, lvalue) in note.get_links():
if ldomain == "gramps":
tagtype = _(ltype)
@ -141,6 +147,8 @@ class NoteLinkReport(Report):
self.doc.end_cell()
self.doc.end_row()
if self._user:
self._user.end_progress()
self.doc.end_table()

View File

@ -3,10 +3,8 @@
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkDialog" id="patchnames">
<property name="visible">True</property>
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="default_width">500</property>
<property name="default_height">450</property>
<property name="type_hint">dialog</property>
<signal name="delete-event" handler="on_delete_event" swapped="no"/>
<child internal-child="vbox">

View File

@ -48,11 +48,11 @@ from gramps.gui.plug import tool
from gramps.gui.dialog import OkDialog
from gramps.gui.managedwindow import ManagedWindow
from gramps.gui.display import display_help
from gramps.gui.glade import Glade
from gramps.gen.lib import NameOriginType, Surname
from gramps.gen.db import DbTxn
from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = glocale.translation.sgettext
from gramps.gui.glade import Glade
#-------------------------------------------------------------------------
#
@ -74,8 +74,7 @@ PREFIX_LIST = [
"de", "van", "von", "di", "le", "du", "dela", "della",
"des", "vande", "ten", "da", "af", "den", "das", "dello",
"del", "en", "ein", "el" "et", "les", "lo", "los", "un",
"um", "una", "uno", "der", "ter", "te", "die",
]
"um", "una", "uno", "der", "ter", "te", "die"]
CONNECTOR_LIST = ['e', 'y', ]
CONNECTOR_LIST_NONSPLIT = ['de', 'van']
@ -109,13 +108,14 @@ class PatchNames(tool.BatchTool, ManagedWindow):
tool.BatchTool.__init__(self, dbstate, user, options_class, name)
if self.fail:
self.close()
return
winprefix = Gtk.Dialog(_("Default prefix and connector settings"),
self.uistate.window,
Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_OK'), Gtk.ResponseType.ACCEPT))
winprefix = Gtk.Dialog(
title=_("Default prefix and connector settings"),
transient_for=self.uistate.window, modal=True,
destroy_with_parent=True)
winprefix.add_button(_('_OK'), Gtk.ResponseType.ACCEPT)
winprefix.vbox.set_spacing(5)
hboxpref = Gtk.Box()
label = Gtk.Label(label=_('Prefixes to search for:'))
@ -138,8 +138,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.connsbox.set_text(', '.join(CONNECTOR_LIST_NONSPLIT))
hboxconns.pack_start(self.connsbox, True, True, 0)
winprefix.vbox.pack_start(hboxconns, True, True, 0)
winprefix.show_all()
winprefix.resize(700, 100)
winprefix.show_all()
response = winprefix.run()
self.prefix_list = self.prefixbox.get_text().split(',')
@ -149,19 +149,21 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.connector_list = list(map(strip, self.connector_list))
self.conbox = None
self.connector_list_nonsplit = self.connsbox.get_text().split(',')
self.connector_list_nonsplit = list(map(strip, self.connector_list_nonsplit))
self.connector_list_nonsplit = list(
map(strip, self.connector_list_nonsplit))
self.connsbox = None
# Find a prefix in the first_name
self._fn_prefix_re = re.compile("(\S+)\s+(%s)\s*$" % '|'.join(self.prefix_list),
re.IGNORECASE)
self._fn_prefix_re = re.compile(
r"(\S+)\s+(%s)\s*$" % '|'.join(self.prefix_list), re.IGNORECASE)
# Find a prefix in the surname
self._sn_prefix_re = re.compile("^\s*(%s)\s+(.+)" % '|'.join(self.prefix_list),
re.IGNORECASE)
self._sn_prefix_re = re.compile(
r"^\s*(%s)\s+(.+)" % '|'.join(self.prefix_list), re.IGNORECASE)
# Find a connector in the surname
self._sn_con_re = re.compile("^\s*(.+)\s+(%s)\s+(.+)" % '|'.join(self.connector_list),
re.IGNORECASE)
self._sn_con_re = re.compile(
r"^\s*(.+)\s+(%s)\s+(.+)" % '|'.join(self.connector_list),
re.IGNORECASE)
winprefix.destroy()
self.cb = callback
@ -206,7 +208,7 @@ class PatchNames(tool.BatchTool, ManagedWindow):
matchnick = _nick_re.match(first)
if new_title:
titleval = (" ".join(old_title+new_title), first)
titleval = (" ".join(old_title + new_title), first)
if key in self.handle_to_action:
self.handle_to_action[key][self.titleid] = titleval
else:
@ -250,8 +252,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
for ind in range(len(prefixes)):
origs.append(NameOriginType())
origs[0] = old_orig[0]
compoundval = (surnames, prefixes, ['']*len(prefixes),
primaries, origs)
compoundval = (surnames, prefixes, [''] * len(prefixes),
primaries, origs)
if key in self.handle_to_action:
self.handle_to_action[key][self.compid] = compoundval
else:
@ -268,8 +270,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
new_orig_list = []
ind = 0
cont = True
for pref, surn, con, prim, orig in zip(old_prefix, old_surn,
old_con, old_prim, old_orig):
for pref, surn, con, prim, orig in zip(
old_prefix, old_surn, old_con, old_prim, old_orig):
surnval = surn.split()
if surnval == []:
new_prefix_list.append(pref)
@ -307,7 +309,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
val = ''
cont = False
#if value after surname indicates continue, then continue
while cont and (val.lower() in self.connector_list_nonsplit):
while cont and (
val.lower() in self.connector_list_nonsplit):
#add this val to the current surname
new_surname_list[-1] += ' ' + val
try:
@ -315,10 +318,10 @@ class PatchNames(tool.BatchTool, ManagedWindow):
except IndexError:
val = ''
cont = False
# if previous is non-splitting connector, then add new val to
# current surname
# if previous is non-splitting connector, then add new val
# to current surname
if cont and (new_surname_list[-1].split()[-1].lower()
in self.connector_list_nonsplit):
in self.connector_list_nonsplit):
new_surname_list[-1] += ' ' + val
try:
val = surnval.pop(0)
@ -337,18 +340,19 @@ class PatchNames(tool.BatchTool, ManagedWindow):
except IndexError:
val = ''
cont = False
#initialize for a next surname in case there are still
#val
# initialize for a next surname in case there are still
# val
if cont:
found = True # we split surname
pref=''
pref = ''
con = ''
prim = False
orig = NameOriginType()
ind += 1
if found:
compoundval = (new_surname_list, new_prefix_list,
new_connector_list, new_prim_list, new_orig_list)
new_connector_list, new_prim_list,
new_orig_list)
if key in self.handle_to_action:
self.handle_to_action[key][self.compid] = compoundval
else:
@ -379,14 +383,14 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.top = Glade()
window = self.top.toplevel
self.top.connect_signals({
"destroy_passed_object" : self.close,
"on_ok_clicked" : self.on_ok_clicked,
"on_help_clicked" : self.on_help_clicked,
"on_delete_event" : self.close,
})
"destroy_passed_object": self.close,
"on_ok_clicked": self.on_ok_clicked,
"on_help_clicked": self.on_help_clicked,
"on_delete_event": self.close})
self.list = self.top.get_object("list")
self.set_window(window, self.top.get_object('title'), self.label)
self.setup_configs("interface.patchnames", 680, 400)
self.model = Gtk.ListStore(GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
GObject.TYPE_STRING, GObject.TYPE_STRING,
@ -406,7 +410,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
c = Gtk.TreeViewColumn(_('Value'), Gtk.CellRendererText(), text=3)
self.list.append_column(c)
c = Gtk.TreeViewColumn(_('Current Name'), Gtk.CellRendererText(), text=4)
c = Gtk.TreeViewColumn(_('Current Name'), Gtk.CellRendererText(),
text=4)
self.list.append_column(c)
self.list.set_model(self.model)
@ -429,7 +434,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.model.set_value(handle, 1, gid)
self.model.set_value(handle, 2, _('Nickname'))
self.model.set_value(handle, 3, nick)
self.model.set_value(handle, 4, p.get_primary_name().get_name())
self.model.set_value(handle, 4,
p.get_primary_name().get_name())
self.nick_hash[key] = handle
if self.titleid in data:
@ -439,7 +445,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.model.set_value(handle, 1, gid)
self.model.set_value(handle, 2, _('Person|Title'))
self.model.set_value(handle, 3, title)
self.model.set_value(handle, 4, p.get_primary_name().get_name())
self.model.set_value(
handle, 4, p.get_primary_name().get_name())
self.title_hash[key] = handle
if self.pref1id in data:
@ -449,11 +456,13 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.model.set_value(handle, 1, gid)
self.model.set_value(handle, 2, _('Prefix in given name'))
self.model.set_value(handle, 3, prefixtotal)
self.model.set_value(handle, 4, p.get_primary_name().get_name())
self.model.set_value(
handle, 4, p.get_primary_name().get_name())
self.prefix1_hash[key] = handle
if self.compid in data:
surn_list, pref_list, con_list, prims, origs = data[self.compid]
surn_list, pref_list, con_list, prims, origs =\
data[self.compid]
handle = self.model.append()
self.model.set_value(handle, 0, 1)
self.model.set_value(handle, 1, gid)
@ -463,14 +472,15 @@ class PatchNames(tool.BatchTool, ManagedWindow):
if newval:
newval += '-['
else:
newval = '['
newval = '['
newval += pre + ',' + sur
if con:
newval += ',' + con + ']'
else:
newval += ']'
self.model.set_value(handle, 3, newval)
self.model.set_value(handle, 4, p.get_primary_name().get_name())
self.model.set_value(handle, 4,
p.get_primary_name().get_name())
self.compound_hash[key] = handle
self.progress.step()
@ -518,7 +528,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
if oldpref == '' or oldpref == prefix.strip():
name.get_surname_list()[0].set_prefix(prefix)
else:
name.get_surname_list()[0].set_prefix('%s %s' % (prefix, oldpref))
name.get_surname_list()[0].set_prefix(
'%s %s' % (prefix, oldpref))
if self.compid in data:
modelhandle = self.compound_hash[key]
@ -527,8 +538,8 @@ class PatchNames(tool.BatchTool, ManagedWindow):
surns, prefs, cons, prims, origs = data[self.compid]
name = p.get_primary_name()
new_surn_list = []
for surn, pref, con, prim, orig in zip(surns, prefs, cons,
prims, origs):
for surn, pref, con, prim, orig in zip(
surns, prefs, cons, prims, origs):
new_surn_list.append(Surname())
new_surn_list[-1].set_surname(surn.strip())
new_surn_list[-1].set_prefix(pref.strip())
@ -544,6 +555,7 @@ class PatchNames(tool.BatchTool, ManagedWindow):
self.close()
self.cb()
class PatchNamesOptions(tool.ToolOptions):
"""
Defines options and provides handling interface.
@ -552,6 +564,6 @@ class PatchNamesOptions(tool.ToolOptions):
def __init__(self, name, person_id=None):
tool.ToolOptions.__init__(self, name, person_id)
def strip(arg):
return arg.strip()

View File

@ -150,6 +150,9 @@ SORT_KEY = glocale.sort_key
#------------------------------------------------
# constants
#------------------------------------------------
HTTP = "http://"
HTTPS = "https://"
GOOGLE_MAPS = 'https://maps.googleapis.com/maps/'
# javascript code for marker path
MARKER_PATH = """
@ -534,6 +537,10 @@ class BasePage:
lang = report.options['trans']
self.rlocale = report.set_locale(lang)
self._ = self.rlocale.translation.sgettext
if report.options['securesite']:
self.secure_mode = HTTPS
else:
self.secure_mode = HTTP
# Functions used when no Web Page plugin is provided
def add_instance(self, *param):
@ -1053,9 +1060,9 @@ class BasePage:
attrlist.extend(event_ref.get_attribute_list())
for attr in attrlist:
htmllist.extend(Html("p",
_("%(type)s: %(value)s") % {
'type' : Html("b", attr.get_type()),
'value' : attr.get_value()
_("%(str1)s: %(str2)s") % {
'str1' : Html("b", attr.get_type()),
'str2' : attr.get_value()
}))
#also output notes attached to the attributes
@ -2481,7 +2488,8 @@ class BasePage:
elif _type == UrlType.WEB_HOME:
if not (uri.startswith("http://") or
uri.startswith("https://")):
uri = "http://%(website)s" % {"website" : uri}
url = self.secure_mode
uri = url + "%(website)s" % {"website" : uri}
# FTP server address
elif _type == UrlType.WEB_FTP:
@ -2590,7 +2598,11 @@ class BasePage:
[self._("Page"), sref.page],
[self._("Confidence"), conf]]:
if data:
tmp += Html("li", "%s: %s" % (label, data))
tmp += Html("li",
_("%(str1)s: %(str2)s") % {
'str1' : label,
'str2' : data
})
if self.create_media:
for media_ref in sref.get_media_list():
media_handle = media_ref.get_reference_handle()
@ -2635,12 +2647,12 @@ class BasePage:
for handle in sref.get_note_list():
this_note = self.r_db.get_note_from_handle(handle)
if this_note is not None:
format = self.get_note_format(this_note, True)
tmp += Html("li",
"%s: %s" % (
str(this_note.get_type()),
self.get_note_format(this_note,
True)
))
_("%(str1)s: %(str2)s") % {
'str1' : str(this_note.get_type()),
'str2' : format
})
if tmp:
cit_ref_li += tmp
ordered1 += cit_ref_li
@ -4012,19 +4024,24 @@ class PlacePages(BasePage):
head += Html("script", type="text/javascript",
src=src_js, inline=True)
else:
url = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
url = self.secure_mode
url += "maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
head += Html("link", href=url, type="text/javascript",
rel="stylesheet")
src_js = "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
src_js = self.secure_mode
src_js += "ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
head += Html("script", type="text/javascript",
src=src_js, inline=True)
src_js = "http://openlayers.org/en/v3.17.1/build/ol.js"
src_js = self.secure_mode
src_js += "openlayers.org/en/v3.17.1/build/ol.js"
head += Html("script", type="text/javascript",
src=src_js, inline=True)
url = "http://openlayers.org/en/v3.17.1/css/ol.css"
url = self.secure_mode
url += "openlayers.org/en/v3.17.1/css/ol.css"
head += Html("link", href=url, type="text/javascript",
rel="stylesheet")
src_js = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
src_js = self.secure_mode
src_js += "maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
head += Html("script", type="text/javascript",
src=src_js, inline=True)
@ -6600,19 +6617,24 @@ class PersonPages(BasePage):
head += Html("script", type="text/javascript",
src=src_js, inline=True)
else:
url = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
url = self.secure_mode
url += "maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
head += Html("link", href=url, type="text/javascript",
rel="stylesheet")
src_js = "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
src_js = self.secure_mode
src_js += "ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"
head += Html("script", type="text/javascript",
src=src_js, inline=True)
src_js = "http://openlayers.org/en/v3.17.1/build/ol.js"
src_js = self.secure_mode
src_js += "openlayers.org/en/v3.17.1/build/ol.js"
head += Html("script", type="text/javascript",
src=src_js, inline=True)
url = "http://openlayers.org/en/v3.17.1/css/ol.css"
url = self.secure_mode
url += "openlayers.org/en/v3.17.1/css/ol.css"
head += Html("link", href=url, type="text/javascript",
rel="stylesheet")
src_js = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
src_js = self.secure_mode
src_js += "maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
head += Html("script", type="text/javascript",
src=src_js, inline=True)
@ -8349,6 +8371,10 @@ class NavWebReport(Report):
self.bkref_dict = None
self.rel_class = None
self.tab = None
if self.options['securesite']:
self.secure_mode = HTTPS
else:
self.secure_mode = HTTP
def write_report(self):
"""
@ -9660,6 +9686,11 @@ class NavWebOptions(MenuReportOptions):
stdoptions.add_localization_option(menu, category_name)
self.__securesite = BooleanOption(_("This is a secure site (https)"),
False)
self.__securesite.set_help(_('Whether to use http:// or https://'))
addopt("securesite", self.__securesite)
def __add_report_options_2(self, menu):
"""
Continue Options on the "Report Options" tab.

View File

@ -36,6 +36,7 @@ from gramps.cli.user import User
from gramps.cli.grampscli import CLIManager
from gramps.cli.argparser import ArgParser
from gramps.cli.arghandler import ArgHandler
from gramps.gen.const import USER_DIRLIST
# _caller_context is primarily here to support and document the process
# of determining the test-module's directory.
@ -254,21 +255,36 @@ class Gramps:
def run(self, *args, stdin=None, bytesio=False):
with capture(stdin, bytesio=bytesio) as output:
#load the plugins
self.climanager.do_reg_plugins(self.dbstate, uistate=None)
# handle the arguments
args = [sys.executable] + list(args)
argparser = ArgParser(args)
argparser.need_gui() # initializes some variables
if argparser.errors:
print(argparser.errors, file=sys.stderr)
argparser.print_help()
argparser.print_usage()
handler = ArgHandler(self.dbstate, argparser, self.climanager)
# create a manager to manage the database
handler.handle_args_cli()
if handler.dbstate.is_open():
handler.dbstate.db.close()
try:
try: # make sure we have user directories
for path in USER_DIRLIST:
if not os.path.isdir(path):
os.makedirs(path)
except OSError as msg:
print("Error creating user directories: " + str(msg))
except:
print("Error reading configuration.", exc_info=True)
#load the plugins
self.climanager.do_reg_plugins(self.dbstate, uistate=None)
# handle the arguments
args = [sys.executable] + list(args)
argparser = ArgParser(args)
argparser.need_gui() # initializes some variables
if argparser.errors:
print(argparser.errors, file=sys.stderr)
argparser.print_help()
argparser.print_usage()
handler = ArgHandler(self.dbstate, argparser, self.climanager)
# create a manager to manage the database
handler.handle_args_cli()
if handler.dbstate.is_open():
handler.dbstate.db.close()
except:
print("Exception in test:")
print("-" * 60)
traceback.print_exc(file=sys.stdout)
print("-" * 60)
return output
#===eof===

View File

@ -19,7 +19,7 @@
(gtk_accel_path "<Actions>/Events/Backward/Back" "<Alt>Left")
; (gtk_accel_path "<Actions>/ToolWindow/rebuild_refmap" "")
; (gtk_accel_path "<Actions>/ToolWindow/Database-Processing" "")
(gtk_accel_path "<Actions>/Events/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Events/Bookmark/EditBook" "<Shift><Meta>d")
(gtk_accel_path "<Actions>/People Tree View/PersonEdit/Remove" "<Meta>Delete")
(gtk_accel_path "<Actions>/Notes/Forward/Forward" "<Alt>Right")
(gtk_accel_path "<Actions>/Undo/Undo" "<Meta>z")
@ -29,7 +29,7 @@
(gtk_accel_path "<Actions>/Media/ChangeOrder/Remove" "<Meta>Delete")
; (gtk_accel_path "<Actions>/FileWindow/HelpMenu" "")
(gtk_accel_path "<Actions>/Place View/Bookmark/AddBook" "<Meta>d")
(gtk_accel_path "<Actions>/Repositories/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Repositories/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/ReportWindow/book" "")
; (gtk_accel_path "<Actions>/FileWindow/FileMenu" "")
(gtk_accel_path "<Actions>/Person View/Backward/Back" "<Alt>Left")
@ -49,7 +49,7 @@
(gtk_accel_path "<Actions>/Place Tree View/ChangeOrder/Add" "<Alt><Meta>i")
; (gtk_accel_path "<Actions>/ReportWindow/number_of_ancestors" "")
(gtk_accel_path "<Actions>/Families/ChangeOrder/Add" "<Alt><Meta>i")
(gtk_accel_path "<Actions>/Person View/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Person View/Bookmark/EditBook" "<Shift><Meta>d")
(gtk_accel_path "<Actions>/Relationships/Bookmark/AddBook" "<Meta>d")
; (gtk_accel_path "<Actions>/ReportWindow/familylines_graph" "")
(gtk_accel_path "<Actions>/Person View/Forward/Forward" "<Alt>Right")
@ -59,9 +59,9 @@
; (gtk_accel_path "<Actions>/ToolWindow/relcalc" "")
(gtk_accel_path "<Actions>/AllMainWindow/Export" "<Meta>e")
(gtk_accel_path "<Actions>/Pedigree/Backward/Back" "<Alt>Left")
(gtk_accel_path "<Actions>/Relationships/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Relationships/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/ToolWindow/reorder_ids" "")
(gtk_accel_path "<Actions>/Place Tree View/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Place Tree View/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu0" "")
(gtk_accel_path "<Actions>/Person View/PersonAll/Edit" "<Meta>Return")
; (gtk_accel_path "<Actions>/FileWindow/MailingLists" "")
@ -87,7 +87,7 @@
; (gtk_accel_path "<Actions>/ToolWindow/dupfind" "")
; (gtk_accel_path "<Actions>/MainWindow/EditMenu" "")
(gtk_accel_path "<Actions>/UndoHistory/UndoHistory" "<Meta>h")
(gtk_accel_path "<Actions>/Sources/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Sources/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/FileWindow/ReportBug" "")
(gtk_accel_path "<Actions>/AllMainWindow/<CONTROL>Insert" "<Alt><Meta>i")
(gtk_accel_path "<Actions>/Notes/Bookmark/AddBook" "<Meta>d")
@ -117,7 +117,7 @@
(gtk_accel_path "<Actions>/AllMainWindow/<CONTROL>BackSpace" "<Meta>BackSpace")
; (gtk_accel_path "<Actions>/ToolWindow/Utilities" "")
; (gtk_accel_path "<Actions>/AllMainWindow/WindowsMenu" "")
(gtk_accel_path "<Actions>/Families/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Families/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/AllMainWindow/F9" "F9")
; (gtk_accel_path "<Actions>/AllMainWindow/F8" "F8")
; (gtk_accel_path "<Actions>/AllMainWindow/F7" "F7")
@ -127,7 +127,7 @@
; (gtk_accel_path "<Actions>/AllMainWindow/F4" "F4")
; (gtk_accel_path "<Actions>/AllMainWindow/F3" "F3")
; (gtk_accel_path "<Actions>/AllMainWindow/F2" "F2")
(gtk_accel_path "<Actions>/Notes/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Notes/Bookmark/EditBook" "<Shift><Meta>d")
(gtk_accel_path "<Actions>/Sources/ChangeOrder/Add" "<Alt><Meta>i")
; (gtk_accel_path "<Actions>/ReportWindow/Books" "")
; (gtk_accel_path "<Actions>/FileWindow/About" "")
@ -135,7 +135,7 @@
; (gtk_accel_path "<Actions>/ReportWindow/endofline_report" "")
(gtk_accel_path "<Actions>/People Tree View/PersonEdit/Add" "<Alt><Meta>i")
; (gtk_accel_path "<Actions>/ToolWindow/dbrowse" "")
(gtk_accel_path "<Actions>/Pedigree/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Pedigree/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/ToolWindow/soundgen" "")
; (gtk_accel_path "<Actions>/FileWindow/ExtraPlugins" "")
; (gtk_accel_path "<Actions>/AllMainWindow/ReportsMenu" "")
@ -158,7 +158,7 @@
(gtk_accel_path "<Actions>/Notes/ChangeOrder/Add" "<Alt><Meta>i")
; (gtk_accel_path "<Actions>/ReportWindow/calendar" "")
; (gtk_accel_path "<Actions>/FileWindow/Fullscreen" "F11")
(gtk_accel_path "<Actions>/Fan Chart/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Fan Chart/Bookmark/EditBook" "<Shift><Meta>d")
; (gtk_accel_path "<Actions>/ReportWindow/navwebpage" "")
(gtk_accel_path "<Actions>/Repositories/Bookmark/AddBook" "<Meta>d")
(gtk_accel_path "<Actions>/Families/ChangeOrder/Remove" "<Meta>Delete")
@ -170,11 +170,11 @@
; (gtk_accel_path "<Actions>/FileWindow/TipOfDay" "")
(gtk_accel_path "<Actions>/Media/ChangeOrder/Add" "<Alt><Meta>i")
(gtk_accel_path "<Actions>/FileWindow/Quit" "<Meta>q")
(gtk_accel_path "<Actions>/People Tree View/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/People Tree View/Bookmark/EditBook" "<Shift><Meta>d")
(gtk_accel_path "<Actions>/Place Tree View/Backward/Back" "<Alt>Left")
(gtk_accel_path "<Actions>/FileWindow/Open" "<Meta>o")
(gtk_accel_path "<Actions>/Place View/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Media/Bookmark/EditBook" "<Shift><Meta>b")
(gtk_accel_path "<Actions>/Place View/Bookmark/EditBook" "<Shift><Meta>d")
(gtk_accel_path "<Actions>/Media/Bookmark/EditBook" "<Shift><Meta>d")
(gtk_accel_path "<Actions>/MainWindow/ConfigView" "<Shift><Meta>c")
(gtk_accel_path "<Actions>/People Tree View/Backward/Back" "<Alt>Left")
; (gtk_accel_path "<Actions>/FileWindow/KeyBindings" "")

View File

@ -542,7 +542,6 @@ gramps/plugins/db/bsddb/upgrade.py
gramps/plugins/db/bsddb/write.py
gramps/plugins/db/dbapi/inmemorydb.gpr.py
gramps/plugins/db/dbapi/inmemorydb.py
gramps/plugins/db/dummydb.gpr.py
gramps/plugins/docgen/asciidoc.py
gramps/plugins/docgen/docgen.gpr.py
gramps/plugins/docgen/gtkprint.glade

1709
po/ru.po

File diff suppressed because it is too large Load Diff

13194
po/sl.po

File diff suppressed because it is too large Load Diff

View File

@ -10,48 +10,49 @@ FMT="txt"
TOP_DIR=`dirname $PWD`
TEST_DIR=$TOP_DIR/test
SRC_DIR=$TOP_DIR/src
PRG="python gramps.py"
SRC_DIR=$TOP_DIR
PRG="python3 Gramps.py"
EXAMPLE_XML=$TOP_DIR/example/gramps/example.gramps
EXAMPLE_GED=$TOP_DIR/example/gedcom/sample.ged
REP_DIR=$TEST_DIR/reports/$REP
mkdir -p $REP_DIR
DATA_DIR=$TEST_DIR/data
mkdir -p $DATA_DIR
if [ -f $DATA_DIR/example.grdb ]; then
rm $DATA_DIR/example.grdb
if [ -f $DATA_DIR/example.gramps ]; then
rm $DATA_DIR/example.gramps
fi
echo ""
echo "+--------------------------------------------------------------"
echo "| Import XML, write GRDB"
echo "| Import XML, write .gramps"
echo "+--------------------------------------------------------------"
OPTS="-i $EXAMPLE_XML -o $DATA_DIR/example.grdb"
OPTS="-i $EXAMPLE_XML -e $DATA_DIR/example.gramps"
(cd $SRC_DIR; $PRG $OPTS)
OPTS="-O $DATA_DIR/example.grdb"
OPTS="-i $DATA_DIR/example.gramps"
echo ""
echo "+--------------------------------------------------------------"
echo "| Export Test Files"
echo "| Text Report: "$REP
echo "| Text Format: "$FMT
echo "+--------------------------------------------------------------"
for desref in {0,1}; do
for incphotos in {0,1}; do
for omitda in {0,1}; do
for incsources in {0,1}; do
for usenick in {0,1}; do
for fulldates in {0,1}; do
for incnotes in {0,1}; do
for repplace in {0,1}; do
for repdate in {0,1}; do
for computeage in {0,1}; do
for incnames in {0,1}; do
for incevents in {0,1}; do
for listc in {0,1}; do
output="$desref$incphotos$omitda$incsources$usenick$fulldates$incnotes$repplace$repdate$computeage$incnames$incevents$listc"
action="-a report -p name=$REP,id=I44,off=$FMT,of=$REP_DIR/$output.$FMT,desref=$desref,incphotos=$incphotos,omitda=$omitda,incsources=$incsources,usenick=$usenick,fulldates=$fulldates,incnotes=$incnotes,repplace=$repplace,repdate=$repdate,computeage=$computeage,incnames=$incnames,incevents=$incevents,listc=$listc"
for desref in 'True' 'False'; do
for incphotos in 'True' 'False'; do
for omitda in 'True' 'False'; do
for incsources in 'True' 'False'; do
for fulldates in 'True' 'False'; do
for incnotes in 'True' 'False'; do
for repplace in 'True' 'False'; do
for repdate in 'True' 'False'; do
for computeage in 'True' 'False'; do
for incnames in 'True' 'False'; do
for incevents in 'True' 'False'; do
for listc in 'True' 'False'; do
output="$desref$incphotos$omitda$incsources$fulldates$incnotes$repplace$repdate$computeage$incnames$incevents$listc"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,desref=$desref,incphotos=$incphotos,omitda=$omitda,incsources=$incsources,fulldates=$fulldates,incnotes=$incnotes,repplace=$repplace,repdate=$repdate,computeage=$computeage,incnames=$incnames,incevents=$incevents,listc=$listc"
(cd $SRC_DIR; $PRG $OPTS $action)
done
done
@ -65,4 +66,20 @@ done
done
done
done
done
echo "+--------------------------------------------------------------"
echo "| Export file based on sample.ged"
echo "| Text Report: "$REP
echo "| Text Format: "$FMT
echo "+--------------------------------------------------------------"
(cd $SRC_DIR; $PRG -i $EXAMPLE_GED -e $DATA_DIR/example.gramps)
output="NoChildren"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,listc=False,listc_spouses=False"
(cd $SRC_DIR; $PRG $OPTS $action)
output="ChildrenNoSpouse"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,listc=True,listc_spouses=False"
(cd $SRC_DIR; $PRG $OPTS $action)
output="ChildrenSpouse"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,listc=True,listc_spouses=True"
(cd $SRC_DIR; $PRG $OPTS $action)

View File

@ -5,55 +5,55 @@
# $Id$
REP="det_ancestor_report"
REP="det_descendant_report"
FMT="txt"
TOP_DIR=`dirname $PWD`
TEST_DIR=$TOP_DIR/test
SRC_DIR=$TOP_DIR/src
PRG="python gramps.py"
SRC_DIR=$TOP_DIR
PRG="python3 Gramps.py"
EXAMPLE_XML=$TOP_DIR/example/gramps/example.gramps
EXAMPLE_GED=$TOP_DIR/example/gedcom/sample.ged
REP_DIR=$TEST_DIR/reports/$REP
mkdir -p $REP_DIR
DATA_DIR=$TEST_DIR/data
mkdir -p $DATA_DIR
if [ -f $DATA_DIR/example.grdb ]; then
rm $DATA_DIR/example.grdb
if [ -f $DATA_DIR/example.gramps ]; then
rm $DATA_DIR/example.gramps
fi
echo ""
echo "+--------------------------------------------------------------"
echo "| Import XML, write GRDB"
echo "| Import XML, write .gramps"
echo "+--------------------------------------------------------------"
OPTS="-i $EXAMPLE_XML -o $DATA_DIR/example.grdb"
(cd $SRC_DIR; $PRG $OPTS)
OPTS="-i $EXAMPLE_XML -e $DATA_DIR/example.gramps"
#(cd $SRC_DIR; $PRG $OPTS)
OPTS="-O $DATA_DIR/example.grdb"
OPTS="-i $DATA_DIR/example.gramps"
echo ""
echo "+--------------------------------------------------------------"
echo "| Export Test Files"
echo "| Text Report: "$REP
echo "| Text Format: "$FMT
echo "+--------------------------------------------------------------"
for desref in {0,1}; do
for incphotos in {0,1}; do
for omitda in {0,1}; do
for incsources in {0,1}; do
for usenick in {0,1}; do
for fulldates in {0,1}; do
for incnotes in {0,1}; do
for repplace in {0,1}; do
for repdate in {0,1}; do
for computeage in {0,1}; do
for incnames in {0,1}; do
for incevents in {0,1}; do
for listc in {0,1}; do
for desref in 'True' 'False'; do
for incphotos in 'True' 'False'; do
for omitda in 'True' 'False'; do
for incsources in 'True' 'False'; do
for fulldates in 'True' 'False'; do
for incnotes in 'True' 'False'; do
for repplace in 'True' 'False'; do
for repdate in 'True' 'False'; do
for computeage in 'True' 'False'; do
for incnames in 'True' 'False'; do
for incevents in 'True' 'False'; do
for listc in 'True' 'False'; do
output="$desref$incphotos$omitda$incsources$usenick$fulldates$incnotes$repplace$repdate$computeage$incnames$incevents$listc"
action="-a report -p name=$REP,id=I44,off=$FMT,of=$REP_DIR/$output.$FMT,desref=$desref,incphotos=$incphotos,omitda=$omitda,incsources=$incsources,usenick=$usenick,fulldates=$fulldates,incnotes=$incnotes,repplace=$repplace,repdate=$repdate,computeage=$computeage,incnames=$incnames,incevents=$incevents,listc=$listc"
(cd $SRC_DIR; $PRG $OPTS $action)
done
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,desref=$desref,incphotos=$incphotos,omitda=$omitda,incsources=$incsources,fulldates=$fulldates,incnotes=$incnotes,repplace=$repplace,repdate=$repdate,computeage=$computeage,incnames=$incnames,incevents=$incevents,listc=$listc"
#(cd $SRC_DIR; $PRG $OPTS $action)
done
done
done
@ -66,3 +66,14 @@ done
done
done
done
(cd $SRC_DIR; $PRG -i $EXAMPLE_GED -e $DATA_DIR/example.gramps)
output="NoChildren"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,listc=False,listc_spouses=False"
(cd $SRC_DIR; $PRG $OPTS $action)
output="ChildrenNoSpouse"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,listc=True,listc_spouses=False"
(cd $SRC_DIR; $PRG $OPTS $action)
output="ChildrenSpouse"
action="-a report -p name=$REP,off=$FMT,of=$REP_DIR/$output.$FMT,listc=True,listc_spouses=True"
(cd $SRC_DIR; $PRG $OPTS $action)