Merge branch 'gramps50'
This commit is contained in:
commit
19f8c3561c
@ -288,10 +288,6 @@ table.infolist thead tr th {
|
||||
table.infolist tr td {
|
||||
border-bottom: dashed 1px #000;
|
||||
vertical-align: middle;
|
||||
padding: 6px 0 6px 10px;
|
||||
}
|
||||
table.infolist tr td a {
|
||||
display: block;
|
||||
}
|
||||
table.infolist tr.BeginLetter td, table.infolist tr.BeginSurname td {
|
||||
border-top: solid 1px #000;
|
||||
@ -351,15 +347,15 @@ div#Individuals {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
div#Individuals table.individuallist {
|
||||
div#Individuals table.IndividualList {
|
||||
border-bottom: solid 1px #000;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td.ColumnSurname a:hover,
|
||||
div#Individuals table.individuallist tbody tr td.ColumnSurname a:active {
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnSurname a:hover,
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnSurname a:active {
|
||||
cursor: default;
|
||||
background: none;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td.ColumnName a {
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnName a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
div#Individuals div table.infolist tr td p {
|
||||
@ -1129,9 +1125,10 @@ div.narrative {
|
||||
}
|
||||
.narrative p {
|
||||
font: normal .9em/1.4em sans-serif;
|
||||
margin-top: .5em;
|
||||
margin-bottom: 0;
|
||||
padding: 0 20px 1em 20px;
|
||||
margin: 0.1em 0 0.2em 0;
|
||||
}
|
||||
i + div.grampsstylednote p {
|
||||
margin: 0.1em 0 0.2em 0;
|
||||
}
|
||||
|
||||
/* Subsections : References
|
||||
|
@ -276,7 +276,6 @@ table.infolist tr th a:hover {
|
||||
table.infolist tr td {
|
||||
font:normal 1.1em/1.4em serif;
|
||||
vertical-align:middle;
|
||||
padding:.1em 10px;
|
||||
}
|
||||
table.infolist tr td a {
|
||||
display:block;
|
||||
@ -396,30 +395,30 @@ table.surname thead tr th.ColumnParents, table.surname tbody tr td.ColumnParents
|
||||
/* Individuals
|
||||
----------------------------------------------------- */
|
||||
#Individuals { }
|
||||
#Individuals table.individuallist {
|
||||
#Individuals table.IndividualList {
|
||||
border-bottom:solid 1px #A97;
|
||||
}
|
||||
#Individuals table.individuallist tbody tr td {
|
||||
#Individuals table.IndividualList tbody tr td {
|
||||
border-bottom:dashed 1px #C1B398;
|
||||
}
|
||||
#Individuals table.individuallist tbody tr td a:hover {
|
||||
#Individuals table.IndividualList tbody tr td a:hover {
|
||||
text-decoration:none;
|
||||
}
|
||||
table.individuallist tbody tr td.ColumnSurname a:hover, table.individuallist tbody tr td.ColumnSurname a:active {
|
||||
table.IndividualList tbody tr td.ColumnSurname a:hover, table.IndividualList tbody tr td.ColumnSurname a:active {
|
||||
cursor:default;
|
||||
color:black;
|
||||
background:none;
|
||||
}
|
||||
table.individuallist tbody tr td.ColumnName {
|
||||
table.IndividualList tbody tr td.ColumnName {
|
||||
padding:0;
|
||||
background-color:#FFF;
|
||||
}
|
||||
table.individuallist tbody tr td.ColumnName a {
|
||||
table.IndividualList tbody tr td.ColumnName a {
|
||||
display:block;
|
||||
padding:.6em 10px;
|
||||
padding:.1em .1em;
|
||||
vertical-align:middle;
|
||||
}
|
||||
table.individuallist tbody tr td.ColumnName a:hover {
|
||||
table.IndividualList tbody tr td.ColumnName a:hover {
|
||||
background-color:#C1B398;
|
||||
}
|
||||
#Individuals div table.infolist tr td p {
|
||||
@ -960,11 +959,12 @@ div#Addresses table.infolist tr td a, div#Addresses table.infolist tr td p a {
|
||||
div.narrative {
|
||||
padding-bottom:0;
|
||||
}
|
||||
i + div.grampsstylednote p {
|
||||
margin: 0.1em 0 0.2em 0;
|
||||
}
|
||||
.narrative p {
|
||||
margin: 0.1em 0 0.2em 0;
|
||||
font:normal .9em/1.4em sans-serif;
|
||||
margin-top:.5em;
|
||||
margin-bottom:0;
|
||||
padding:0 20px 1em 20px;
|
||||
}
|
||||
|
||||
/* Subsections : References
|
||||
|
@ -454,30 +454,30 @@ div#Individuals {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
div#Individuals table.individuallist {
|
||||
div#Individuals table.IndividualList {
|
||||
border-bottom: solid 1px #5D835F;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td {
|
||||
div#Individuals table.IndividualList tbody tr td {
|
||||
border-bottom: dashed 1px #5D835F;
|
||||
background-color: #D8F3D6;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td a {
|
||||
div#Individuals table.IndividualList tbody tr td a {
|
||||
display: block;
|
||||
padding: .6em 10px;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td.ColumnSurname a:hover,
|
||||
div#Individuals table.individuallist tbody tr td.ColumnSurname a:active {
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnSurname a:hover,
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnSurname a:active {
|
||||
cursor:default;
|
||||
color: #000;
|
||||
background:none;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td.ColumnName {
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnName {
|
||||
background-color: #FFF;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td.ColumnName a {
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnName a {
|
||||
vertical-align:middle;
|
||||
}
|
||||
div#Individuals table.individuallist tbody tr td.ColumnPartner {
|
||||
div#Individuals table.IndividualList tbody tr td.ColumnPartner {
|
||||
background-color: #FFF;
|
||||
}
|
||||
div#Individuals div table.infolist tr td p {
|
||||
|
@ -33,7 +33,9 @@ body#FamilyMap {
|
||||
border: solid 4px #000;
|
||||
margin: 0px auto;
|
||||
width: 800px;
|
||||
height: 800px;
|
||||
height: 400px;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
/* Place Maps
|
||||
@ -43,6 +45,8 @@ div#place_canvas {
|
||||
border: solid 4px #000;
|
||||
width: 500px;
|
||||
height: 400px;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
button#drop {
|
||||
background-color: purple;
|
||||
|
@ -318,6 +318,7 @@ class CLIManager:
|
||||
and self.dbstate.db.get_total() == 0):
|
||||
self.dbstate.db.set_researcher(owner)
|
||||
|
||||
name_displayer.clear_custom_formats()
|
||||
name_displayer.set_name_format(self.dbstate.db.name_formats)
|
||||
fmt_default = config.get('preferences.name-format')
|
||||
name_displayer.set_default_format(fmt_default)
|
||||
|
@ -47,7 +47,8 @@ LOG = logging.getLogger(".")
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.plug import BasePluginManager
|
||||
from gramps.gen.plug.docgen import (StyleSheet, StyleSheetList, PaperStyle,
|
||||
PAPER_PORTRAIT, PAPER_LANDSCAPE, graphdoc)
|
||||
PAPER_PORTRAIT, PAPER_LANDSCAPE, graphdoc,
|
||||
treedoc)
|
||||
from gramps.gen.plug.menu import (FamilyOption, PersonOption, NoteOption,
|
||||
MediaOption, PersonListOption, NumberOption,
|
||||
BooleanOption, DestinationOption, Option,
|
||||
@ -56,8 +57,8 @@ from gramps.gen.plug.menu import (FamilyOption, PersonOption, NoteOption,
|
||||
from gramps.gen.display.name import displayer as name_displayer
|
||||
from gramps.gen.errors import ReportError, FilterError
|
||||
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
||||
CATEGORY_GRAPHVIZ, CATEGORY_CODE,
|
||||
ReportOptions, append_styles)
|
||||
CATEGORY_GRAPHVIZ, CATEGORY_TREE,
|
||||
CATEGORY_CODE, ReportOptions, append_styles)
|
||||
from gramps.gen.plug.report._paper import paper_sizes
|
||||
from gramps.gen.const import USER_HOME, DOCGEN_OPTIONS
|
||||
from gramps.gen.dbstate import DbState
|
||||
@ -250,6 +251,15 @@ class CommandLineReport:
|
||||
if name not in self.option_class.options_dict:
|
||||
self.option_class.options_dict[
|
||||
name] = menu.get_option_by_name(name).get_value()
|
||||
if category == CATEGORY_TREE:
|
||||
# Need to include Genealogy Tree options
|
||||
self.__toptions = treedoc.TreeOptions()
|
||||
menu = self.option_class.menu
|
||||
self.__toptions.add_menu_options(menu)
|
||||
for name in menu.get_all_option_names():
|
||||
if name not in self.option_class.options_dict:
|
||||
self.option_class.options_dict[
|
||||
name] = menu.get_option_by_name(name).get_value()
|
||||
self.option_class.load_previous_values()
|
||||
_validate_options(self.option_class, database)
|
||||
self.show = options_str_dict.pop('show', None)
|
||||
@ -320,6 +330,10 @@ class CommandLineReport:
|
||||
for graph_format in graphdoc.FORMATS:
|
||||
self.options_help['off'][2].append(
|
||||
graph_format["type"] + "\t" + graph_format["descr"])
|
||||
elif self.category == CATEGORY_TREE:
|
||||
for tree_format in treedoc.FORMATS:
|
||||
self.options_help['off'][2].append(
|
||||
tree_format["type"] + "\t" + tree_format["descr"])
|
||||
else:
|
||||
self.options_help['off'][2] = "NA"
|
||||
|
||||
@ -498,6 +512,15 @@ class CommandLineReport:
|
||||
# Pick the first one as the default.
|
||||
self.format = graphdoc.FORMATS[0]["class"]
|
||||
_chosen_format = graphdoc.FORMATS[0]["type"]
|
||||
elif self.category == CATEGORY_TREE:
|
||||
for tree_format in treedoc.FORMATS:
|
||||
if tree_format['type'] == self.options_dict['off']:
|
||||
if not self.format: # choose the first one, not the last
|
||||
self.format = tree_format["class"]
|
||||
if self.format is None:
|
||||
# Pick the first one as the default.
|
||||
self.format = tree_format.FORMATS[0]["class"]
|
||||
_chosen_format = tree_format.FORMATS[0]["type"]
|
||||
else:
|
||||
self.format = None
|
||||
if _chosen_format and _format_str:
|
||||
@ -665,7 +688,7 @@ def cl_report(database, name, category, report_class, options_class,
|
||||
clr.selected_style,
|
||||
PaperStyle(clr.paper, clr.orien, clr.marginl,
|
||||
clr.marginr, clr.margint, clr.marginb))
|
||||
elif category == CATEGORY_GRAPHVIZ:
|
||||
elif category in [CATEGORY_GRAPHVIZ, CATEGORY_TREE]:
|
||||
clr.option_class.handler.doc = clr.format(
|
||||
clr.option_class,
|
||||
PaperStyle(clr.paper, clr.orien, clr.marginl,
|
||||
|
@ -274,22 +274,25 @@ register('preferences.last-view', '')
|
||||
register('preferences.last-views', [])
|
||||
register('preferences.family-relation-type', 3) # UNKNOWN
|
||||
register('preferences.age-display-precision', 1)
|
||||
register('preferences.color-gender-male-alive', '#b8cee6')
|
||||
register('preferences.color-gender-male-death', '#b8cee6')
|
||||
register('preferences.color-gender-female-alive', '#feccf0')
|
||||
register('preferences.color-gender-female-death', '#feccf0')
|
||||
register('preferences.color-gender-unknown-alive', '#f3dbb6')
|
||||
register('preferences.color-gender-unknown-death', '#f3dbb6')
|
||||
#register('preferences.color-gender-other-alive', '#fcaf3e')
|
||||
#register('preferences.color-gender-other-death', '#fcaf3e')
|
||||
register('preferences.bordercolor-gender-male-alive', '#1f4986')
|
||||
register('preferences.bordercolor-gender-male-death', '#000000')
|
||||
register('preferences.bordercolor-gender-female-alive', '#861f69')
|
||||
register('preferences.bordercolor-gender-female-death', '#000000')
|
||||
register('preferences.bordercolor-gender-unknown-alive', '#8e5801')
|
||||
register('preferences.bordercolor-gender-unknown-death', '#000000')
|
||||
#register('preferences.bordercolor-gender-other-alive', '#f57900')
|
||||
#register('preferences.bordercolor-gender-other-death', '#000000')
|
||||
|
||||
register('colors.scheme', 0)
|
||||
register('colors.male-alive', ['#b8cee6', '#1f344a'])
|
||||
register('colors.male-dead', ['#b8cee6', '#2d3039'])
|
||||
register('colors.female-alive', ['#feccf0', '#62242D'])
|
||||
register('colors.female-dead', ['#feccf0', '#3a292b'])
|
||||
register('colors.unknown-alive', ['#f3dbb6', '#75507B'])
|
||||
register('colors.unknown-dead', ['#f3dbb6', '#35103b'])
|
||||
register('colors.family', ['#eeeeee', '#454545'])
|
||||
register('colors.family-divorced', ['#ffdede', '#5c3636'])
|
||||
register('colors.home-person', ['#bbe68a', '#304918'])
|
||||
register('colors.border-male-alive', ['#1f4986', '#171d26'])
|
||||
register('colors.border-male-dead', ['#000000', '#000000'])
|
||||
register('colors.border-female-alive', ['#861f69', '#261111'])
|
||||
register('colors.border-female-dead', ['#000000', '#000000'])
|
||||
register('colors.border-unknown-alive', ['#8e5801', '#8e5801'])
|
||||
register('colors.border-unknown-dead', ['#000000', '#000000'])
|
||||
register('colors.border-family', ['#cccccc', '#252525'])
|
||||
register('colors.border-family-divorced', ['#ff7373', '#720b0b'])
|
||||
|
||||
register('researcher.researcher-addr', '')
|
||||
register('researcher.researcher-locality', '')
|
||||
|
@ -292,7 +292,7 @@ class DateDisplayDE(DateDisplay):
|
||||
)
|
||||
# this definition must agree with its "_display_gregorian" method
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
def _display_gregorian(self, date_val, **kwargs):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
|
@ -155,7 +155,7 @@ class DateDisplayEL(DateDisplay):
|
||||
)
|
||||
# this definition must agree with its "_display_gregorian" method
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
def _display_gregorian(self, date_val, **kwargs):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
|
@ -187,7 +187,7 @@ class DateDisplayLT(DateDisplay):
|
||||
"mmmm m. mėnesio diena d.", "Mėn diena, metai")
|
||||
# this definition must agree with its "_display_gregorian" method
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
def _display_gregorian(self, date_val, **kwargs):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
|
@ -164,7 +164,7 @@ class DateDisplayNL(DateDisplay):
|
||||
)
|
||||
# this definition must agree with its "_display_gregorian" method
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
def _display_gregorian(self, date_val, **kwargs):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
|
@ -215,7 +215,7 @@ class DateDisplayPL(DateDisplay):
|
||||
"XII"
|
||||
)
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
def _display_gregorian(self, date_val, **kwargs):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
|
@ -240,7 +240,7 @@ class DateDisplaySR_Base(DateDisplay):
|
||||
"VII", "VIII", "IX", "X", "XI", "XII"
|
||||
)
|
||||
|
||||
def _display_gregorian(self, date_val):
|
||||
def _display_gregorian(self, date_val, **kwargs):
|
||||
"""
|
||||
display gregorian calendar date in different format
|
||||
"""
|
||||
|
@ -418,6 +418,11 @@ class NameDisplay:
|
||||
result = raw_data[_FIRSTNAME]
|
||||
return ' '.join(result.split())
|
||||
|
||||
def clear_custom_formats(self):
|
||||
self.name_formats = {num: value
|
||||
for num, value in self.name_formats.items()
|
||||
if num >= 0}
|
||||
|
||||
def set_name_format(self, formats):
|
||||
|
||||
raw_func_dict = {
|
||||
|
@ -82,7 +82,8 @@ class IsDescendantFamilyOf(Rule):
|
||||
|
||||
while expand:
|
||||
person = expand.pop(0)
|
||||
if person is None:
|
||||
if person is None or person.handle in self.matches:
|
||||
# if we have been here before, skip
|
||||
continue
|
||||
self.matches.add(person.handle)
|
||||
for family_handle in person.get_family_handle_list():
|
||||
|
@ -67,7 +67,8 @@ class IsDescendantOf(Rule):
|
||||
return person.handle in self.map
|
||||
|
||||
def init_list(self, person, first):
|
||||
if not person:
|
||||
if not person or person.handle in self.map:
|
||||
# if we have been here before, skip
|
||||
return
|
||||
if not first:
|
||||
self.map.add(person.handle)
|
||||
|
@ -61,6 +61,9 @@ class IsLessThanNthGenerationAncestorOf(Rule):
|
||||
queue = [(root_handle, 1)] # generation 1 is root
|
||||
while queue:
|
||||
handle, gen = queue.pop(0) # pop off front of queue
|
||||
if handle in self.map:
|
||||
# if we have been here before, skip
|
||||
continue
|
||||
self.map.add(handle)
|
||||
gen += 1
|
||||
if gen <= int(self.list[1]):
|
||||
|
@ -71,7 +71,8 @@ class IsLessThanNthGenerationAncestorOfBookmarked(Rule):
|
||||
def init_ancestor_list(self, handle, gen):
|
||||
# if p.get_handle() in self.map:
|
||||
# loop_error(self.orig,p)
|
||||
if not handle:
|
||||
if not handle or handle in self.map:
|
||||
# if been here already, skip
|
||||
return
|
||||
if gen:
|
||||
self.map.add(handle)
|
||||
|
@ -64,7 +64,8 @@ class IsLessThanNthGenerationAncestorOfDefaultPerson(Rule):
|
||||
def init_ancestor_list(self, handle, gen):
|
||||
# if p.get_handle() in self.map:
|
||||
# loop_error(self.orig,p)
|
||||
if not handle:
|
||||
if not handle or handle in self.map:
|
||||
# if we have been here before, skip
|
||||
return
|
||||
if gen:
|
||||
self.map.add(handle)
|
||||
|
@ -65,7 +65,8 @@ class IsLessThanNthGenerationDescendantOf(Rule):
|
||||
return person.handle in self.map
|
||||
|
||||
def init_list(self,person,gen):
|
||||
if not person:
|
||||
if not person or person.handle in self.map:
|
||||
# if we have been here before, skip
|
||||
return
|
||||
if gen:
|
||||
self.map.add(person.handle)
|
||||
|
@ -27,7 +27,7 @@ The "plug" package for handling plugins in Gramps.
|
||||
from ._plugin import Plugin
|
||||
from ._pluginreg import (PluginData, PluginRegister, REPORT, TOOL,
|
||||
CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE,
|
||||
CATEGORY_WEB, CATEGORY_BOOK, CATEGORY_GRAPHVIZ,
|
||||
CATEGORY_WEB, CATEGORY_BOOK, CATEGORY_GRAPHVIZ, CATEGORY_TREE,
|
||||
TOOL_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX, TOOL_REVCTL,
|
||||
TOOL_UTILS, CATEGORY_QR_MISC, CATEGORY_QR_PERSON,
|
||||
CATEGORY_QR_FAMILY, CATEGORY_QR_EVENT, CATEGORY_QR_SOURCE,
|
||||
@ -46,14 +46,14 @@ from ._options import (Options, OptionListCollection, OptionList,
|
||||
OptionHandler, MenuOptions)
|
||||
|
||||
__all__ = [ "docbackend", "docgen", "menu", "Plugin", "PluginData",
|
||||
"PluginRegister", "BasePluginManager",
|
||||
"ImportPlugin", "ExportPlugin", "DocGenPlugin",
|
||||
"REPORT", "TOOL", "CATEGORY_TEXT", "CATEGORY_DRAW", "CATEGORY_CODE",
|
||||
"CATEGORY_WEB", "CATEGORY_BOOK", "CATEGORY_GRAPHVIZ",
|
||||
"TOOL_DEBUG", "TOOL_ANAL", "TOOL_DBPROC", "TOOL_DBFIX", "TOOL_REVCTL",
|
||||
"TOOL_UTILS", "CATEGORY_QR_MISC", "CATEGORY_QR_PERSON",
|
||||
"CATEGORY_QR_FAMILY", "CATEGORY_QR_EVENT", "CATEGORY_QR_SOURCE",
|
||||
"CATEGORY_QR_PLACE", "CATEGORY_QR_REPOSITORY", "CATEGORY_QR_NOTE",
|
||||
"CATEGORY_QR_DATE", "PTYPE_STR", "CATEGORY_QR_MEDIA",
|
||||
"CATEGORY_QR_CITATION", "CATEGORY_QR_SOURCE_OR_CITATION",
|
||||
"START", "END", "make_environment"]
|
||||
"PluginRegister", "BasePluginManager", "ImportPlugin",
|
||||
"ExportPlugin", "DocGenPlugin", "REPORT", "TOOL", "CATEGORY_TEXT",
|
||||
"CATEGORY_DRAW", "CATEGORY_CODE", "CATEGORY_WEB", "CATEGORY_BOOK",
|
||||
"CATEGORY_GRAPHVIZ", "CATEGORY_TREE", "TOOL_DEBUG", "TOOL_ANAL",
|
||||
"TOOL_DBPROC", "TOOL_DBFIX", "TOOL_REVCTL","TOOL_UTILS",
|
||||
"CATEGORY_QR_MISC", "CATEGORY_QR_PERSON", "CATEGORY_QR_FAMILY",
|
||||
"CATEGORY_QR_EVENT", "CATEGORY_QR_SOURCE", "CATEGORY_QR_PLACE",
|
||||
"CATEGORY_QR_REPOSITORY", "CATEGORY_QR_NOTE", "CATEGORY_QR_DATE",
|
||||
"PTYPE_STR", "CATEGORY_QR_MEDIA", "CATEGORY_QR_CITATION",
|
||||
"CATEGORY_QR_SOURCE_OR_CITATION", "START", "END",
|
||||
"make_environment"]
|
||||
|
@ -97,8 +97,10 @@ CATEGORY_CODE = 2
|
||||
CATEGORY_WEB = 3
|
||||
CATEGORY_BOOK = 4
|
||||
CATEGORY_GRAPHVIZ = 5
|
||||
CATEGORY_TREE = 6
|
||||
REPORT_CAT = [ CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE,
|
||||
CATEGORY_WEB, CATEGORY_BOOK, CATEGORY_GRAPHVIZ]
|
||||
CATEGORY_WEB, CATEGORY_BOOK, CATEGORY_GRAPHVIZ,
|
||||
CATEGORY_TREE]
|
||||
#possible tool categories
|
||||
TOOL_DEBUG = -1
|
||||
TOOL_ANAL = 0
|
||||
@ -1043,6 +1045,7 @@ def make_environment(**kwargs):
|
||||
'CATEGORY_WEB': CATEGORY_WEB,
|
||||
'CATEGORY_BOOK': CATEGORY_BOOK,
|
||||
'CATEGORY_GRAPHVIZ': CATEGORY_GRAPHVIZ,
|
||||
'CATEGORY_TREE': CATEGORY_TREE,
|
||||
'TOOL_DEBUG': TOOL_DEBUG,
|
||||
'TOOL_ANAL': TOOL_ANAL,
|
||||
'TOOL_DBPROC': TOOL_DBPROC,
|
||||
@ -1242,8 +1245,7 @@ class PluginRegister:
|
||||
"""
|
||||
Return a list of :class:`PluginData` that are of type ptype
|
||||
"""
|
||||
return [self.get_plugin(id) for id in
|
||||
set([x.id for x in self.__plugindata if x.ptype == ptype])]
|
||||
return [x for x in self.__plugindata if x.ptype == ptype]
|
||||
|
||||
def report_plugins(self, gui=True):
|
||||
"""
|
||||
@ -1352,6 +1354,4 @@ class PluginRegister:
|
||||
"""
|
||||
Return a list of :class:`PluginData` that have load_on_reg == True
|
||||
"""
|
||||
return [self.get_plugin(id) for id in
|
||||
set([x.id for x in self.__plugindata
|
||||
if x.load_on_reg == True])]
|
||||
return [x for x in self.__plugindata if x.load_on_reg == True]
|
||||
|
@ -37,3 +37,4 @@ from .textdoc import TextDoc, IndexMark,INDEX_TYPE_ALP, INDEX_TYPE_TOC,\
|
||||
URL_PATTERN, LOCAL_HYPERLINK, LOCAL_TARGET
|
||||
from .drawdoc import DrawDoc
|
||||
from .graphdoc import GVDoc
|
||||
from .treedoc import TreeDoc
|
||||
|
633
gramps/gen/plug/docgen/treedoc.py
Normal file
633
gramps/gen/plug/docgen/treedoc.py
Normal file
@ -0,0 +1,633 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2017-2018 Nick Hall
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
""" LaTeX Genealogy Tree adapter for Trees """
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import os
|
||||
import shutil
|
||||
from io import StringIO
|
||||
import tempfile
|
||||
import logging
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...utils.file import search_for
|
||||
from ...lib import Person, EventType, EventRoleType, Date
|
||||
from ...display.place import displayer as _pd
|
||||
from ...utils.file import media_path_full
|
||||
from . import BaseDoc, PAPER_PORTRAIT
|
||||
from ..menu import NumberOption, TextOption, EnumeratedListOption
|
||||
from ...constfunc import win
|
||||
from ...config import config
|
||||
from ...const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# set up logging
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
LOG = logging.getLogger(".treedoc")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Private Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
_DETAIL = [{'name': _("Full"), 'value': "full"},
|
||||
{'name': _("Medium"), 'value': "medium"},
|
||||
{'name': _("Short"), 'value': "short"}]
|
||||
|
||||
_MARRIAGE = [{'name': _("Default"), 'value': ""},
|
||||
{'name': _("Above"), 'value': "marriage above"},
|
||||
{'name': _("Below"), 'value': "marriage below"},
|
||||
{'name': _("Not shown"), 'value': "no marriage"}]
|
||||
|
||||
_COLOR = [{'name': _("None"), 'value': "none"},
|
||||
{'name': _("Default"), 'value': "default"},
|
||||
{'name': _("Preferences"), 'value': "preferences"}]
|
||||
|
||||
_TIMEFLOW = [{'name': _("Down (↓)"), 'value': ""},
|
||||
{'name': _("Up (↑)"), 'value': "up"},
|
||||
{'name': _("Right (→)"), 'value': "right"},
|
||||
{'name': _("Left (←)"), 'value': "left"}]
|
||||
|
||||
_EDGES = [{'name': _("Perpendicular"), 'value': ""},
|
||||
{'name': _("Rounded"), 'value': "rounded", },
|
||||
{'name': _("Swing"), 'value': "swing", },
|
||||
{'name': _("Mesh"), 'value': 'mesh'}]
|
||||
|
||||
_NOTELOC = [{'name': _("Top"), 'value': "t"},
|
||||
{'name': _("Bottom"), 'value': "b"}]
|
||||
|
||||
_NOTESIZE = [{'name': _("Tiny"), 'value': "tiny"},
|
||||
{'name': _("Script"), 'value': "scriptsize"},
|
||||
{'name': _("Footnote"), 'value': "footnotesize"},
|
||||
{'name': _("Small"), 'value': "small"},
|
||||
{'name': _("Normal"), 'value': "normalsize"},
|
||||
{'name': _("Large"), 'value': "large"},
|
||||
{'name': _("Very large"), 'value': "Large"},
|
||||
{'name': _("Extra large"), 'value': "LARGE"},
|
||||
{'name': _("Huge"), 'value': "huge"},
|
||||
{'name': _("Extra huge"), 'value': "Huge"}]
|
||||
|
||||
if win():
|
||||
_LATEX_FOUND = search_for("lualatex.exe")
|
||||
else:
|
||||
_LATEX_FOUND = search_for("lualatex")
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# TreeOptions
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
class TreeOptions:
|
||||
"""
|
||||
Defines all of the controls necessary
|
||||
to configure the genealogy tree reports.
|
||||
"""
|
||||
def add_menu_options(self, menu):
|
||||
"""
|
||||
Add all graph related options to the menu.
|
||||
|
||||
:param menu: The menu the options should be added to.
|
||||
:type menu: :class:`.Menu`
|
||||
:return: nothing
|
||||
"""
|
||||
################################
|
||||
category = _("Node Options")
|
||||
################################
|
||||
|
||||
detail = EnumeratedListOption(_("Node detail"), "full")
|
||||
for item in _DETAIL:
|
||||
detail.add_item(item["value"], item["name"])
|
||||
detail.set_help(_("Detail of information to be shown in a node."))
|
||||
menu.add_option(category, "detail", detail)
|
||||
|
||||
marriage = EnumeratedListOption(_("Marriage"), "")
|
||||
for item in _MARRIAGE:
|
||||
marriage.add_item(item["value"], item["name"])
|
||||
marriage.set_help(_("Position of marriage information."))
|
||||
menu.add_option(category, "marriage", marriage)
|
||||
|
||||
nodesize = NumberOption(_("Node size"), 25, 5, 100, 5)
|
||||
nodesize.set_help(_("One dimension of a node, in mm. If the timeflow "
|
||||
"is up or down then this is the width, otherwise "
|
||||
"it is the height."))
|
||||
menu.add_option(category, "nodesize", nodesize)
|
||||
|
||||
levelsize = NumberOption(_("Level size"), 35, 5, 100, 5)
|
||||
levelsize.set_help(_("One dimension of a node, in mm. If the timeflow "
|
||||
"is up or down then this is the height, otherwise "
|
||||
"it is the width."))
|
||||
menu.add_option(category, "levelsize", levelsize)
|
||||
|
||||
nodecolor = EnumeratedListOption(_("Color"), "none")
|
||||
for item in _COLOR:
|
||||
nodecolor.add_item(item["value"], item["name"])
|
||||
nodecolor.set_help(_("Node color."))
|
||||
menu.add_option(category, "nodecolor", nodecolor)
|
||||
|
||||
################################
|
||||
category = _("Tree Options")
|
||||
################################
|
||||
|
||||
timeflow = EnumeratedListOption(_("Timeflow"), "")
|
||||
for item in _TIMEFLOW:
|
||||
timeflow.add_item(item["value"], item["name"])
|
||||
timeflow.set_help(_("Direction that the graph will grow over time."))
|
||||
menu.add_option(category, "timeflow", timeflow)
|
||||
|
||||
edges = EnumeratedListOption(_("Edge style"), "")
|
||||
for item in _EDGES:
|
||||
edges.add_item(item["value"], item["name"])
|
||||
edges.set_help(_("Style of the edges between nodes."))
|
||||
menu.add_option(category, "edges", edges)
|
||||
|
||||
leveldist = NumberOption(_("Level distance"), 5, 1, 20, 1)
|
||||
leveldist.set_help(_("The minimum amount of free space, in mm, "
|
||||
"between levels. For vertical graphs, this "
|
||||
"corresponds to spacing between rows. For "
|
||||
"horizontal graphs, this corresponds to spacing "
|
||||
"between columns."))
|
||||
menu.add_option(category, "leveldist", leveldist)
|
||||
|
||||
################################
|
||||
category = _("Note")
|
||||
################################
|
||||
|
||||
note = TextOption(_("Note to add to the tree"), [""])
|
||||
note.set_help(_("This text will be added to the tree."))
|
||||
menu.add_option(category, "note", note)
|
||||
|
||||
noteloc = EnumeratedListOption(_("Note location"), 't')
|
||||
for item in _NOTELOC:
|
||||
noteloc.add_item(item["value"], item["name"])
|
||||
noteloc.set_help(_("Whether note will appear on top "
|
||||
"or bottom of the page."))
|
||||
menu.add_option(category, "noteloc", noteloc)
|
||||
|
||||
notesize = EnumeratedListOption(_("Note size"), 'normalsize')
|
||||
for item in _NOTESIZE:
|
||||
notesize.add_item(item["value"], item["name"])
|
||||
notesize.set_help(_("The size of note text."))
|
||||
menu.add_option(category, "notesize", notesize)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# TreeDoc
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
class TreeDoc(metaclass=ABCMeta):
|
||||
"""
|
||||
Abstract Interface for genealogy tree document generators. Output formats
|
||||
for genealogy tree reports must implement this interface to be used by the
|
||||
report system.
|
||||
"""
|
||||
@abstractmethod
|
||||
def start_tree(self, option_list):
|
||||
"""
|
||||
Write the start of a tree.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def end_tree(self):
|
||||
"""
|
||||
Write the end of a tree.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def start_subgraph(self, level, subgraph_type, family, option_list=None):
|
||||
"""
|
||||
Write the start of a subgraph.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def end_subgraph(self, level):
|
||||
"""
|
||||
Write the end of a subgraph.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def write_node(self, db, level, node_type, person, marriage_flag,
|
||||
option_list=None):
|
||||
"""
|
||||
Write the contents of a node.
|
||||
"""
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# TreeDocBase
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
class TreeDocBase(BaseDoc, TreeDoc):
|
||||
"""
|
||||
Base document generator for all Graphviz document generators. Classes that
|
||||
inherit from this class will only need to implement the close function.
|
||||
The close function will generate the actual file of the appropriate type.
|
||||
"""
|
||||
def __init__(self, options, paper_style):
|
||||
BaseDoc.__init__(self, None, paper_style)
|
||||
|
||||
self._filename = None
|
||||
self._tex = StringIO()
|
||||
self._paper = paper_style
|
||||
|
||||
get_option = options.menu.get_option_by_name
|
||||
|
||||
self.detail = get_option('detail').get_value()
|
||||
self.marriage = get_option('marriage').get_value()
|
||||
self.nodesize = get_option('nodesize').get_value()
|
||||
self.levelsize = get_option('levelsize').get_value()
|
||||
self.nodecolor = get_option('nodecolor').get_value()
|
||||
|
||||
self.timeflow = get_option('timeflow').get_value()
|
||||
self.edges = get_option('edges').get_value()
|
||||
self.leveldist = get_option('leveldist').get_value()
|
||||
|
||||
self.note = get_option('note').get_value()
|
||||
self.noteloc = get_option('noteloc').get_value()
|
||||
self.notesize = get_option('notesize').get_value()
|
||||
|
||||
def write_start(self):
|
||||
"""
|
||||
Write the start of the document.
|
||||
"""
|
||||
paper_size = self._paper.get_size()
|
||||
name = paper_size.get_name().lower()
|
||||
if name == 'custom size':
|
||||
width = str(paper_size.get_width())
|
||||
height = str(paper_size.get_width())
|
||||
paper = 'papersize={%scm,%scm}' % (width, height)
|
||||
elif name in ('a', 'b', 'c', 'd', 'e'):
|
||||
paper = 'ansi' + name + 'paper'
|
||||
else:
|
||||
paper = name + 'paper'
|
||||
|
||||
if self._paper.get_orientation() == PAPER_PORTRAIT:
|
||||
orientation = 'portrait'
|
||||
else:
|
||||
orientation = 'landscape'
|
||||
|
||||
lmargin = self._paper.get_left_margin()
|
||||
rmargin = self._paper.get_right_margin()
|
||||
tmargin = self._paper.get_top_margin()
|
||||
bmargin = self._paper.get_bottom_margin()
|
||||
if lmargin == rmargin == tmargin == bmargin:
|
||||
margin = 'margin=%scm'% lmargin
|
||||
else:
|
||||
if lmargin == rmargin:
|
||||
margin = 'hmargin=%scm' % lmargin
|
||||
else:
|
||||
margin = 'hmargin={%scm,%scm}' % (lmargin, rmargin)
|
||||
if tmargin == bmargin:
|
||||
margin += ',vmargin=%scm' % tmargin
|
||||
else:
|
||||
margin += ',vmargin={%scm,%scm}' % (tmargin, bmargin)
|
||||
|
||||
self.write(0, '\\documentclass[%s]{article}\n' % orientation)
|
||||
|
||||
self.write(0, '\\IfFileExists{libertine.sty}{\n')
|
||||
self.write(0, ' \\usepackage{libertine}\n')
|
||||
self.write(0, '}{}\n')
|
||||
|
||||
self.write(0, '\\usepackage[%s,%s]{geometry}\n' % (paper, margin))
|
||||
self.write(0, '\\usepackage[all]{genealogytree}\n')
|
||||
self.write(0, '\\usepackage{color}\n')
|
||||
self.write(0, '\\begin{document}\n')
|
||||
|
||||
if self.nodecolor == 'preferences':
|
||||
scheme = config.get('colors.scheme')
|
||||
male_bg = config.get('colors.male-dead')[scheme][1:]
|
||||
female_bg = config.get('colors.female-dead')[scheme][1:]
|
||||
neuter_bg = config.get('colors.unknown-dead')[scheme][1:]
|
||||
self.write(0, '\\definecolor{male-bg}{HTML}{%s}\n' % male_bg)
|
||||
self.write(0, '\\definecolor{female-bg}{HTML}{%s}\n' % female_bg)
|
||||
self.write(0, '\\definecolor{neuter-bg}{HTML}{%s}\n' % neuter_bg)
|
||||
|
||||
if ''.join(self.note) != '' and self.noteloc == 't':
|
||||
for line in self.note:
|
||||
self.write(0, '{\\%s %s}\\par\n' % (self.notesize, line))
|
||||
self.write(0, '\\bigskip\n')
|
||||
|
||||
self.write(0, '\\begin{tikzpicture}\n')
|
||||
|
||||
def start_tree(self, option_list):
|
||||
self.write(0, '\\genealogytree[\n')
|
||||
self.write(0, 'processing=database,\n')
|
||||
if self.marriage:
|
||||
info = self.detail + ' ' + self.marriage
|
||||
else:
|
||||
info = self.detail
|
||||
self.write(0, 'database format=%s,\n' % info)
|
||||
if self.timeflow:
|
||||
self.write(0, 'timeflow=%s,\n' % self.timeflow)
|
||||
if self.edges:
|
||||
self.write(0, 'edges=%s,\n' % self.edges)
|
||||
if self.leveldist != 5:
|
||||
self.write(0, 'level distance=%smm,\n' % self.leveldist)
|
||||
if self.nodesize != 25:
|
||||
self.write(0, 'node size=%smm,\n' % self.nodesize)
|
||||
if self.levelsize != 35:
|
||||
self.write(0, 'level size=%smm,\n' % self.levelsize)
|
||||
if self.nodecolor == 'none':
|
||||
self.write(0, 'tcbset={male/.style={},\n')
|
||||
self.write(0, ' female/.style={},\n')
|
||||
self.write(0, ' neuter/.style={}},\n')
|
||||
if self.nodecolor == 'preferences':
|
||||
self.write(0, 'tcbset={male/.style={colback=male-bg},\n')
|
||||
self.write(0, ' female/.style={colback=female-bg},\n')
|
||||
self.write(0, ' neuter/.style={colback=neuter-bg}},\n')
|
||||
|
||||
for option in option_list:
|
||||
self.write(0, '%s,\n' % option)
|
||||
|
||||
self.write(0, ']{\n')
|
||||
|
||||
def end_tree(self):
|
||||
self.write(0, '}\n')
|
||||
|
||||
def write_end(self):
|
||||
"""
|
||||
Write the end of the document.
|
||||
"""
|
||||
self.write(0, '\\end{tikzpicture}\n')
|
||||
|
||||
if ''.join(self.note) != '' and self.noteloc == 'b':
|
||||
self.write(0, '\\bigskip\n')
|
||||
for line in self.note:
|
||||
self.write(0, '\\par{\\%s %s}\n' % (self.notesize, line))
|
||||
|
||||
self.write(0, '\\end{document}\n')
|
||||
|
||||
def start_subgraph(self, level, subgraph_type, family, option_list=None):
|
||||
options = ['id=%s' % family.gramps_id]
|
||||
if option_list:
|
||||
options.extend(option_list)
|
||||
if subgraph_type == 'sandclock':
|
||||
self.write(level, 'sandclock{\n')
|
||||
else:
|
||||
self.write(level, '%s[%s]{\n' % (subgraph_type, ','.join(options)))
|
||||
|
||||
def end_subgraph(self, level):
|
||||
self.write(level, '}\n')
|
||||
|
||||
def write_node(self, db, level, node_type, person, marriage_flag,
|
||||
option_list=None):
|
||||
options = ['id=%s' % person.gramps_id]
|
||||
if option_list:
|
||||
options.extend(option_list)
|
||||
self.write(level, '%s[%s]{\n' % (node_type, ','.join(options)))
|
||||
if person.gender == Person.MALE:
|
||||
self.write(level+1, 'male,\n')
|
||||
elif person.gender == Person.FEMALE:
|
||||
self.write(level+1, 'female,\n')
|
||||
elif person.gender == Person.UNKNOWN:
|
||||
self.write(level+1, 'neuter,\n')
|
||||
name = person.get_primary_name()
|
||||
nick = name.get_nick_name()
|
||||
surn = name.get_surname()
|
||||
name_parts = [self.format_given_names(name),
|
||||
'\\nick{{{}}}'.format(nick) if nick else '',
|
||||
'\\surn{{{}}}'.format(surn) if surn else '']
|
||||
self.write(level+1, 'name = {{{}}},\n'.format(
|
||||
' '.join([e for e in name_parts if e])))
|
||||
for eventref in person.get_event_ref_list():
|
||||
if eventref.role == EventRoleType.PRIMARY:
|
||||
event = db.get_event_from_handle(eventref.ref)
|
||||
self.write_event(db, level+1, event)
|
||||
if marriage_flag:
|
||||
for handle in person.get_family_handle_list():
|
||||
family = db.get_family_from_handle(handle)
|
||||
for eventref in family.get_event_ref_list():
|
||||
if eventref.role == EventRoleType.FAMILY:
|
||||
event = db.get_event_from_handle(eventref.ref)
|
||||
self.write_event(db, level+1, event)
|
||||
for attr in person.get_attribute_list():
|
||||
if str(attr.get_type()) == 'Occupation':
|
||||
self.write(level+1, 'profession = {%s},\n' % attr.get_value())
|
||||
if str(attr.get_type()) == 'Comment':
|
||||
self.write(level+1, 'comment = {%s},\n' % attr.get_value())
|
||||
for mediaref in person.get_media_list():
|
||||
media = db.get_media_from_handle(mediaref.ref)
|
||||
path = media_path_full(db, media.get_path())
|
||||
if os.path.isfile(path):
|
||||
self.write(level+1, 'image = {%s},\n' % path)
|
||||
break # first image only
|
||||
self.write(level, '}\n')
|
||||
|
||||
def write_event(self, db, level, event):
|
||||
"""
|
||||
Write an event.
|
||||
"""
|
||||
modifier = None
|
||||
if event.type == EventType.BIRTH:
|
||||
event_type = 'birth'
|
||||
if 'died' in event.description.lower():
|
||||
modifier = 'died'
|
||||
if 'stillborn' in event.description.lower():
|
||||
modifier = 'stillborn'
|
||||
# modifier = 'out of wedlock'
|
||||
elif event.type == EventType.BAPTISM:
|
||||
event_type = 'baptism'
|
||||
elif event.type == EventType.ENGAGEMENT:
|
||||
event_type = 'engagement'
|
||||
elif event.type == EventType.MARRIAGE:
|
||||
event_type = 'marriage'
|
||||
elif event.type == EventType.DIVORCE:
|
||||
event_type = 'divorce'
|
||||
elif event.type == EventType.DEATH:
|
||||
event_type = 'death'
|
||||
elif event.type == EventType.BURIAL:
|
||||
event_type = 'burial'
|
||||
if 'killed' in event.description.lower():
|
||||
modifier = 'killed'
|
||||
elif event.type == EventType.CREMATION:
|
||||
event_type = 'burial'
|
||||
modifier = 'cremated'
|
||||
else:
|
||||
return
|
||||
|
||||
date = event.get_date_object()
|
||||
|
||||
if date.get_calendar() == Date.CAL_GREGORIAN:
|
||||
calendar = 'AD' # GR
|
||||
elif date.get_calendar() == Date.CAL_JULIAN:
|
||||
calendar = 'JU'
|
||||
else:
|
||||
calendar = ''
|
||||
|
||||
if date.get_modifier() == Date.MOD_ABOUT:
|
||||
calendar = 'ca' + calendar
|
||||
|
||||
date_str = self.format_iso(date.get_ymd(), calendar)
|
||||
if date.get_modifier() == Date.MOD_BEFORE:
|
||||
date_str = '/' + date_str
|
||||
elif date.get_modifier() == Date.MOD_AFTER:
|
||||
date_str = date_str + '/'
|
||||
elif date.is_compound():
|
||||
stop_date = self.format_iso(date.get_stop_ymd(), calendar)
|
||||
date_str = date_str + '/' + stop_date
|
||||
|
||||
place = _pd.display_event(db, event)
|
||||
|
||||
if modifier:
|
||||
event_type += '+'
|
||||
self.write(level, '%s = {%s}{%s}{%s},\n' %
|
||||
(event_type, date_str, place, modifier))
|
||||
elif place == '':
|
||||
event_type += '-'
|
||||
self.write(level, '%s = {%s},\n' % (event_type, date_str))
|
||||
else:
|
||||
self.write(level, '%s = {%s}{%s},\n' %
|
||||
(event_type, date_str, place))
|
||||
|
||||
def format_given_names(self, name):
|
||||
"""
|
||||
Format given names.
|
||||
"""
|
||||
first = name.get_first_name()
|
||||
call = name.get_call_name()
|
||||
if call:
|
||||
if call in first:
|
||||
where = first.index(call)
|
||||
return '{before}\\pref{{{call}}}{after}'.format(
|
||||
before=first[:where],
|
||||
call=call,
|
||||
after=first[where+len(call):])
|
||||
else:
|
||||
# ignore erroneous call name
|
||||
return first
|
||||
else:
|
||||
return first
|
||||
|
||||
def format_iso(self, date_tuple, calendar):
|
||||
"""
|
||||
Format an iso date.
|
||||
"""
|
||||
year, month, day = date_tuple
|
||||
if year == 0:
|
||||
iso_date = ''
|
||||
elif month == 0:
|
||||
iso_date = str(year)
|
||||
elif day == 0:
|
||||
iso_date = '%s-%s' % (year, month)
|
||||
else:
|
||||
iso_date = '%s-%s-%s' % (year, month, day)
|
||||
if calendar and calendar != 'AD':
|
||||
iso_date = '(%s)%s' % (calendar, iso_date)
|
||||
return iso_date
|
||||
|
||||
def write(self, level, text):
|
||||
"""
|
||||
Write indented text.
|
||||
"""
|
||||
self._tex.write(' '*level + text)
|
||||
|
||||
def open(self, filename):
|
||||
""" Implement TreeDocBase.open() """
|
||||
self._filename = os.path.normpath(os.path.abspath(filename))
|
||||
self.write_start()
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
This isn't useful by itself. Other classes need to override this and
|
||||
actually generate a file.
|
||||
"""
|
||||
self.write_end()
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# TreeTexDoc
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
class TreeTexDoc(TreeDocBase):
|
||||
"""
|
||||
TreeTexDoc implementation that generates a .tex file.
|
||||
"""
|
||||
|
||||
def close(self):
|
||||
""" Implements TreeDocBase.close() """
|
||||
TreeDocBase.close(self)
|
||||
|
||||
# Make sure the extension is correct
|
||||
if self._filename[-4:] != ".tex":
|
||||
self._filename += ".tex"
|
||||
|
||||
with open(self._filename, "w") as texfile:
|
||||
texfile.write(self._tex.getvalue())
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# TreePdfDoc
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
class TreePdfDoc(TreeDocBase):
|
||||
"""
|
||||
TreePdfDoc implementation that generates a .pdf file.
|
||||
"""
|
||||
|
||||
def close(self):
|
||||
""" Implements TreeDocBase.close() """
|
||||
TreeDocBase.close(self)
|
||||
|
||||
# Make sure the extension is correct
|
||||
if self._filename[-4:] != ".pdf":
|
||||
self._filename += ".pdf"
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
with open(os.path.join(tmpdir, 'temp.tex'), "w") as texfile:
|
||||
texfile.write(self._tex.getvalue())
|
||||
os.system('lualatex -output-directory %s temp.tex >/dev/null'
|
||||
% tmpdir)
|
||||
shutil.copy(os.path.join(tmpdir, 'temp.pdf'), self._filename)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Various Genealogy Tree formats.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
FORMATS = []
|
||||
|
||||
if _LATEX_FOUND:
|
||||
FORMATS += [{'type' : "pdf",
|
||||
'ext' : "pdf",
|
||||
'descr': _("PDF"),
|
||||
'mime' : "application/pdf",
|
||||
'class': TreePdfDoc}]
|
||||
|
||||
FORMATS += [{'type' : "tex",
|
||||
'ext' : "tex",
|
||||
'descr': _("LaTeX File"),
|
||||
'mime' : "application/x-latex",
|
||||
'class': TreeTexDoc}]
|
@ -495,14 +495,14 @@ class BookList:
|
||||
"""
|
||||
Saves the current BookList to the associated file.
|
||||
"""
|
||||
with open(self.file, "w") as b_f:
|
||||
with open(self.file, "w", encoding="utf-8") as b_f:
|
||||
b_f.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
||||
b_f.write('<booklist>\n')
|
||||
for name in sorted(self.bookmap): # enable a diff of archived copies
|
||||
book = self.get_book(name)
|
||||
dbname = book.get_dbname()
|
||||
dbname = escape(book.get_dbname())
|
||||
b_f.write(' <book name="%s" database="%s">'
|
||||
'\n' % (name, dbname))
|
||||
'\n' % (escape(name), dbname))
|
||||
for item in book.get_item_list():
|
||||
b_f.write(' <item name="%s" '
|
||||
'trans_name="%s">\n' % (
|
||||
@ -566,7 +566,7 @@ class BookList:
|
||||
'\n' % book.get_format_name())
|
||||
if book.get_output():
|
||||
b_f.write(' <output name="%s"/>'
|
||||
'\n' % book.get_output())
|
||||
'\n' % escape(book.get_output()))
|
||||
b_f.write(' </book>\n')
|
||||
|
||||
b_f.write('</booklist>\n')
|
||||
@ -578,8 +578,15 @@ class BookList:
|
||||
try:
|
||||
parser = make_parser()
|
||||
parser.setContentHandler(BookParser(self, self.dbase))
|
||||
with open(self.file) as the_file:
|
||||
parser.parse(the_file)
|
||||
# bug 10387; XML should be utf8, but was not previously saved
|
||||
# that way. So try to read utf8, if fails, try with system
|
||||
# encoding. Only an issue on non-utf8 systems.
|
||||
try:
|
||||
with open(self.file, encoding="utf-8") as the_file:
|
||||
parser.parse(the_file)
|
||||
except UnicodeDecodeError:
|
||||
with open(self.file) as the_file:
|
||||
parser.parse(the_file)
|
||||
except (IOError, OSError, ValueError, SAXParseException, KeyError,
|
||||
AttributeError):
|
||||
LOG.debug("Failed to parse book list", exc_info=True)
|
||||
|
@ -39,7 +39,7 @@ import os
|
||||
|
||||
# Report categories
|
||||
from .. import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE, CATEGORY_WEB,
|
||||
CATEGORY_BOOK, CATEGORY_GRAPHVIZ)
|
||||
CATEGORY_BOOK, CATEGORY_GRAPHVIZ, CATEGORY_TREE)
|
||||
|
||||
standalone_categories = {
|
||||
CATEGORY_TEXT : ("RepText", _("Text Reports")),
|
||||
@ -48,6 +48,7 @@ standalone_categories = {
|
||||
CATEGORY_WEB : ("RepWeb", _("Web Pages")),
|
||||
CATEGORY_BOOK : ("RepBook", _("Books")),
|
||||
CATEGORY_GRAPHVIZ : ("Graphs", _("Graphs")),
|
||||
CATEGORY_TREE : ("Trees", _("Trees")),
|
||||
}
|
||||
book_categories = {
|
||||
CATEGORY_TEXT : _("Text"),
|
||||
|
@ -31,6 +31,7 @@ import csv
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .tabbeddoc import *
|
||||
from ...constfunc import win
|
||||
|
||||
class CSVTab(TabbedDoc):
|
||||
|
||||
@ -48,7 +49,8 @@ class CSVTab(TabbedDoc):
|
||||
else:
|
||||
self.filename = filename
|
||||
|
||||
self.f = open(self.filename, "w")
|
||||
self.f = open(self.filename, "w",
|
||||
encoding='utf_8_sig' if win() else 'utf_8')
|
||||
self.writer = csv.writer(self.f)
|
||||
|
||||
def close(self):
|
||||
|
@ -249,13 +249,23 @@ class ConfigureDialog(ManagedWindow):
|
||||
"""
|
||||
self.__config.set(constant, obj.get_text())
|
||||
|
||||
def update_color(self, obj, constant, color_hex_label):
|
||||
def update_color(self, obj, pspec, constant, color_hex_label):
|
||||
"""
|
||||
Called on changing some color.
|
||||
Either on programmatically color change.
|
||||
"""
|
||||
rgba = obj.get_rgba()
|
||||
hexval = "#%02x%02x%02x" % (int(rgba.red * 255),
|
||||
int(rgba.green * 255),
|
||||
int(rgba.blue * 255))
|
||||
color_hex_label.set_text(hexval)
|
||||
self.__config.set(constant, hexval)
|
||||
colors = self.__config.get(constant)
|
||||
if isinstance(colors, list):
|
||||
scheme = self.__config.get('colors.scheme')
|
||||
colors[scheme] = hexval
|
||||
self.__config.set(constant, colors)
|
||||
else:
|
||||
self.__config.set(constant, hexval)
|
||||
|
||||
def update_checkbox(self, obj, constant, config=None):
|
||||
if not config:
|
||||
@ -383,15 +393,24 @@ class ConfigureDialog(ManagedWindow):
|
||||
grid.attach(entry, col_attach+1, index, 1, 1)
|
||||
|
||||
def add_color(self, grid, label, index, constant, config=None, col=0):
|
||||
"""
|
||||
Add color chooser widget with label to the grid.
|
||||
"""
|
||||
if not config:
|
||||
config = self.__config
|
||||
lwidget = BasicLabel(_("%s: ") % label) # needed for French, else ignore
|
||||
hexval = config.get(constant)
|
||||
colors = config.get(constant)
|
||||
if isinstance(colors, list):
|
||||
scheme = config.get('colors.scheme')
|
||||
hexval = colors[scheme]
|
||||
else:
|
||||
hexval = colors
|
||||
color = Gdk.color_parse(hexval)
|
||||
entry = Gtk.ColorButton(color=color)
|
||||
color_hex_label = BasicLabel(hexval)
|
||||
color_hex_label.set_hexpand(True)
|
||||
entry.connect('color-set', self.update_color, constant, color_hex_label)
|
||||
entry.connect('notify::color', self.update_color, constant,
|
||||
color_hex_label)
|
||||
grid.attach(lwidget, col, index, 1, 1)
|
||||
grid.attach(entry, col+1, index, 1, 1)
|
||||
grid.attach(color_hex_label, col+2, index, 1, 1)
|
||||
@ -554,7 +573,7 @@ class GrampsPreferences(ConfigureDialog):
|
||||
|
||||
def add_color_panel(self, configdialog):
|
||||
"""
|
||||
Add the tab to set defaults colors for graph boxes
|
||||
Add the tab to set defaults colors for graph boxes.
|
||||
"""
|
||||
grid = Gtk.Grid()
|
||||
grid.set_border_width(12)
|
||||
@ -562,40 +581,62 @@ class GrampsPreferences(ConfigureDialog):
|
||||
grid.set_row_spacing(6)
|
||||
self.add_text(grid, _('Set the colors used for boxes in the graphical views'),
|
||||
0, line_wrap=False)
|
||||
self.add_color(grid, _('Gender Male Alive'), 1,
|
||||
'preferences.color-gender-male-alive')
|
||||
self.add_color(grid, _('Border Male Alive'), 2,
|
||||
'preferences.bordercolor-gender-male-alive')
|
||||
self.add_color(grid, _('Gender Male Death'), 3,
|
||||
'preferences.color-gender-male-death')
|
||||
self.add_color(grid, _('Border Male Death'), 4,
|
||||
'preferences.bordercolor-gender-male-death')
|
||||
self.add_color(grid, _('Gender Female Alive'), 1,
|
||||
'preferences.color-gender-female-alive', col=4)
|
||||
self.add_color(grid, _('Border Female Alive'), 2,
|
||||
'preferences.bordercolor-gender-female-alive', col=4)
|
||||
self.add_color(grid, _('Gender Female Death'), 3,
|
||||
'preferences.color-gender-female-death', col=4)
|
||||
self.add_color(grid, _('Border Female Death'), 4,
|
||||
'preferences.bordercolor-gender-female-death', col=4)
|
||||
## self.add_color(grid, _('Gender Other Alive'), 5,
|
||||
## 'preferences.color-gender-other-alive')
|
||||
## self.add_color(grid, _('Border Other Alive'), 6,
|
||||
## 'preferences.bordercolor-gender-other-alive')
|
||||
## self.add_color(grid, _('Gender Other Death'), 7,
|
||||
## 'preferences.color-gender-other-death')
|
||||
## self.add_color(grid, _('Border Other Death'), 8,
|
||||
## 'preferences.bordercolor-gender-other-death')
|
||||
self.add_color(grid, _('Gender Unknown Alive'), 5,
|
||||
'preferences.color-gender-unknown-alive', col=4)
|
||||
self.add_color(grid, _('Border Unknown Alive'), 6,
|
||||
'preferences.bordercolor-gender-unknown-alive', col=4)
|
||||
self.add_color(grid, _('Gender Unknown Death'), 7,
|
||||
'preferences.color-gender-unknown-death', col=4)
|
||||
self.add_color(grid, _('Border Unknown Death'), 8,
|
||||
'preferences.bordercolor-gender-unknown-death', col=4)
|
||||
|
||||
hbox = Gtk.Box(spacing=12)
|
||||
self.color_scheme_box = Gtk.ComboBoxText()
|
||||
formats = [_("Light colors"),
|
||||
_("Dark colors"),]
|
||||
list(map(self.color_scheme_box.append_text, formats))
|
||||
scheme = config.get('colors.scheme')
|
||||
self.color_scheme_box.set_active(scheme)
|
||||
self.color_scheme_box.connect('changed', self.color_scheme_changed)
|
||||
lwidget = BasicLabel(_("%s: ") % _('Color scheme'))
|
||||
hbox.pack_start(lwidget, False, False, 0)
|
||||
hbox.pack_start(self.color_scheme_box, False, False, 0)
|
||||
|
||||
restore_btn = Gtk.Button(_('Restore to defaults'))
|
||||
restore_btn.connect('clicked', self.restore_colors)
|
||||
hbox.pack_start(restore_btn, False, False, 0)
|
||||
grid.attach(hbox, 1, 1, 6, 1)
|
||||
|
||||
color_list = [
|
||||
(_('Male Alive'), 'male-alive', 2, 0),
|
||||
(_('Male Dead'), 'male-dead', 4, 0),
|
||||
(_('Female Alive'), 'female-alive', 2, 4),
|
||||
(_('Female Dead'), 'female-dead', 4, 4),
|
||||
(_('Unknown Alive'), 'unknown-alive', 6, 4),
|
||||
(_('Unknown Dead'), 'unknown-dead', 8, 4),
|
||||
(_('Family Node'), 'family', 7, 0),
|
||||
(_('Family Divorced'), 'family-divorced', 9, 0),
|
||||
(_('Home Person'), 'home-person', 6, 0),
|
||||
(_('Border Male Alive'), 'border-male-alive', 3, 0),
|
||||
(_('Border Male Dead'), 'border-male-dead', 5, 0),
|
||||
(_('Border Female Alive'), 'border-female-alive', 3, 4),
|
||||
(_('Border Female Dead'), 'border-female-dead', 5, 4),
|
||||
(_('Border Unknown Alive'), 'border-unknown-alive', 7, 4),
|
||||
(_('Border Unknown Dead'), 'border-unknown-dead', 9, 4),
|
||||
(_('Border Family'), 'border-family', 8, 0),
|
||||
(_('Border Family Divorced'), 'border-family-divorced', 10, 0),
|
||||
]
|
||||
|
||||
self.colors = {}
|
||||
for color in color_list:
|
||||
pref_name = 'colors.' + color[1]
|
||||
self.colors[pref_name] = self.add_color(grid, color[0], color[2],
|
||||
pref_name, col=color[3])
|
||||
return _('Colors'), grid
|
||||
|
||||
def restore_colors(self, widget=None):
|
||||
"""
|
||||
Restore colors of selected scheme to default.
|
||||
"""
|
||||
scheme = config.get('colors.scheme')
|
||||
for key, widget in self.colors.items():
|
||||
color = Gdk.RGBA()
|
||||
hexval = config.get_default(key)[scheme]
|
||||
Gdk.RGBA.parse(color, hexval)
|
||||
widget.set_rgba(color)
|
||||
|
||||
def add_advanced_panel(self, configdialog):
|
||||
grid = Gtk.Grid()
|
||||
grid.set_border_width(12)
|
||||
@ -1205,6 +1246,18 @@ class GrampsPreferences(ConfigureDialog):
|
||||
self.old_format = the_list.get_value(the_iter, COL_FMT)
|
||||
win = DisplayNameEditor(self.uistate, self.dbstate, self.track, self)
|
||||
|
||||
def color_scheme_changed(self, obj):
|
||||
"""
|
||||
Called on swiching color scheme.
|
||||
"""
|
||||
scheme = obj.get_active()
|
||||
config.set('colors.scheme', scheme)
|
||||
for key, widget in self.colors.items():
|
||||
color = Gdk.RGBA()
|
||||
hexval = config.get(key)[scheme]
|
||||
Gdk.RGBA.parse(color, hexval)
|
||||
widget.set_rgba(color)
|
||||
|
||||
def check_for_type_changed(self, obj):
|
||||
active = obj.get_active()
|
||||
if active == 0: # update
|
||||
|
@ -35,6 +35,7 @@ _LOG = logging.getLogger(".dialog")
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -46,6 +47,7 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.const import ICON, URL_BUGHOME
|
||||
from gramps.gen.config import config
|
||||
from gramps.gen.constfunc import is_quartz
|
||||
from .glade import Glade
|
||||
from .display import display_url
|
||||
|
||||
@ -506,6 +508,12 @@ def main(args):
|
||||
win = Gtk.Window()
|
||||
win.set_title('Dialog test window')
|
||||
win.set_position(Gtk.WindowPosition.CENTER)
|
||||
#Set the mnemonic modifier on Macs to alt-ctrl so that it
|
||||
#doesn't interfere with the extended keyboard, see
|
||||
#https://gramps-project.org/bugs/view.php?id=6943
|
||||
if is_quartz():
|
||||
win.set_mnemonic_modifier(
|
||||
Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)
|
||||
def cb(window, event):
|
||||
Gtk.main_quit()
|
||||
win.connect('delete-event', cb)
|
||||
|
@ -42,6 +42,7 @@ from gi.repository import Pango
|
||||
# Gramps classes
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from ...widgets.cellrenderertextedit import CellRendererTextEdit
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from ...utils import is_right_click
|
||||
@ -482,7 +483,10 @@ class EmbeddedList(ButtonTab):
|
||||
type_col = self._column_names[pair[1]][3]
|
||||
|
||||
if (type_col in [TEXT_COL, MARKUP_COL, TEXT_EDIT_COL]):
|
||||
renderer = Gtk.CellRendererText()
|
||||
if type_col == TEXT_EDIT_COL:
|
||||
renderer = CellRendererTextEdit()
|
||||
else:
|
||||
renderer = Gtk.CellRendererText()
|
||||
renderer.set_property('ellipsize', Pango.EllipsizeMode.END)
|
||||
if type_col == TEXT_COL or type_col == TEXT_EDIT_COL:
|
||||
column = Gtk.TreeViewColumn(name, renderer, text=pair[1])
|
||||
@ -519,9 +523,12 @@ class EmbeddedList(ButtonTab):
|
||||
# insert the colum into the tree
|
||||
column.set_resizable(True)
|
||||
column.set_clickable(True)
|
||||
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
|
||||
#column.set_min_width(self._column_names[pair[1]][2])
|
||||
column.set_fixed_width(self._column_names[pair[1]][2])
|
||||
if self._column_names[pair[1]][2] != -1:
|
||||
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
|
||||
#column.set_min_width(self._column_names[pair[1]][2])
|
||||
column.set_fixed_width(self._column_names[pair[1]][2])
|
||||
else:
|
||||
column.set_expand(True)
|
||||
|
||||
column.set_sort_column_id(self._column_names[pair[1]][1])
|
||||
self.columns.append(column)
|
||||
|
@ -45,7 +45,7 @@ _ENTER = Gdk.keyval_from_name("Enter")
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from .surnamemodel import SurnameModel
|
||||
from .embeddedlist import EmbeddedList, TEXT_COL, MARKUP_COL, ICON_COL
|
||||
from .embeddedlist import EmbeddedList, TEXT_EDIT_COL
|
||||
from ...ddtargets import DdTargets
|
||||
from gramps.gen.lib import Surname, NameOriginType
|
||||
from ...utils import get_primary_mask
|
||||
@ -71,9 +71,9 @@ class SurnameTab(EmbeddedList):
|
||||
#index = column in model. Value =
|
||||
# (name, sortcol in model, width, markup/text
|
||||
_column_names = [
|
||||
(_('Prefix'), -1, 150, TEXT_COL, -1, None),
|
||||
(_('Surname'), -1, 250, TEXT_COL, -1, None),
|
||||
(_('Connector'), -1, 100, TEXT_COL, -1, None),
|
||||
(_('Prefix'), 0, 150, TEXT_EDIT_COL, -1, None),
|
||||
(_('Surname'), 1, -1, TEXT_EDIT_COL, -1, None),
|
||||
(_('Connector'), 2, 100, TEXT_EDIT_COL, -1, None),
|
||||
]
|
||||
_column_combo = (_('Origin'), -1, 150, 3) # name, sort, width, modelcol
|
||||
_column_toggle = (_('Name|Primary'), -1, 80, 4)
|
||||
@ -94,14 +94,6 @@ class SurnameTab(EmbeddedList):
|
||||
#first the standard text columns with normal method
|
||||
EmbeddedList.build_columns(self)
|
||||
|
||||
# Need to add attributes to renderers
|
||||
# and connect renderers to the 'edited' signal
|
||||
for colno in range(len(self.columns)):
|
||||
for renderer in self.columns[colno].get_cells():
|
||||
renderer.set_property('editable', not self.dbstate.db.readonly)
|
||||
renderer.connect('editing_started', self.on_edit_start, colno)
|
||||
renderer.connect('edited', self.on_edit_inline, self.column_order()[colno][1])
|
||||
|
||||
# now we add the two special columns
|
||||
# combobox for type
|
||||
colno = len(self.columns)
|
||||
@ -133,7 +125,7 @@ class SurnameTab(EmbeddedList):
|
||||
column.set_resizable(True)
|
||||
column.set_sort_column_id(self._column_combo[1])
|
||||
column.set_min_width(self._column_combo[2])
|
||||
column.set_expand(True)
|
||||
column.set_expand(False)
|
||||
self.columns.append(column)
|
||||
self.tree.append_column(column)
|
||||
# toggle box for primary
|
||||
@ -149,7 +141,7 @@ class SurnameTab(EmbeddedList):
|
||||
column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
|
||||
column.set_alignment(0.5)
|
||||
column.set_sort_column_id(self._column_toggle[1])
|
||||
column.set_min_width(self._column_toggle[2])
|
||||
column.set_max_width(self._column_toggle[2])
|
||||
self.columns.append(column)
|
||||
self.tree.append_column(column)
|
||||
|
||||
@ -161,6 +153,24 @@ class SurnameTab(EmbeddedList):
|
||||
## svalue = self.cmborigmap[second]
|
||||
## return glocale.strcoll(fvalue, svalue)
|
||||
|
||||
def setup_editable_col(self):
|
||||
"""
|
||||
inherit this and set the variables needed for editable columns
|
||||
Variable edit_col_funcs needs to be a dictionary from model col_nr to
|
||||
function to call for
|
||||
Example:
|
||||
self.edit_col_funcs ={1: {'edit_start': self.on_edit_start,
|
||||
'edited': self.on_edited
|
||||
}}
|
||||
"""
|
||||
self.edit_col_funcs = {
|
||||
0: {'edit_start': self.on_edit_start,
|
||||
'edited': self.on_edit_inline},
|
||||
1: {'edit_start': self.on_edit_start,
|
||||
'edited': self.on_edit_inline},
|
||||
2: {'edit_start': self.on_edit_start,
|
||||
'edited': self.on_edit_inline}}
|
||||
|
||||
def get_data(self):
|
||||
return self.obj.get_surname_list()
|
||||
|
||||
@ -194,6 +204,16 @@ class SurnameTab(EmbeddedList):
|
||||
if self.on_change:
|
||||
self.on_change()
|
||||
|
||||
def post_rebuild(self, prebuildpath):
|
||||
"""
|
||||
Called when data model has changed, in particular necessary when row
|
||||
order is updated.
|
||||
@param prebuildpath: path selected before rebuild, None if none
|
||||
@type prebuildpath: tree path
|
||||
"""
|
||||
if self.on_change:
|
||||
self.on_change()
|
||||
|
||||
def column_order(self):
|
||||
# order of columns for EmbeddedList. Only the text columns here
|
||||
return ((1, 0), (1, 1), (1, 2))
|
||||
@ -239,11 +259,13 @@ class SurnameTab(EmbeddedList):
|
||||
"""
|
||||
self.on_edit_start(cellr, celle, path, colnr)
|
||||
#set up autocomplete
|
||||
entry = celle.get_child()
|
||||
entry.set_width_chars(10)
|
||||
completion = Gtk.EntryCompletion()
|
||||
completion.set_model(self.cmborig)
|
||||
completion.set_minimum_key_length(1)
|
||||
completion.set_text_column(1)
|
||||
celle.get_child().set_completion(completion)
|
||||
entry.set_completion(completion)
|
||||
#
|
||||
celle.connect('changed', self.on_origcmb_change, path, colnr)
|
||||
|
||||
|
@ -197,9 +197,6 @@ class EditPerson(EditPrimary):
|
||||
self.singsurnfr = SingSurn(self.top)
|
||||
self.multsurnfr = self.top.get_object("hboxmultsurnames")
|
||||
self.singlesurn_active = True
|
||||
self.surntab = SurnameTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_primary_name(),
|
||||
on_change=self._changed_name)
|
||||
|
||||
self.set_contexteventbox(self.top.get_object("eventboxtop"))
|
||||
|
||||
@ -445,6 +442,9 @@ class EditPerson(EditPrimary):
|
||||
|
||||
self.preview_name = self.top.get_object("full_name")
|
||||
self.preview_name.override_font(Pango.FontDescription('sans bold 12'))
|
||||
self.surntab = SurnameTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_primary_name(),
|
||||
on_change=self._changed_name)
|
||||
|
||||
def get_start_date(self):
|
||||
"""
|
||||
@ -936,7 +936,8 @@ class EditPerson(EditPrimary):
|
||||
msurhbox = self.top.get_object("hboxmultsurnames")
|
||||
msurhbox.remove(self.surntab)
|
||||
self.surntab = SurnameTab(self.dbstate, self.uistate, self.track,
|
||||
self.obj.get_primary_name())
|
||||
self.obj.get_primary_name(),
|
||||
on_change=self._changed_name)
|
||||
self.multsurnfr.set_size_request(-1,
|
||||
int(config.get('interface.surname-box-height')))
|
||||
msurhbox.pack_start(self.surntab, True, True, 0)
|
||||
|
@ -46,6 +46,7 @@ from gi.repository import Gtk
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gramps.gen.const import GLADE_DIR, GRAMPS_LOCALE as glocale
|
||||
from gramps.gen.constfunc import is_quartz
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -142,11 +143,19 @@ class Glade(Gtk.Builder):
|
||||
# toplevel is given
|
||||
if toplevel:
|
||||
loadlist = [toplevel] + also_load
|
||||
self.add_objects_from_file(path, loadlist)
|
||||
with open(path, 'r', encoding='utf-8') as builder_file:
|
||||
data = builder_file.read().replace('\n', '')
|
||||
if is_quartz():
|
||||
data = data.replace('GDK_CONTROL_MASK', 'GDK_META_MASK')
|
||||
self.add_objects_from_string(data, loadlist)
|
||||
self.__toplevel = self.get_object(toplevel)
|
||||
# toplevel not given
|
||||
else:
|
||||
self.add_from_file(path)
|
||||
with open(path, 'r', encoding='utf-8') as builder_file:
|
||||
data = builder_file.read().replace('\n', '')
|
||||
if is_quartz():
|
||||
data = data.replace('GDK_CONTROL_MASK', 'GDK_META_MASK')
|
||||
self.add_from_string(data)
|
||||
# first, use filename as possible toplevel widget name
|
||||
self.__toplevel = self.get_object(filename.rpartition('.')[0])
|
||||
|
||||
|
@ -197,7 +197,7 @@
|
||||
<child>
|
||||
<object class="GtkComboBox" id="confidence">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Conveys the submitter's quantitative evaluation of the credibility of a piece of information, based upon its supporting evidence. It is not intended to eliminate the receiver's need to evaluate the evidence for themselves.
|
||||
Very Low =Unreliable evidence or estimated data
|
||||
Low =Questionable reliability of evidence (interviews, census, oral genealogies, or potential for bias for example, an autobiography)
|
||||
|
@ -38,6 +38,7 @@ from io import StringIO
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -47,6 +48,7 @@ from gi.repository import Gtk
|
||||
from gramps.gen.const import GLADE_FILE, ICON
|
||||
from gramps.gen.errors import WindowActiveError
|
||||
from gramps.gen.config import config
|
||||
from gramps.gen.constfunc import is_quartz
|
||||
from .glade import Glade
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -488,6 +490,13 @@ class ManagedWindow:
|
||||
#closing the Gtk.Window must also close ManagedWindow
|
||||
self.window = window
|
||||
self.window.connect('delete-event', self.close)
|
||||
#Set the mnemonic modifier on Macs to alt-ctrl so that it
|
||||
#doesn't interfere with the extended keyboard, see
|
||||
#https://gramps-project.org/bugs/view.php?id=6943
|
||||
if is_quartz():
|
||||
self.window.set_mnemonic_modifier(
|
||||
Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)
|
||||
|
||||
if self.modal:
|
||||
self.window.set_modal(True)
|
||||
# The following makes sure that we only have one modal window open;
|
||||
|
@ -684,7 +684,7 @@ class BookSelector(ManagedWindow):
|
||||
old_margins = self.book.get_margins()
|
||||
old_format_name = self.book.get_format_name()
|
||||
old_output = self.book.get_output()
|
||||
BookDialog(self.dbstate, self.uistate, self.book, BookOptions)
|
||||
BookDialog(self.dbstate, self.uistate, self.book, BookOptions, track=self.track)
|
||||
new_paper_name = self.book.get_paper_name()
|
||||
new_orientation = self.book.get_orientation()
|
||||
new_paper_metric = self.book.get_paper_metric()
|
||||
@ -918,7 +918,7 @@ class BookDialog(DocReportDialog):
|
||||
Create a dialog selecting target, format, and paper/HTML options.
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, book, options):
|
||||
def __init__(self, dbstate, uistate, book, options, track=[]):
|
||||
self.format_menu = None
|
||||
self.options = options
|
||||
self.page_html_added = False
|
||||
@ -926,7 +926,7 @@ class BookDialog(DocReportDialog):
|
||||
self.title = _('Generate Book')
|
||||
self.database = dbstate.db
|
||||
DocReportDialog.__init__(self, dbstate, uistate, options,
|
||||
'book', self.title)
|
||||
'book', self.title, track=track)
|
||||
self.options.options_dict['bookname'] = self.book.get_name()
|
||||
|
||||
response = self.window.run()
|
||||
|
@ -63,7 +63,7 @@ class DocReportDialog(ReportDialog):
|
||||
dialogs for docgen derived reports.
|
||||
"""
|
||||
|
||||
def __init__(self, dbstate, uistate, option_class, name, trans_name):
|
||||
def __init__(self, dbstate, uistate, option_class, name, trans_name, track=[]):
|
||||
"""Initialize a dialog to request that the user select options
|
||||
for a basic *stand-alone* report."""
|
||||
|
||||
@ -72,7 +72,7 @@ class DocReportDialog(ReportDialog):
|
||||
self.css = PLUGMAN.process_plugin_data('WEBSTUFF')
|
||||
self.dbname = dbstate.db.get_dbname()
|
||||
ReportDialog.__init__(self, dbstate, uistate, option_class,
|
||||
name, trans_name)
|
||||
name, trans_name, track=track)
|
||||
|
||||
self.basedocname = None # keep pylint happy
|
||||
self.css_filename = None
|
||||
|
289
gramps/gui/plug/report/_graphreportdialog.py
Normal file
289
gramps/gui/plug/report/_graphreportdialog.py
Normal file
@ -0,0 +1,289 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2007-2008 Brian G. Matherly
|
||||
# Copyright (C) 2007-2009 Stephane Charette
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
# Contribution 2009 by Bob Ham <rah@bash.sh>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2012-2013 Paul Franklin
|
||||
# Copyright (C) 2017 Nick Hall
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""base class for generating dialogs for graph-based reports """
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GTK+ modules
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.config import config
|
||||
from gramps.gen.plug.report import CATEGORY_GRAPHVIZ
|
||||
from ._reportdialog import ReportDialog
|
||||
from ._papermenu import PaperFrame
|
||||
import gramps.gen.plug.docgen.graphdoc as graphdoc
|
||||
from gramps.gen.plug.menu import Menu
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GraphvizFormatComboBox
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
class BaseFormatComboBox(Gtk.ComboBox):
|
||||
"""
|
||||
Combo box base class for graph-based report format choices.
|
||||
"""
|
||||
FORMATS = []
|
||||
|
||||
def set(self, active=None):
|
||||
""" initialize the Graphviz choices """
|
||||
store = Gtk.ListStore(GObject.TYPE_STRING)
|
||||
self.set_model(store)
|
||||
cell = Gtk.CellRendererText()
|
||||
self.pack_start(cell, True)
|
||||
self.add_attribute(cell, 'text', 0)
|
||||
|
||||
index = 0
|
||||
active_index = 0
|
||||
for item in self.FORMATS:
|
||||
name = item["descr"]
|
||||
store.append(row=[name])
|
||||
if item['type'] == active:
|
||||
active_index = index
|
||||
index += 1
|
||||
self.set_active(active_index)
|
||||
|
||||
def get_label(self):
|
||||
""" get the format description """
|
||||
return self.FORMATS[self.get_active()]["descr"]
|
||||
|
||||
def get_reference(self):
|
||||
""" get the format class """
|
||||
return self.FORMATS[self.get_active()]["class"]
|
||||
|
||||
def get_ext(self):
|
||||
""" get the format extension """
|
||||
return '.%s' % self.FORMATS[self.get_active()]['ext']
|
||||
|
||||
def get_clname(self):
|
||||
""" get the report's output format type"""
|
||||
return self.FORMATS[self.get_active()]["type"]
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
#
|
||||
# GraphReportDialog
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
class GraphReportDialog(ReportDialog, metaclass=ABCMeta):
|
||||
"""A base class of ReportDialog customized for graph-based reports."""
|
||||
|
||||
def __init__(self, dbstate, uistate, opt, name, translated_name):
|
||||
"""Initialize a dialog to request that the user select options
|
||||
for a Graphviz report. See the ReportDialog class for
|
||||
more information."""
|
||||
self.category = self.get_category()
|
||||
self._goptions = self.get_options()
|
||||
self.dbname = dbstate.db.get_dbname()
|
||||
ReportDialog.__init__(self, dbstate, uistate, opt,
|
||||
name, translated_name)
|
||||
|
||||
self.doc = None # keep pylint happy
|
||||
self.format = None
|
||||
self.paper_label = None
|
||||
|
||||
def init_options(self, option_class):
|
||||
try:
|
||||
if issubclass(option_class, object): # Old-style class
|
||||
self.options = option_class(self.raw_name,
|
||||
self.dbstate.get_database())
|
||||
except TypeError:
|
||||
self.options = option_class
|
||||
|
||||
menu = Menu()
|
||||
self._goptions.add_menu_options(menu)
|
||||
|
||||
for category in menu.get_categories():
|
||||
for name in menu.get_option_names(category):
|
||||
option = menu.get_option(category, name)
|
||||
self.options.add_menu_option(category, name, option)
|
||||
|
||||
self.options.load_previous_values()
|
||||
|
||||
def init_interface(self):
|
||||
ReportDialog.init_interface(self)
|
||||
self.doc_type_changed(self.format_menu)
|
||||
self.notebook.set_current_page(1) # don't start on "Paper Options"
|
||||
|
||||
def setup_format_frame(self):
|
||||
"""Set up the format frame of the dialog."""
|
||||
self.make_doc_menu()
|
||||
self.format_menu.set(self.options.handler.get_format_name())
|
||||
self.format_menu.connect('changed', self.doc_type_changed)
|
||||
label = Gtk.Label(label=_("%s:") % _("Output Format"))
|
||||
label.set_halign(Gtk.Align.START)
|
||||
self.grid.attach(label, 1, self.row, 1, 1)
|
||||
self.format_menu.set_hexpand(True)
|
||||
self.grid.attach(self.format_menu, 2, self.row, 2, 1)
|
||||
self.row += 1
|
||||
|
||||
self.open_with_app = Gtk.CheckButton(
|
||||
label=_("Open with default viewer"))
|
||||
self.open_with_app.set_active(
|
||||
config.get('interface.open-with-default-viewer'))
|
||||
self.grid.attach(self.open_with_app, 2, self.row, 2, 1)
|
||||
self.row += 1
|
||||
|
||||
ext = self.format_menu.get_ext()
|
||||
if ext is None:
|
||||
ext = ""
|
||||
else:
|
||||
spath = self.get_default_directory()
|
||||
if self.options.get_output():
|
||||
base = os.path.basename(self.options.get_output())
|
||||
else:
|
||||
if self.dbname is None:
|
||||
default_name = self.raw_name
|
||||
else:
|
||||
default_name = self.dbname + "_" + self.raw_name
|
||||
base = "%s%s" % (default_name, ext) # "ext" already has a dot
|
||||
spath = os.path.normpath(os.path.join(spath, base))
|
||||
self.target_fileentry.set_filename(spath)
|
||||
|
||||
def setup_report_options_frame(self):
|
||||
self.paper_label = Gtk.Label(label='<b>%s</b>' % _("Paper Options"))
|
||||
self.paper_label.set_use_markup(True)
|
||||
handler = self.options.handler
|
||||
self.paper_frame = PaperFrame(
|
||||
handler.get_paper_metric(),
|
||||
handler.get_paper_name(),
|
||||
handler.get_orientation(),
|
||||
handler.get_margins(),
|
||||
handler.get_custom_paper_size())
|
||||
self.notebook.insert_page(self.paper_frame, self.paper_label, 0)
|
||||
self.paper_frame.show_all()
|
||||
|
||||
ReportDialog.setup_report_options_frame(self)
|
||||
|
||||
def doc_type_changed(self, obj):
|
||||
"""
|
||||
This routine is called when the user selects a new file
|
||||
format for the report. It adjusts the various dialog sections
|
||||
to reflect the appropriate values for the currently selected
|
||||
file format. For example, a HTML document doesn't need any
|
||||
paper size/orientation options, but it does need a template
|
||||
file. Those changes are made here.
|
||||
"""
|
||||
self.open_with_app.set_sensitive(True)
|
||||
|
||||
fname = self.target_fileentry.get_full_path(0)
|
||||
(spath, ext) = os.path.splitext(fname)
|
||||
|
||||
ext_val = obj.get_ext()
|
||||
if ext_val:
|
||||
fname = spath + ext_val
|
||||
else:
|
||||
fname = spath
|
||||
self.target_fileentry.set_filename(fname)
|
||||
|
||||
def make_document(self):
|
||||
"""Create a document of the type requested by the user.
|
||||
"""
|
||||
pstyle = self.paper_frame.get_paper_style()
|
||||
|
||||
self.doc = self.format(self.options, pstyle)
|
||||
|
||||
self.options.set_document(self.doc)
|
||||
|
||||
def on_ok_clicked(self, obj):
|
||||
"""The user is satisfied with the dialog choices. Validate
|
||||
the output file name before doing anything else. If there is
|
||||
a file name, gather the options and create the report."""
|
||||
|
||||
# Is there a filename? This should also test file permissions, etc.
|
||||
if not self.parse_target_frame():
|
||||
self.window.run()
|
||||
|
||||
# Preparation
|
||||
self.parse_format_frame()
|
||||
self.parse_user_options()
|
||||
|
||||
self.options.handler.set_paper_metric(
|
||||
self.paper_frame.get_paper_metric())
|
||||
self.options.handler.set_paper_name(
|
||||
self.paper_frame.get_paper_name())
|
||||
self.options.handler.set_orientation(
|
||||
self.paper_frame.get_orientation())
|
||||
self.options.handler.set_margins(
|
||||
self.paper_frame.get_paper_margins())
|
||||
self.options.handler.set_custom_paper_size(
|
||||
self.paper_frame.get_custom_paper_size())
|
||||
|
||||
# Create the output document.
|
||||
self.make_document()
|
||||
|
||||
# Save options
|
||||
self.options.handler.save_options()
|
||||
config.set('interface.open-with-default-viewer',
|
||||
self.open_with_app.get_active())
|
||||
|
||||
def parse_format_frame(self):
|
||||
"""Parse the format frame of the dialog. Save the user
|
||||
selected output format for later use."""
|
||||
self.format = self.format_menu.get_reference()
|
||||
format_name = self.format_menu.get_clname()
|
||||
self.options.handler.set_format_name(format_name)
|
||||
|
||||
def setup_style_frame(self):
|
||||
"""Required by ReportDialog"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def make_doc_menu(self):
|
||||
"""
|
||||
Build a menu of document types that are appropriate for
|
||||
this graph report.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_category(self):
|
||||
"""
|
||||
Return the report category.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_options(self):
|
||||
"""
|
||||
Return the graph options.
|
||||
"""
|
@ -1,12 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2007-2008 Brian G. Matherly
|
||||
# Copyright (C) 2007-2009 Stephane Charette
|
||||
# Copyright (C) 2009 Gary Burton
|
||||
# Contribution 2009 by Bob Ham <rah@bash.sh>
|
||||
# Copyright (C) 2010 Jakim Friant
|
||||
# Copyright (C) 2012-2013 Paul Franklin
|
||||
# Copyright (C) 2017 Nick Hall
|
||||
#
|
||||
# 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
|
||||
@ -23,174 +18,42 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
""" a ReportDialog customized for Graphviz-based reports """
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# python modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GTK+ modules
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
"""class for generating dialogs for graphviz-based reports """
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.config import config
|
||||
from ._graphreportdialog import GraphReportDialog, BaseFormatComboBox
|
||||
from gramps.gen.plug.report import CATEGORY_GRAPHVIZ
|
||||
from ._reportdialog import ReportDialog
|
||||
from ._papermenu import PaperFrame
|
||||
import gramps.gen.plug.docgen.graphdoc as graphdoc
|
||||
from gramps.gen.plug.menu import Menu
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GraphvizFormatComboBox
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
class GraphvizFormatComboBox(Gtk.ComboBox):
|
||||
"""
|
||||
Combo box class for Graphviz report format choices.
|
||||
"""
|
||||
def set(self, active=None):
|
||||
""" initialize the Graphviz choices """
|
||||
store = Gtk.ListStore(GObject.TYPE_STRING)
|
||||
self.set_model(store)
|
||||
cell = Gtk.CellRendererText()
|
||||
self.pack_start(cell, True)
|
||||
self.add_attribute(cell, 'text', 0)
|
||||
|
||||
index = 0
|
||||
active_index = 0
|
||||
for item in graphdoc.FORMATS:
|
||||
name = item["descr"]
|
||||
store.append(row=[name])
|
||||
if item['type'] == active:
|
||||
active_index = index
|
||||
index += 1
|
||||
self.set_active(active_index)
|
||||
|
||||
def get_label(self):
|
||||
""" get the format description """
|
||||
return graphdoc.FORMATS[self.get_active()]["descr"]
|
||||
|
||||
def get_reference(self):
|
||||
""" get the format class """
|
||||
return graphdoc.FORMATS[self.get_active()]["class"]
|
||||
|
||||
def get_ext(self):
|
||||
""" get the format extension """
|
||||
return '.%s' % graphdoc.FORMATS[self.get_active()]['ext']
|
||||
|
||||
def get_clname(self):
|
||||
""" get the report's output format type"""
|
||||
return graphdoc.FORMATS[self.get_active()]["type"]
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
#
|
||||
# GraphvizReportDialog
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
class GraphvizReportDialog(ReportDialog):
|
||||
"""A class of ReportDialog customized for Graphviz-based reports."""
|
||||
class GraphvizReportDialog(GraphReportDialog):
|
||||
|
||||
def __init__(self, dbstate, uistate, opt, name, translated_name):
|
||||
"""Initialize a dialog to request that the user select options
|
||||
for a Graphviz report. See the ReportDialog class for
|
||||
more information."""
|
||||
self.category = CATEGORY_GRAPHVIZ
|
||||
self.__gvoptions = graphdoc.GVOptions()
|
||||
self.dbname = dbstate.db.get_dbname()
|
||||
ReportDialog.__init__(self, dbstate, uistate, opt,
|
||||
name, translated_name)
|
||||
|
||||
self.doc = None # keep pylint happy
|
||||
self.format = None
|
||||
self.paper_label = None
|
||||
|
||||
def init_options(self, option_class):
|
||||
try:
|
||||
if issubclass(option_class, object): # Old-style class
|
||||
self.options = option_class(self.raw_name,
|
||||
self.dbstate.get_database())
|
||||
except TypeError:
|
||||
self.options = option_class
|
||||
|
||||
menu = Menu()
|
||||
self.__gvoptions.add_menu_options(menu)
|
||||
|
||||
for category in menu.get_categories():
|
||||
for name in menu.get_option_names(category):
|
||||
option = menu.get_option(category, name)
|
||||
self.options.add_menu_option(category, name, option)
|
||||
|
||||
self.options.load_previous_values()
|
||||
|
||||
def init_interface(self):
|
||||
ReportDialog.init_interface(self)
|
||||
self.doc_type_changed(self.format_menu)
|
||||
self.notebook.set_current_page(1) # don't start on "Paper Options"
|
||||
|
||||
def setup_format_frame(self):
|
||||
"""Set up the format frame of the dialog."""
|
||||
def make_doc_menu(self):
|
||||
"""
|
||||
Build a menu of document types that are appropriate for
|
||||
this graph report.
|
||||
"""
|
||||
self.format_menu = GraphvizFormatComboBox()
|
||||
self.format_menu.set(self.options.handler.get_format_name())
|
||||
self.format_menu.connect('changed', self.doc_type_changed)
|
||||
label = Gtk.Label(label=_("%s:") % _("Output Format"))
|
||||
label.set_halign(Gtk.Align.START)
|
||||
self.grid.attach(label, 1, self.row, 1, 1)
|
||||
self.format_menu.set_hexpand(True)
|
||||
self.grid.attach(self.format_menu, 2, self.row, 2, 1)
|
||||
self.row += 1
|
||||
|
||||
self.open_with_app = Gtk.CheckButton(
|
||||
label=_("Open with default viewer"))
|
||||
self.open_with_app.set_active(
|
||||
config.get('interface.open-with-default-viewer'))
|
||||
self.grid.attach(self.open_with_app, 2, self.row, 2, 1)
|
||||
self.row += 1
|
||||
def get_category(self):
|
||||
"""
|
||||
Return the report category.
|
||||
"""
|
||||
return CATEGORY_GRAPHVIZ
|
||||
|
||||
ext = self.format_menu.get_ext()
|
||||
if ext is None:
|
||||
ext = ""
|
||||
else:
|
||||
spath = self.get_default_directory()
|
||||
if self.options.get_output():
|
||||
base = os.path.basename(self.options.get_output())
|
||||
else:
|
||||
if self.dbname is None:
|
||||
default_name = self.raw_name
|
||||
else:
|
||||
default_name = self.dbname + "_" + self.raw_name
|
||||
base = "%s%s" % (default_name, ext) # "ext" already has a dot
|
||||
spath = os.path.normpath(os.path.join(spath, base))
|
||||
self.target_fileentry.set_filename(spath)
|
||||
|
||||
def setup_report_options_frame(self):
|
||||
self.paper_label = Gtk.Label(label='<b>%s</b>' % _("Paper Options"))
|
||||
self.paper_label.set_use_markup(True)
|
||||
handler = self.options.handler
|
||||
self.paper_frame = PaperFrame(
|
||||
handler.get_paper_metric(),
|
||||
handler.get_paper_name(),
|
||||
handler.get_orientation(),
|
||||
handler.get_margins(),
|
||||
handler.get_custom_paper_size())
|
||||
self.notebook.insert_page(self.paper_frame, self.paper_label, 0)
|
||||
self.paper_frame.show_all()
|
||||
|
||||
ReportDialog.setup_report_options_frame(self)
|
||||
def get_options(self):
|
||||
"""
|
||||
Return the graph options.
|
||||
"""
|
||||
return graphdoc.GVOptions()
|
||||
|
||||
def doc_type_changed(self, obj):
|
||||
"""
|
||||
@ -201,84 +64,31 @@ class GraphvizReportDialog(ReportDialog):
|
||||
paper size/orientation options, but it does need a template
|
||||
file. Those changes are made here.
|
||||
"""
|
||||
self.open_with_app.set_sensitive(True)
|
||||
|
||||
fname = self.target_fileentry.get_full_path(0)
|
||||
(spath, ext) = os.path.splitext(fname)
|
||||
|
||||
ext_val = obj.get_ext()
|
||||
if ext_val:
|
||||
fname = spath + ext_val
|
||||
else:
|
||||
fname = spath
|
||||
self.target_fileentry.set_filename(fname)
|
||||
GraphReportDialog.doc_type_changed(self, obj)
|
||||
|
||||
output_format_str = obj.get_clname()
|
||||
if output_format_str in ['gvpdf', 'gspdf', 'ps']:
|
||||
# Always use 72 DPI for PostScript and PDF files.
|
||||
self.__gvoptions.dpi.set_value(72)
|
||||
self.__gvoptions.dpi.set_available(False)
|
||||
self._goptions.dpi.set_value(72)
|
||||
self._goptions.dpi.set_available(False)
|
||||
else:
|
||||
self.__gvoptions.dpi.set_available(True)
|
||||
self._goptions.dpi.set_available(True)
|
||||
|
||||
if output_format_str in ['gspdf', 'dot']:
|
||||
# Multiple pages only valid for dot and PDF via GhostsScript.
|
||||
self.__gvoptions.h_pages.set_available(True)
|
||||
self.__gvoptions.v_pages.set_available(True)
|
||||
self._goptions.h_pages.set_available(True)
|
||||
self._goptions.v_pages.set_available(True)
|
||||
else:
|
||||
self.__gvoptions.h_pages.set_value(1)
|
||||
self.__gvoptions.v_pages.set_value(1)
|
||||
self.__gvoptions.h_pages.set_available(False)
|
||||
self.__gvoptions.v_pages.set_available(False)
|
||||
self._goptions.h_pages.set_value(1)
|
||||
self._goptions.v_pages.set_value(1)
|
||||
self._goptions.h_pages.set_available(False)
|
||||
self._goptions.v_pages.set_available(False)
|
||||
|
||||
def make_document(self):
|
||||
"""Create a document of the type requested by the user.
|
||||
"""
|
||||
pstyle = self.paper_frame.get_paper_style()
|
||||
|
||||
self.doc = self.format(self.options, pstyle)
|
||||
|
||||
self.options.set_document(self.doc)
|
||||
|
||||
def on_ok_clicked(self, obj):
|
||||
"""The user is satisfied with the dialog choices. Validate
|
||||
the output file name before doing anything else. If there is
|
||||
a file name, gather the options and create the report."""
|
||||
|
||||
# Is there a filename? This should also test file permissions, etc.
|
||||
if not self.parse_target_frame():
|
||||
self.window.run()
|
||||
|
||||
# Preparation
|
||||
self.parse_format_frame()
|
||||
self.parse_user_options()
|
||||
|
||||
self.options.handler.set_paper_metric(
|
||||
self.paper_frame.get_paper_metric())
|
||||
self.options.handler.set_paper_name(
|
||||
self.paper_frame.get_paper_name())
|
||||
self.options.handler.set_orientation(
|
||||
self.paper_frame.get_orientation())
|
||||
self.options.handler.set_margins(
|
||||
self.paper_frame.get_paper_margins())
|
||||
self.options.handler.set_custom_paper_size(
|
||||
self.paper_frame.get_custom_paper_size())
|
||||
|
||||
# Create the output document.
|
||||
self.make_document()
|
||||
|
||||
# Save options
|
||||
self.options.handler.save_options()
|
||||
config.set('interface.open-with-default-viewer',
|
||||
self.open_with_app.get_active())
|
||||
|
||||
def parse_format_frame(self):
|
||||
"""Parse the format frame of the dialog. Save the user
|
||||
selected output format for later use."""
|
||||
self.format = self.format_menu.get_reference()
|
||||
format_name = self.format_menu.get_clname()
|
||||
self.options.handler.set_format_name(format_name)
|
||||
|
||||
def setup_style_frame(self):
|
||||
"""Required by ReportDialog"""
|
||||
pass
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# GraphvizFormatComboBox
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
class GraphvizFormatComboBox(BaseFormatComboBox):
|
||||
FORMATS = graphdoc.FORMATS
|
||||
|
@ -55,7 +55,8 @@ from ...user import User
|
||||
from ...dialog import ErrorDialog, OptionDialog
|
||||
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
||||
CATEGORY_CODE, CATEGORY_WEB,
|
||||
CATEGORY_GRAPHVIZ, standalone_categories)
|
||||
CATEGORY_GRAPHVIZ, CATEGORY_TREE,
|
||||
standalone_categories)
|
||||
from gramps.gen.plug.docgen import StyleSheet, StyleSheetList
|
||||
from ...managedwindow import ManagedWindow
|
||||
from ._stylecombobox import StyleComboBox
|
||||
@ -676,6 +677,9 @@ def report(dbstate, uistate, person, report_class, options_class,
|
||||
elif category == CATEGORY_GRAPHVIZ:
|
||||
from ._graphvizreportdialog import GraphvizReportDialog
|
||||
dialog_class = GraphvizReportDialog
|
||||
elif category == CATEGORY_TREE:
|
||||
from ._treereportdialog import TreeReportDialog
|
||||
dialog_class = TreeReportDialog
|
||||
elif category == CATEGORY_WEB:
|
||||
from ._webreportdialog import WebReportDialog
|
||||
dialog_class = WebReportDialog
|
||||
|
64
gramps/gui/plug/report/_treereportdialog.py
Normal file
64
gramps/gui/plug/report/_treereportdialog.py
Normal file
@ -0,0 +1,64 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2017 Nick Hall
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""class for generating dialogs for graphviz-based reports """
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
from ._graphreportdialog import GraphReportDialog, BaseFormatComboBox
|
||||
from gramps.gen.plug.report import CATEGORY_TREE
|
||||
import gramps.gen.plug.docgen.treedoc as treedoc
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
#
|
||||
# TreeReportDialog
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
class TreeReportDialog(GraphReportDialog):
|
||||
|
||||
def make_doc_menu(self):
|
||||
"""
|
||||
Build a menu of document types that are appropriate for
|
||||
this graph report.
|
||||
"""
|
||||
self.format_menu = TreeFormatComboBox()
|
||||
|
||||
def get_category(self):
|
||||
"""
|
||||
Return the report category.
|
||||
"""
|
||||
return CATEGORY_TREE
|
||||
|
||||
def get_options(self):
|
||||
"""
|
||||
Return the graph options.
|
||||
"""
|
||||
return treedoc.TreeOptions()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# TreeFormatComboBox
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
class TreeFormatComboBox(BaseFormatComboBox):
|
||||
FORMATS = treedoc.FORMATS
|
@ -53,6 +53,7 @@ from gi.repository import Gdk
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
from gramps.gen.lib import EventType, EventRoleType
|
||||
from gramps.gen.lib.person import Person
|
||||
from gramps.gen.constfunc import has_display, is_quartz, mac, win
|
||||
from gramps.gen.config import config
|
||||
@ -314,6 +315,7 @@ class ProgressMeter:
|
||||
"""
|
||||
Close the progress meter
|
||||
"""
|
||||
del self.__cancel_callback
|
||||
self.__dialog.destroy()
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -473,33 +475,50 @@ def is_right_click(event):
|
||||
if Gdk.Event.triggers_context_menu(event):
|
||||
return True
|
||||
|
||||
def color_graph_family(family, dbstate):
|
||||
"""
|
||||
:return: based on the config the color for graph family node in hex
|
||||
:rtype: tuple (hex color fill, hex color border)
|
||||
"""
|
||||
scheme = config.get('colors.scheme')
|
||||
for event_ref in family.get_event_ref_list():
|
||||
event = dbstate.db.get_event_from_handle(event_ref.ref)
|
||||
if (event.type == EventType.DIVORCE and
|
||||
event_ref.get_role() in (EventRoleType.FAMILY,
|
||||
EventRoleType.PRIMARY)):
|
||||
return (config.get('colors.family-divorced')[scheme],
|
||||
config.get('colors.border-family-divorced')[scheme])
|
||||
return (config.get('colors.family')[scheme],
|
||||
config.get('colors.border-family')[scheme])
|
||||
|
||||
def color_graph_box(alive=False, gender=Person.MALE):
|
||||
"""
|
||||
:return: based on the config the color for graph boxes in hex
|
||||
If gender is None, an empty box is assumed
|
||||
:rtype: tuple (hex color fill, hex color border)
|
||||
"""
|
||||
scheme = config.get('colors.scheme')
|
||||
if gender == Person.MALE:
|
||||
if alive:
|
||||
return (config.get('preferences.color-gender-male-alive'),
|
||||
config.get('preferences.bordercolor-gender-male-alive'))
|
||||
return (config.get('colors.male-alive')[scheme],
|
||||
config.get('colors.border-male-alive')[scheme])
|
||||
else:
|
||||
return (config.get('preferences.color-gender-male-death'),
|
||||
config.get('preferences.bordercolor-gender-male-death'))
|
||||
return (config.get('colors.male-dead')[scheme],
|
||||
config.get('colors.border-male-dead')[scheme])
|
||||
elif gender == Person.FEMALE:
|
||||
if alive:
|
||||
return (config.get('preferences.color-gender-female-alive'),
|
||||
config.get('preferences.bordercolor-gender-female-alive'))
|
||||
return (config.get('colors.female-alive')[scheme],
|
||||
config.get('colors.border-female-alive')[scheme])
|
||||
else:
|
||||
return (config.get('preferences.color-gender-female-death'),
|
||||
config.get('preferences.bordercolor-gender-female-death'))
|
||||
return (config.get('colors.female-dead')[scheme],
|
||||
config.get('colors.border-female-dead')[scheme])
|
||||
elif gender == Person.UNKNOWN:
|
||||
if alive:
|
||||
return (config.get('preferences.color-gender-unknown-alive'),
|
||||
config.get('preferences.bordercolor-gender-unknown-alive'))
|
||||
return (config.get('colors.unknown-alive')[scheme],
|
||||
config.get('colors.border-unknown-alive')[scheme])
|
||||
else:
|
||||
return (config.get('preferences.color-gender-unknown-death'),
|
||||
config.get('preferences.bordercolor-gender-unknown-death'))
|
||||
return (config.get('colors.unknown-dead')[scheme],
|
||||
config.get('colors.border-unknown-dead')[scheme])
|
||||
#empty box, no gender
|
||||
return ('#d2d6ce', '#000000')
|
||||
## print 'male alive', rgb_to_hex((185/256.0, 207/256.0, 231/256.0))
|
||||
@ -543,6 +562,21 @@ def rgb_to_hex(rgb):
|
||||
rgbint = (int(rgb[0] * 255), int(rgb[1] * 255), int(rgb[2] * 255))
|
||||
return '#%02x%02x%02x' % rgbint
|
||||
|
||||
def get_link_color(context):
|
||||
"""
|
||||
Find the link color for the current theme.
|
||||
"""
|
||||
from gi.repository import Gtk
|
||||
|
||||
if Gtk.get_minor_version() > 11:
|
||||
col = context.get_color(Gtk.StateFlags.LINK)
|
||||
else:
|
||||
found, col = context.lookup_color('link_color')
|
||||
if not found:
|
||||
col.parse('blue')
|
||||
|
||||
return rgb_to_hex((col.red, col.green, col.blue))
|
||||
|
||||
def edit_object(dbstate, uistate, reftype, ref):
|
||||
"""
|
||||
Invokes the appropriate editor for an object type and given handle.
|
||||
|
@ -39,6 +39,7 @@ import time
|
||||
import datetime
|
||||
from io import StringIO
|
||||
import posixpath
|
||||
import gc
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -54,6 +55,7 @@ LOG = logging.getLogger(".")
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -136,8 +138,6 @@ UIDEFAULT = '''<ui>
|
||||
<menuitem action="Quit"/>
|
||||
</menu>
|
||||
<menu action="AddMenu">
|
||||
<menu action="AddNewMenu">
|
||||
<separator/>
|
||||
<menuitem action="PersonAdd"/>
|
||||
<separator/>
|
||||
<menuitem action="FamilyAdd"/>
|
||||
@ -150,7 +150,6 @@ UIDEFAULT = '''<ui>
|
||||
<menuitem action="RepositoryAdd"/>
|
||||
<menuitem action="MediaAdd"/>
|
||||
<menuitem action="NoteAdd"/>
|
||||
</menu>
|
||||
</menu>
|
||||
<menu action="EditMenu">
|
||||
<menuitem action="Undo"/>
|
||||
@ -396,7 +395,12 @@ class ViewManager(CLIManager):
|
||||
self.window.set_icon_from_file(ICON)
|
||||
self.window.set_default_size(width, height)
|
||||
self.window.move(horiz_position, vert_position)
|
||||
|
||||
#Set the mnemonic modifier on Macs to alt-ctrl so that it
|
||||
#doesn't interfere with the extended keyboard, see
|
||||
#https://gramps-project.org/bugs/view.php?id=6943
|
||||
if is_quartz():
|
||||
self.window.set_mnemonic_modifier(
|
||||
Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
self.window.add(vbox)
|
||||
hpane = Gtk.Paned()
|
||||
@ -599,20 +603,20 @@ class ViewManager(CLIManager):
|
||||
('Clipboard', 'edit-paste', _('Clip_board'), "<PRIMARY>b",
|
||||
_("Open the Clipboard dialog"), self.clipboard),
|
||||
('AddMenu', None, _('_Add')),
|
||||
('AddNewMenu', None, _('New')),
|
||||
('PersonAdd', None, _('Person'), "<Alt>p", None,
|
||||
#('AddNewMenu', None, _('New')),
|
||||
('PersonAdd', None, _('Person'), "<shift><Alt>p", None,
|
||||
self.add_new_person),
|
||||
('FamilyAdd', None, _('Family'), "<Alt>y", None,
|
||||
('FamilyAdd', None, _('Family'), "<shift><Alt>f", None,
|
||||
self.add_new_family),
|
||||
('EventAdd', None, _('Event'), "<shift>e", None,
|
||||
('EventAdd', None, _('Event'), "<shift><Alt>e", None,
|
||||
self.add_new_event),
|
||||
('PlaceAdd', None, _('Place'), "<shift><Alt>p", None,
|
||||
('PlaceAdd', None, _('Place'), "<shift><Alt>l", None,
|
||||
self.add_new_place),
|
||||
('SourceAdd', None, _('Source'), "<shift><Alt>s", None,
|
||||
self.add_new_source),
|
||||
('CitationAdd', None, _('Citation'), "<shift><Alt>c", None,
|
||||
self.add_new_citation),
|
||||
('RepositoryAdd', None, _('Repository'), "<shift><Alt>y", None,
|
||||
('RepositoryAdd', None, _('Repository'), "<shift><Alt>r", None,
|
||||
self.add_new_repository),
|
||||
('MediaAdd', None, _('Media'), "<shift><Alt>m", None,
|
||||
self.add_new_media),
|
||||
@ -1769,6 +1773,7 @@ def run_plugin(pdata, dbstate, uistate):
|
||||
name=pdata.id,
|
||||
category=pdata.category,
|
||||
callback=dbstate.db.request_rebuild)
|
||||
gc.collect(2)
|
||||
|
||||
def make_plugin_callback(pdata, dbstate, uistate):
|
||||
"""
|
||||
|
@ -278,14 +278,12 @@ class ListView(NavigationView):
|
||||
def foreground_color(self, column, renderer, model, iter_, data=None):
|
||||
'''
|
||||
Set the foreground color of the cell renderer. We use a cell data
|
||||
function because we don't want to set the color of untagged rows.
|
||||
function because there is a problem returning None from a model.
|
||||
'''
|
||||
fg_color = model.get_value(iter_, model.color_column())
|
||||
#for color errors, typically color column is badly set
|
||||
if fg_color:
|
||||
renderer.set_property('foreground', fg_color)
|
||||
else:
|
||||
LOG.debug('Bad color set: ' + str(fg_color))
|
||||
if fg_color == '':
|
||||
fg_color = None
|
||||
renderer.set_property('foreground', fg_color)
|
||||
|
||||
def set_active(self):
|
||||
"""
|
||||
|
@ -156,8 +156,7 @@ class PageView(DbGUIElement, metaclass=ABCMeta):
|
||||
hpane = Gtk.Paned()
|
||||
vpane = Gtk.Paned(orientation=Gtk.Orientation.VERTICAL)
|
||||
hpane.pack1(vpane, resize=True, shrink=False)
|
||||
hpane.pack2(self.sidebar, resize=False, shrink=True)
|
||||
self._setup_slider_config(hpane, 'hpane.slider-position')
|
||||
hpane.pack2(self.sidebar, resize=False, shrink=False)
|
||||
hpane.show()
|
||||
vpane.show()
|
||||
|
||||
@ -168,14 +167,31 @@ class PageView(DbGUIElement, metaclass=ABCMeta):
|
||||
self._setup_slider_config(vpane, 'vpane.slider-position')
|
||||
|
||||
self.sidebar_toggled(self.sidebar.get_property('visible'))
|
||||
self.hpane_sig = hpane.connect("draw", self.set_page_slider)
|
||||
|
||||
return hpane
|
||||
|
||||
def _setup_slider_config(self, widget, setting):
|
||||
def set_page_slider(self, widget, dummy):
|
||||
""" Setup slider. We have the page realized at this point. """
|
||||
widget.disconnect(self.hpane_sig)
|
||||
# get current width of pane
|
||||
width = widget.get_allocated_width()
|
||||
# default will use natural size for sidebar until it gets to 400 pix
|
||||
side_ch = self.sidebar.get_children() # Gtk Notebook
|
||||
try:
|
||||
vp_ch = side_ch[0].get_children() # Gtk Viewport child
|
||||
ch_width = vp_ch[0].get_preferred_width()[0] + 3
|
||||
except AttributeError:
|
||||
ch_width = 300 # needed if no Gramplet installed
|
||||
pos = width - min(ch_width, 400)
|
||||
self._setup_slider_config(widget, 'hpane.slider-position',
|
||||
position=pos)
|
||||
|
||||
def _setup_slider_config(self, widget, setting, position=-1):
|
||||
"""
|
||||
Setup the slider configuration setting.
|
||||
"""
|
||||
self._config.register(setting, -1)
|
||||
self._config.register(setting, position)
|
||||
widget.set_position(self._config.get(setting))
|
||||
widget.connect('notify::position', self._position_changed, setting)
|
||||
|
||||
|
@ -139,7 +139,7 @@ class CitationBaseModel:
|
||||
tag_handle = data[0]
|
||||
cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[COLUMN_TAGS]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
@ -300,7 +300,7 @@ class CitationBaseModel:
|
||||
tag_handle = data[0]
|
||||
cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[COLUMN2_TAGS]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -208,7 +208,7 @@ class EventModel(FlatBaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[COLUMN_TAGS]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -220,7 +220,7 @@ class FamilyModel(FlatBaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[13]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -171,7 +171,7 @@ class MediaModel(FlatBaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[11]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -148,7 +148,7 @@ class NoteModel(FlatBaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, value = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[Note.POS_TAGS]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -538,7 +538,7 @@ class PeopleBaseModel(BaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, value = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[COLUMN_TAGS]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -201,7 +201,7 @@ class PlaceBaseModel:
|
||||
tag_handle = data[0]
|
||||
cached, value = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[16]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -253,7 +253,7 @@ class RepositoryModel(FlatBaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, tag_color = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[8]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -143,7 +143,7 @@ class SourceModel(FlatBaseModel):
|
||||
tag_handle = data[0]
|
||||
cached, value = self.get_cached_value(tag_handle, "TAG_COLOR")
|
||||
if not cached:
|
||||
tag_color = "#000000000000"
|
||||
tag_color = ""
|
||||
tag_priority = None
|
||||
for handle in data[11]:
|
||||
tag = self.db.get_tag_from_handle(handle)
|
||||
|
@ -898,7 +898,8 @@ class TreeBaseModel(GObject.GObject, Gtk.TreeModel, BaseModel):
|
||||
if node.handle is None:
|
||||
# Header rows dont get the foreground color set
|
||||
if col == self.color_column():
|
||||
return "#000000000000"
|
||||
#color must not be utf-8
|
||||
return ""
|
||||
|
||||
# Return the node name for the first column
|
||||
if col == 0:
|
||||
|
@ -32,6 +32,7 @@ from .photo import *
|
||||
from .placeentry import *
|
||||
from .monitoredwidgets import *
|
||||
from .selectionwidget import SelectionWidget, Region
|
||||
from .shadebox import *
|
||||
from .shortlistcomboentry import *
|
||||
from .springseparator import *
|
||||
from .statusbar import Statusbar
|
||||
|
70
gramps/gui/widgets/cellrenderertextedit.py
Normal file
70
gramps/gui/widgets/cellrenderertextedit.py
Normal file
@ -0,0 +1,70 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2017 Paul Culley
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Python Modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
class CellRendererTextEdit(Gtk.CellRendererText):
|
||||
""" To be used where you normally use Gtk.CellRendererText and you want to
|
||||
avoid losing the text if the user clicks outside the cell (Like an 'OK'
|
||||
button. """
|
||||
|
||||
__gtype_name__ = 'CellRendererTextEdit'
|
||||
|
||||
def __init__(self):
|
||||
Gtk.CellRendererText.__init__(self)
|
||||
|
||||
def do_start_editing(
|
||||
self, event, treeview, path, background_area, cell_area, flags):
|
||||
if not self.get_property('editable'):
|
||||
return
|
||||
entry = Gtk.Entry()
|
||||
entry.set_has_frame(False)
|
||||
xalign, yalign = self.get_alignment()
|
||||
entry.set_alignment(xalign)
|
||||
entry.set_width_chars(5)
|
||||
entry.set_text(self.get_property("text")) # get original cell text
|
||||
entry.add_events(Gdk.EventMask.FOCUS_CHANGE_MASK)
|
||||
entry.connect('focus-out-event', self.focus_out, path)
|
||||
entry.connect('key-press-event', self._key_press)
|
||||
entry.show()
|
||||
return entry
|
||||
|
||||
def focus_out(self, entry, event, path):
|
||||
self.emit('edited', path, entry.get_text())
|
||||
return False
|
||||
|
||||
def _key_press(self, entry, event):
|
||||
if event.type == Gdk.EventType.KEY_PRESS:
|
||||
if event.keyval == Gdk.KEY_Escape:
|
||||
# get original cell text
|
||||
entry.set_text(self.get_property("text"))
|
||||
return False
|
@ -1221,7 +1221,9 @@ class FanChartWidget(FanChartBaseWidget):
|
||||
cr.scale(scale, scale)
|
||||
if widget:
|
||||
self.center_xy = self.center_xy_from_delta()
|
||||
cr.translate(*self.center_xy)
|
||||
cr.translate(*self.center_xy)
|
||||
else:
|
||||
cr.translate(halfdist, halfdist)
|
||||
|
||||
cr.save()
|
||||
cr.rotate(math.radians(self.rotate_value))
|
||||
@ -1596,6 +1598,8 @@ class FanChartGrampsGUI:
|
||||
siblings.append(sib_id)
|
||||
# Collect a list of per-step-family step-siblings
|
||||
for parent_h in [fam.get_father_handle(), fam.get_mother_handle()]:
|
||||
if not parent_h:
|
||||
continue
|
||||
parent = self.dbstate.db.get_person_from_handle(parent_h)
|
||||
other_families = [self.dbstate.db.get_family_from_handle(fam_id)
|
||||
for fam_id in parent.get_family_handle_list()
|
||||
|
@ -374,7 +374,9 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
||||
cr.scale(scale, scale)
|
||||
if widget:
|
||||
self.center_xy = self.center_xy_from_delta()
|
||||
cr.translate(*self.center_xy)
|
||||
cr.translate(*self.center_xy)
|
||||
else:
|
||||
cr.translate(halfdist, halfdist)
|
||||
|
||||
cr.save()
|
||||
# Draw background
|
||||
|
@ -370,7 +370,7 @@ class GrampletBar(Gtk.Notebook):
|
||||
"""
|
||||
Add a tab to the notebook for the given gramplet.
|
||||
"""
|
||||
width = min(int(self.uistate.screen_width() * 0.25), 400)
|
||||
width = -1 # Allow tab width to adjust (smaller) to sidebar
|
||||
height = min(int(self.uistate.screen_height() * 0.20), 400)
|
||||
gramplet.set_size_request(width, height)
|
||||
|
||||
|
@ -48,7 +48,7 @@ from gramps.gen.errors import WindowActiveError
|
||||
from gramps.gen.const import URL_MANUAL_PAGE, VERSION_DIR, COLON
|
||||
from ..editors import EditPerson, EditFamily
|
||||
from ..managedwindow import ManagedWindow
|
||||
from ..utils import is_right_click, rgb_to_hex, get_primary_mask
|
||||
from ..utils import is_right_click, get_primary_mask, get_link_color
|
||||
from .menuitem import add_menuitem
|
||||
from ..plug import make_gui_option
|
||||
from ..plug.quick import run_quick_report_by_name
|
||||
@ -196,12 +196,7 @@ class LinkTag(Gtk.TextTag):
|
||||
lid = 0
|
||||
#obtaining the theme link color once. Restart needed on theme change!
|
||||
linkcolor = Gtk.Label(label='test') #needed to avoid label destroyed to early
|
||||
linkcolor = linkcolor.get_style_context().lookup_color('link_color')
|
||||
if linkcolor[0]:
|
||||
linkcolor = rgb_to_hex((linkcolor[1].red, linkcolor[1].green,
|
||||
linkcolor[1].blue))
|
||||
else:
|
||||
linkcolor = 'blue'
|
||||
linkcolor = get_link_color(linkcolor.get_style_context())
|
||||
|
||||
def __init__(self, buffer):
|
||||
LinkTag.lid += 1
|
||||
|
@ -48,7 +48,7 @@ from gi.repository import Pango
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.constfunc import has_display, win
|
||||
from ..utils import rgb_to_hex
|
||||
from ..utils import get_link_color
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -81,11 +81,7 @@ class LinkLabel(Gtk.EventBox):
|
||||
Gtk.EventBox.__init__(self)
|
||||
|
||||
st_cont = self.get_style_context()
|
||||
col = st_cont.lookup_color('link_color')
|
||||
if col[0]:
|
||||
self.color = rgb_to_hex((col[1].red, col[1].green, col[1].blue))
|
||||
else:
|
||||
self.color = 'blue'
|
||||
self.color = get_link_color(st_cont)
|
||||
|
||||
if emph:
|
||||
#emphasize a link
|
||||
|
58
gramps/gui/widgets/shadebox.py
Normal file
58
gramps/gui/widgets/shadebox.py
Normal file
@ -0,0 +1,58 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2018 Nick Hall
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
__all__ = ["ShadeBox"]
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger(".widgets.shadebox")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gi.repository import Gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# ShadeBox class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class ShadeBox(Gtk.EventBox):
|
||||
"""
|
||||
An EventBox with a shaded background.
|
||||
"""
|
||||
def __init__(self, use_shade):
|
||||
Gtk.EventBox.__init__(self)
|
||||
self.use_shade = use_shade
|
||||
|
||||
def do_draw(self, cr):
|
||||
if self.use_shade:
|
||||
tv = Gtk.TextView()
|
||||
tv_context = tv.get_style_context()
|
||||
width = self.get_allocated_width()
|
||||
height = self.get_allocated_height()
|
||||
Gtk.render_background(tv_context, cr, 0, 0, width, height)
|
||||
self.get_child().draw(cr)
|
@ -60,9 +60,9 @@ from .toolcomboentry import ToolComboEntry
|
||||
from .springseparator import SpringSeparatorAction
|
||||
from ..spell import Spell
|
||||
from ..display import display_url
|
||||
from ..utils import SystemFonts, rgb_to_hex, get_primary_mask
|
||||
from ..utils import SystemFonts, get_primary_mask, get_link_color
|
||||
from gramps.gen.config import config
|
||||
from gramps.gen.constfunc import has_display
|
||||
from gramps.gen.constfunc import has_display, mac
|
||||
from ..actiongroup import ActionGroup
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -186,11 +186,7 @@ class StyledTextEditor(Gtk.TextView):
|
||||
self.set_buffer(self.textbuffer)
|
||||
|
||||
st_cont = self.get_style_context()
|
||||
col = st_cont.lookup_color('link_color')
|
||||
if col[0]:
|
||||
self.linkcolor = rgb_to_hex((col[1].red, col[1].green, col[1].blue))
|
||||
else:
|
||||
self.linkcolor = 'blue'
|
||||
self.linkcolor = get_link_color(st_cont)
|
||||
self.textbuffer.linkcolor = self.linkcolor
|
||||
|
||||
self.match = None
|
||||
@ -319,7 +315,9 @@ class StyledTextEditor(Gtk.TextView):
|
||||
if url.startswith("gramps://"):
|
||||
obj_class, prop, value = url[9:].split("/")
|
||||
display = simple_access.display(obj_class, prop, value) or url
|
||||
return display
|
||||
return display + ((_("\nCommand-Click to follow link") if mac() else
|
||||
_("\nCtrl-Click to follow link"))
|
||||
if self.get_editable() else '')
|
||||
|
||||
def on_button_release_event(self, widget, event):
|
||||
"""
|
||||
|
@ -52,7 +52,7 @@ from gi.repository import Pango
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.errors import MaskError, ValidationError, WindowActiveError
|
||||
from .undoableentry import UndoableEntry
|
||||
|
||||
from gramps.gen.constfunc import is_quartz
|
||||
#============================================================================
|
||||
#
|
||||
# MaskedEntry and ValidatableMaskedEntry copied and merged from the Kiwi
|
||||
@ -1248,6 +1248,12 @@ def main(args):
|
||||
win = Gtk.Window()
|
||||
win.set_title('ValidatableMaskedEntry test window')
|
||||
win.set_position(Gtk.WindowPosition.CENTER)
|
||||
#Set the mnemonic modifier on Macs to alt-ctrl so that it
|
||||
#doesn't interfere with the extended keyboard, see
|
||||
#https://gramps-project.org/bugs/view.php?id=6943
|
||||
if is_quartz():
|
||||
win.set_mnemonic_modifier(
|
||||
Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)
|
||||
def cb(window, event):
|
||||
Gtk.main_quit()
|
||||
win.connect('delete-event', cb)
|
||||
|
@ -468,8 +468,9 @@ class RecurseDown:
|
||||
#calculate the text.
|
||||
myself.calc_text(self.database, indi_handle, fams_handle)
|
||||
|
||||
myself.add_mark(self.database,
|
||||
self.database.get_person_from_handle(indi_handle))
|
||||
if indi_handle:
|
||||
myself.add_mark(self.database,
|
||||
self.database.get_person_from_handle(indi_handle))
|
||||
|
||||
self.add_to_col(myself)
|
||||
|
||||
@ -692,7 +693,8 @@ class MakePersonTree(RecurseDown):
|
||||
family2 = family2_h = None
|
||||
if self.do_parents:
|
||||
family2_h = center1.get_main_parents_family_handle()
|
||||
family2 = self.database.get_family_from_handle(family2_h)
|
||||
if family2_h:
|
||||
family2 = self.database.get_family_from_handle(family2_h)
|
||||
|
||||
mother2_h = father2_h = None
|
||||
if family2:
|
||||
|
@ -27,7 +27,6 @@
|
||||
# standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
@ -43,9 +42,12 @@ log = logging.getLogger(".WriteFtree")
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gramps.gen.utils.alive import probably_alive
|
||||
# keep the following line even though not obviously used (works on import)
|
||||
from gramps.gui.plug.export import WriterOptionBox
|
||||
from gramps.gui.glade import Glade
|
||||
from gramps.gui.dialog import ErrorDialog
|
||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||
_ = glocale.translation.gettext
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -53,22 +55,25 @@ from gramps.gui.glade import Glade
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def writeData(database, filename, user, option_box=None):
|
||||
""" function to export Web Family Tree file """
|
||||
writer = FtreeWriter(database, filename, user, option_box)
|
||||
return writer.export_data()
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# FtreeWriter
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class FtreeWriter:
|
||||
|
||||
""" Export a Web Family Tree format file """
|
||||
def __init__(self, database, filename, user, option_box=None):
|
||||
self.db = database
|
||||
self.filename = filename
|
||||
self.user = user
|
||||
self.option_box = option_box
|
||||
if isinstance(self.user.callback, collections.Callable): # callback is really callable
|
||||
# is callback is really callable?
|
||||
if isinstance(self.user.callback, collections.Callable):
|
||||
self.update = self.update_real
|
||||
else:
|
||||
self.update = self.update_empty
|
||||
@ -78,121 +83,132 @@ class FtreeWriter:
|
||||
self.db = option_box.get_filtered_database(self.db)
|
||||
|
||||
self.plist = [x for x in self.db.iter_person_handles()]
|
||||
# the following are used to update the progress meter
|
||||
self.total = 2 * len(self.plist)
|
||||
self.count = 0
|
||||
self.oldval = 0 # we only update when percentage changes
|
||||
|
||||
def update_empty(self):
|
||||
""" used when no callback is present """
|
||||
pass
|
||||
|
||||
def update_real(self):
|
||||
""" Progress update """
|
||||
self.count += 1
|
||||
newval = int(100*self.count/self.total)
|
||||
newval = int(100 * self.count / self.total)
|
||||
if newval != self.oldval:
|
||||
self.user.callback(newval)
|
||||
self.oldval = newval
|
||||
|
||||
def export_data(self):
|
||||
""" main export processing """
|
||||
name_map = {}
|
||||
id_map = {}
|
||||
id_name = {}
|
||||
self.count = 0
|
||||
self.oldval = 0
|
||||
self.total = 2*len(self.plist)
|
||||
|
||||
for key in self.plist:
|
||||
self.update()
|
||||
pn = self.db.get_person_from_handle(key).get_primary_name()
|
||||
sn = pn.get_surname()
|
||||
items = pn.get_first_name().split()
|
||||
n = ("%s %s" % (items[0], sn)) if items else sn
|
||||
pnam = self.db.get_person_from_handle(key).get_primary_name()
|
||||
snam = pnam.get_surname()
|
||||
items = pnam.get_first_name().split()
|
||||
nam = ("%s %s" % (items[0], snam)) if items else snam
|
||||
|
||||
count = -1
|
||||
if n in name_map:
|
||||
if nam in name_map:
|
||||
count = 0
|
||||
while 1:
|
||||
nn = "%s%d" % (n, count)
|
||||
if nn not in name_map:
|
||||
break;
|
||||
nam_num = "%s%d" % (nam, count)
|
||||
if nam_num not in name_map:
|
||||
break
|
||||
count += 1
|
||||
name_map[nn] = key
|
||||
id_map[key] = nn
|
||||
name_map[nam_num] = key
|
||||
id_map[key] = nam_num
|
||||
else:
|
||||
name_map[n] = key
|
||||
id_map[key] = n
|
||||
id_name[key] = get_name(pn, sn, count)
|
||||
name_map[nam] = key
|
||||
id_map[key] = nam
|
||||
id_name[key] = get_name(pnam, snam, count)
|
||||
|
||||
with open(self.filename, "w", encoding='utf_8') as f:
|
||||
try:
|
||||
with open(self.filename, "w", encoding='utf_8') as file:
|
||||
return self._export_data(file, id_name, id_map)
|
||||
except IOError as msg:
|
||||
msg2 = _("Could not create %s") % self.filename
|
||||
ErrorDialog(msg2, str(msg), parent=self.option_box.window)
|
||||
return False
|
||||
|
||||
for key in self.plist:
|
||||
self.update()
|
||||
p = self.db.get_person_from_handle(key)
|
||||
name = id_name[key]
|
||||
father = mother = email = web = ""
|
||||
def _export_data(self, file, id_name, id_map):
|
||||
""" file export processing """
|
||||
for key in self.plist:
|
||||
self.update()
|
||||
pers = self.db.get_person_from_handle(key)
|
||||
name = id_name[key]
|
||||
father = mother = email = web = ""
|
||||
|
||||
family_handle = p.get_main_parents_family_handle()
|
||||
if family_handle:
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
if family.get_father_handle() and \
|
||||
family.get_father_handle() in id_map:
|
||||
father = id_map[family.get_father_handle()]
|
||||
if family.get_mother_handle() and \
|
||||
family.get_mother_handle() in id_map:
|
||||
mother = id_map[family.get_mother_handle()]
|
||||
family_handle = pers.get_main_parents_family_handle()
|
||||
if family_handle:
|
||||
family = self.db.get_family_from_handle(family_handle)
|
||||
if family.get_father_handle() and \
|
||||
family.get_father_handle() in id_map:
|
||||
father = id_map[family.get_father_handle()]
|
||||
if family.get_mother_handle() and \
|
||||
family.get_mother_handle() in id_map:
|
||||
mother = id_map[family.get_mother_handle()]
|
||||
|
||||
#
|
||||
# Calculate Date
|
||||
#
|
||||
birth_ref = p.get_birth_ref()
|
||||
death_ref = p.get_death_ref()
|
||||
if birth_ref:
|
||||
birth_event = self.db.get_event_from_handle(birth_ref.ref)
|
||||
birth = birth_event.get_date_object()
|
||||
#
|
||||
# Calculate Date
|
||||
#
|
||||
birth_ref = pers.get_birth_ref()
|
||||
death_ref = pers.get_death_ref()
|
||||
if birth_ref:
|
||||
birth_event = self.db.get_event_from_handle(birth_ref.ref)
|
||||
birth = birth_event.get_date_object()
|
||||
else:
|
||||
birth = None
|
||||
if death_ref:
|
||||
death_event = self.db.get_event_from_handle(death_ref.ref)
|
||||
death = death_event.get_date_object()
|
||||
else:
|
||||
death = None
|
||||
|
||||
#if self.restrict:
|
||||
# alive = probably_alive(pers, self.db)
|
||||
#else:
|
||||
# alive = 0
|
||||
|
||||
if birth:
|
||||
if death:
|
||||
dates = "%s-%s" % (fdate(birth), fdate(death))
|
||||
else:
|
||||
birth = None
|
||||
if death_ref:
|
||||
death_event = self.db.get_event_from_handle(death_ref.ref)
|
||||
death = death_event.get_date_object()
|
||||
dates = fdate(birth)
|
||||
else:
|
||||
if death:
|
||||
dates = fdate(death)
|
||||
else:
|
||||
death = None
|
||||
dates = ""
|
||||
|
||||
#if self.restrict:
|
||||
# alive = probably_alive(p, self.db)
|
||||
#else:
|
||||
# alive = 0
|
||||
file.write('%s;%s;%s;%s;%s;%s\n' %
|
||||
(name, father, mother, email, web, dates))
|
||||
|
||||
if birth:
|
||||
if death:
|
||||
dates = "%s-%s" % (fdate(birth), fdate(death))
|
||||
else:
|
||||
dates = fdate(birth)
|
||||
else:
|
||||
if death:
|
||||
dates = fdate(death)
|
||||
else:
|
||||
dates = ""
|
||||
return True
|
||||
|
||||
f.write('%s;%s;%s;%s;%s;%s\n' % (name, father, mother, email, web,
|
||||
dates))
|
||||
|
||||
return True
|
||||
|
||||
def fdate(val):
|
||||
""" return properly formatted date """
|
||||
if val.get_year_valid():
|
||||
if val.get_month_valid():
|
||||
if val.get_day_valid():
|
||||
return "%d/%d/%d" % (val.get_day(), val.get_month(),
|
||||
val.get_year())
|
||||
else:
|
||||
return "%d/%d" % (val.get_month(), val.get_year())
|
||||
else:
|
||||
return "%d" % val.get_year()
|
||||
else:
|
||||
return ""
|
||||
return "%d/%d" % (val.get_month(), val.get_year())
|
||||
return "%d" % val.get_year()
|
||||
return ""
|
||||
|
||||
|
||||
def get_name(name, surname, count):
|
||||
"""returns a name string built from the components of the Name
|
||||
instance, in the form of Firstname Surname"""
|
||||
|
||||
return (name.first_name + ' ' +
|
||||
surname +
|
||||
(str(count) if count != -1 else '') +
|
||||
(', ' +name.suffix if name.suffix else '')
|
||||
)
|
||||
surname +
|
||||
(str(count) if count != -1 else '') +
|
||||
(', ' + name.suffix if name.suffix else ''))
|
||||
|
@ -1072,7 +1072,7 @@ class FamilyLinesReport(Report):
|
||||
|
||||
def get_event_place(self, event):
|
||||
""" get the place of the event """
|
||||
place_text = None
|
||||
place_text = ''
|
||||
place_handle = event.get_place_handle()
|
||||
if place_handle:
|
||||
place = self._db.get_place_from_handle(place_handle)
|
||||
|
@ -669,7 +669,7 @@ class TitleBox(BoxBase):
|
||||
return
|
||||
#fix me. width should be the printable area
|
||||
self.width = PT2CM(self.doc.string_width(self.font, self.text))
|
||||
self.height = PT2CM(self.font.get_size() * 1.2)
|
||||
self.height = PT2CM(self.font.get_size() * 2)
|
||||
|
||||
def _get_names(self, persons, name_displayer):
|
||||
""" A helper function that receives a list of persons and
|
||||
|
@ -528,8 +528,6 @@ class CairoPrintSave():
|
||||
pxwidth = round(context.get_width())
|
||||
pxheight = round(context.get_height())
|
||||
scale = min(pxwidth/self.widthpx, pxheight/self.heightpx)
|
||||
if scale > 1:
|
||||
scale = 1
|
||||
self.drawfunc(None, cr, scale=scale)
|
||||
|
||||
def on_paginate(self, operation, context):
|
||||
|
@ -516,8 +516,6 @@ class CairoPrintSave:
|
||||
pxwidth = round(context.get_width())
|
||||
pxheight = round(context.get_height())
|
||||
scale = min(pxwidth/self.widthpx, pxheight/self.heightpx)
|
||||
if scale > 1:
|
||||
scale = 1
|
||||
self.drawfunc(None, cr, scale=scale)
|
||||
|
||||
def on_paginate(self, operation, context):
|
||||
|
@ -523,8 +523,6 @@ class CairoPrintSave:
|
||||
pxwidth = round(context.get_width())
|
||||
pxheight = round(context.get_height())
|
||||
scale = min(pxwidth/self.widthpx, pxheight/self.heightpx)
|
||||
if scale > 1:
|
||||
scale = 1
|
||||
self.drawfunc(None, cr, scale=scale)
|
||||
|
||||
def on_paginate(self, operation, context):
|
||||
|
@ -316,15 +316,6 @@ class RelationshipView(NavigationView):
|
||||
self.child = None
|
||||
|
||||
self.scroll = Gtk.ScrolledWindow()
|
||||
|
||||
st_cont = self.scroll.get_style_context()
|
||||
col = st_cont.lookup_color('base_color')
|
||||
if col[0]:
|
||||
self.color = col[1]
|
||||
else:
|
||||
self.color = Gdk.RGBA()
|
||||
self.color.parse("White")
|
||||
|
||||
self.scroll.set_policy(Gtk.PolicyType.AUTOMATIC,
|
||||
Gtk.PolicyType.AUTOMATIC)
|
||||
self.scroll.show()
|
||||
@ -589,9 +580,7 @@ class RelationshipView(NavigationView):
|
||||
|
||||
grid.attach(eventbox, 0, 0, 2, 1)
|
||||
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
grid.attach(eventbox, 1, 1, 1, 1)
|
||||
subgrid = Gtk.Grid()
|
||||
subgrid.set_column_spacing(12)
|
||||
@ -888,9 +877,7 @@ class RelationshipView(NavigationView):
|
||||
box = self.get_people_box(family.get_father_handle(),
|
||||
family.get_mother_handle(),
|
||||
post_msg=childmsg)
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
eventbox.add(box)
|
||||
self.child.attach(eventbox, _PDATA_START, self.row,
|
||||
_PDATA_STOP-_PDATA_START, 1)
|
||||
@ -942,9 +929,7 @@ class RelationshipView(NavigationView):
|
||||
else :
|
||||
childmsg = _(" (only child)")
|
||||
box = self.get_people_box(post_msg=childmsg)
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
eventbox.add(box)
|
||||
self.child.attach(eventbox, _PDATA_START, self.row,
|
||||
_PDATA_STOP-_PDATA_START, 1)
|
||||
@ -972,9 +957,7 @@ class RelationshipView(NavigationView):
|
||||
child_should_be_linked = (child_handle != active)
|
||||
self.write_child(vbox, child_handle, i, child_should_be_linked)
|
||||
i += 1
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
eventbox.add(vbox)
|
||||
self.child.attach(eventbox, _CDATA_START-1, self.row,
|
||||
_CDATA_STOP-_CDATA_START+1, 1)
|
||||
@ -994,9 +977,6 @@ class RelationshipView(NavigationView):
|
||||
name = self.get_name(handle, True)
|
||||
link_label = widgets.LinkLabel(name, self._button_press,
|
||||
handle, theme=self.theme)
|
||||
if self.use_shade:
|
||||
link_label.override_background_color(Gtk.StateType.NORMAL,
|
||||
self.color)
|
||||
if self._config.get('preferences.releditbtn'):
|
||||
button = widgets.IconButton(self.edit_button_press,
|
||||
handle)
|
||||
@ -1039,7 +1019,7 @@ class RelationshipView(NavigationView):
|
||||
_PLABEL_STOP-_PLABEL_START, 1)
|
||||
|
||||
vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
||||
eventbox = Gtk.EventBox()
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
if handle:
|
||||
name = self.get_name(handle, True)
|
||||
person = self.dbstate.db.get_person_from_handle(handle)
|
||||
@ -1053,8 +1033,6 @@ class RelationshipView(NavigationView):
|
||||
emph = False
|
||||
link_label = widgets.LinkLabel(name, self._button_press,
|
||||
handle, emph, theme=self.theme)
|
||||
if self.use_shade:
|
||||
link_label.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
if self._config.get('preferences.releditbtn'):
|
||||
button = widgets.IconButton(self.edit_button_press, handle)
|
||||
button.set_tooltip_text(_('Edit Person (%s)') % name[0])
|
||||
@ -1073,8 +1051,6 @@ class RelationshipView(NavigationView):
|
||||
if value:
|
||||
vbox.pack_start(widgets.MarkupLabel(value), True, True, 0)
|
||||
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox.add(vbox)
|
||||
|
||||
self.child.attach(eventbox, _PDATA_START, self.row,
|
||||
@ -1174,9 +1150,6 @@ class RelationshipView(NavigationView):
|
||||
name = self.get_name(handle, True)
|
||||
link_label = widgets.LinkLabel(name, link_func, handle, emph,
|
||||
theme=self.theme)
|
||||
|
||||
if self.use_shade:
|
||||
link_label.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
link_label.set_padding(3, 0)
|
||||
if child_should_be_linked and self._config.get(
|
||||
'preferences.releditbtn'):
|
||||
@ -1391,9 +1364,7 @@ class RelationshipView(NavigationView):
|
||||
else :
|
||||
childmsg = _(" (no children)")
|
||||
box = self.get_people_box(handle, post_msg=childmsg)
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
eventbox.add(box)
|
||||
self.child.attach(eventbox, _PDATA_START, self.row,
|
||||
_PDATA_STOP-_PDATA_START, 1)
|
||||
@ -1438,9 +1409,7 @@ class RelationshipView(NavigationView):
|
||||
else :
|
||||
childmsg = _(" (no children)")
|
||||
box = self.get_people_box(post_msg=childmsg)
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
eventbox.add(box)
|
||||
self.child.attach(eventbox, _PDATA_START, self.row,
|
||||
_PDATA_STOP-_PDATA_START, 1)
|
||||
@ -1468,9 +1437,7 @@ class RelationshipView(NavigationView):
|
||||
i += 1
|
||||
|
||||
self.row += 1
|
||||
eventbox = Gtk.EventBox()
|
||||
if self.use_shade:
|
||||
eventbox.override_background_color(Gtk.StateType.NORMAL, self.color)
|
||||
eventbox = widgets.ShadeBox(self.use_shade)
|
||||
eventbox.add(vbox)
|
||||
self.child.attach(eventbox, _CDATA_START-1, self.row,
|
||||
_CDATA_STOP-_CDATA_START+1, 1)
|
||||
|
@ -628,17 +628,25 @@ class BasePage: # pylint: disable=C1001
|
||||
"""
|
||||
creates the event header row for all events
|
||||
"""
|
||||
trow = Html("tr")
|
||||
trow = Html("tr", close=None)
|
||||
trow.extend(
|
||||
Html("th", trans, class_=colclass, inline=True)
|
||||
for trans, colclass in [
|
||||
(self._("Event"), "ColumnEvent"),
|
||||
(self._("Date"), "ColumnDate"),
|
||||
(self._("Place"), "ColumnPlace"),
|
||||
(self._("Description"), "ColumnDescription"),
|
||||
(self._("Notes"), "ColumnNotes"),
|
||||
(self._("Sources"), "ColumnSources")]
|
||||
(self._("Description"), "ColumnDescription")]
|
||||
)
|
||||
trow += Html("/tr", close=None)
|
||||
trow2 = Html("tr", indent=False)
|
||||
trow2.extend(
|
||||
Html("th", trans, class_=colclass, colspan=opt, inline=True)
|
||||
for trans, colclass, opt in [
|
||||
("", "ColumnEvent", 1),
|
||||
(self._("Sources"), "ColumnSources", 1),
|
||||
(self._("Notes"), "ColumnNotes", 2)]
|
||||
)
|
||||
trow.extend(trow2)
|
||||
return trow
|
||||
|
||||
def display_event_row(self, event, event_ref, place_lat_long,
|
||||
@ -688,6 +696,12 @@ class BasePage: # pylint: disable=C1001
|
||||
for (label, colclass, data) in event_data
|
||||
)
|
||||
|
||||
trow2 = Html("tr")
|
||||
trow2 += Html("td", "", class_="ColumnSources")
|
||||
# get event source references
|
||||
srcrefs = self.get_citation_links(event.get_citation_list()) or " "
|
||||
trow2 += Html("td", srcrefs, class_="ColumnSources")
|
||||
|
||||
# get event notes
|
||||
notelist = event.get_note_list()
|
||||
notelist.extend(event_ref.get_note_list())
|
||||
@ -709,12 +723,9 @@ class BasePage: # pylint: disable=C1001
|
||||
if notelist:
|
||||
htmllist.extend(self.dump_notes(notelist))
|
||||
|
||||
trow += Html("td", htmllist, class_="ColumnNotes")
|
||||
|
||||
# get event source references
|
||||
srcrefs = self.get_citation_links(event.get_citation_list()) or " "
|
||||
trow += Html("td", srcrefs, class_="ColumnSources")
|
||||
trow2 += Html("td", htmllist, class_="ColumnNotes", colspan=2)
|
||||
|
||||
trow += trow2
|
||||
# return events table row to its callers
|
||||
return trow
|
||||
|
||||
@ -1502,7 +1513,7 @@ class BasePage: # pylint: disable=C1001
|
||||
("addressbook", self._("Address Book"),
|
||||
self.report.inc_addressbook),
|
||||
('contact', self._("Contact"), self.report.use_contact),
|
||||
('statistics', self._("Statistics"), True),
|
||||
('statistics', self._("Statistics"), self.report.inc_stats),
|
||||
(self.target_cal_uri, self._("Web Calendar"), self.usecal)
|
||||
]
|
||||
|
||||
|
@ -31,6 +31,7 @@ from unicodedata import normalize
|
||||
from collections import defaultdict
|
||||
from hashlib import md5
|
||||
import re
|
||||
import gc
|
||||
import logging
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
@ -859,4 +860,3 @@ def html_escape(text):
|
||||
text = text.replace("'", ''')
|
||||
|
||||
return text
|
||||
|
||||
|
@ -110,17 +110,18 @@ class EventPages(BasePage):
|
||||
for event_handle in event_handle_list:
|
||||
event = self.r_db.get_event_from_handle(event_handle)
|
||||
event_types.append(self._(event.get_type().xml_str()))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating event pages"),
|
||||
message = _("Creating event pages")
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
len(event_handle_list) + 1
|
||||
) as step:
|
||||
self.eventlistpage(self.report, title, event_types,
|
||||
event_handle_list)
|
||||
|
||||
index = 1
|
||||
for event_handle in event_handle_list:
|
||||
step()
|
||||
index += 1
|
||||
self.eventpage(self.report, title, event_handle)
|
||||
|
||||
step()
|
||||
self.eventlistpage(self.report, title, event_types,
|
||||
event_handle_list)
|
||||
|
||||
def eventlistpage(self, report, title, event_types, event_handle_list):
|
||||
"""
|
||||
|
@ -103,16 +103,18 @@ class FamilyPages(BasePage):
|
||||
for item in self.report.obj_dict[Family].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating family pages..."),
|
||||
message = _("Creating family pages...")
|
||||
index = 1
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
len(self.report.obj_dict[Family]) + 1
|
||||
) as step:
|
||||
self.familylistpage(self.report, title,
|
||||
self.report.obj_dict[Family].keys())
|
||||
|
||||
for family_handle in self.report.obj_dict[Family]:
|
||||
step()
|
||||
index += 1
|
||||
self.familypage(self.report, title, family_handle)
|
||||
step()
|
||||
self.familylistpage(self.report, title,
|
||||
self.report.obj_dict[Family].keys())
|
||||
|
||||
def familylistpage(self, report, title, fam_list):
|
||||
"""
|
||||
|
@ -94,6 +94,7 @@ class MediaPages(BasePage):
|
||||
"""
|
||||
BasePage.__init__(self, report, title="")
|
||||
self.media_dict = defaultdict(set)
|
||||
self.unused_media_handles = []
|
||||
|
||||
def display_pages(self, title):
|
||||
"""
|
||||
@ -105,9 +106,13 @@ class MediaPages(BasePage):
|
||||
LOG.debug("obj_dict[Media]")
|
||||
for item in self.report.obj_dict[Media].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating media pages"),
|
||||
len(self.report.obj_dict[Media]) + 1
|
||||
if self.create_unused_media:
|
||||
media_count = len(self.r_db.get_media_handles())
|
||||
else:
|
||||
media_count = len(self.report.obj_dict[Media])
|
||||
message = _("Creating media pages")
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
media_count + 1
|
||||
) as step:
|
||||
# bug 8950 : it seems it's better to sort on desc + gid.
|
||||
def sort_by_desc_and_gid(obj):
|
||||
@ -116,24 +121,62 @@ class MediaPages(BasePage):
|
||||
"""
|
||||
return (obj.desc.lower(), obj.gramps_id)
|
||||
|
||||
self.unused_media_handles = []
|
||||
if self.create_unused_media:
|
||||
# add unused media
|
||||
media_list = self.r_db.get_media_handles()
|
||||
for media_ref in media_list:
|
||||
if media_ref not in self.report.obj_dict[Media]:
|
||||
self.unused_media_handles.append(media_ref)
|
||||
self.unused_media_handles = sorted(
|
||||
self.unused_media_handles,
|
||||
key=lambda x: sort_by_desc_and_gid(
|
||||
self.r_db.get_media_from_handle(x)))
|
||||
|
||||
sorted_media_handles = sorted(
|
||||
self.report.obj_dict[Media].keys(),
|
||||
key=lambda x: sort_by_desc_and_gid(
|
||||
self.r_db.get_media_from_handle(x)))
|
||||
self.medialistpage(self.report, title, sorted_media_handles)
|
||||
|
||||
prev = None
|
||||
total = len(sorted_media_handles)
|
||||
index = 1
|
||||
for handle in sorted_media_handles:
|
||||
gc.collect() # Reduce memory usage when there are many images.
|
||||
next_ = None if index == total else sorted_media_handles[index]
|
||||
step()
|
||||
if index == media_count:
|
||||
next_ = None
|
||||
elif index < total:
|
||||
next_ = sorted_media_handles[index]
|
||||
elif len(self.unused_media_handles) > 0:
|
||||
next_ = self.unused_media_handles[0]
|
||||
else:
|
||||
next_ = None
|
||||
self.mediapage(self.report, title,
|
||||
handle, (prev, next_, index, total))
|
||||
handle, (prev, next_, index, media_count))
|
||||
prev = handle
|
||||
step()
|
||||
index += 1
|
||||
|
||||
total = len(self.unused_media_handles)
|
||||
idx = 1
|
||||
prev = sorted_media_handles[len(sorted_media_handles)-1]
|
||||
if total > 0:
|
||||
for media_handle in self.unused_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
gc.collect() # Reduce memory usage when many images.
|
||||
if index == media_count:
|
||||
next_ = None
|
||||
else:
|
||||
next_ = self.unused_media_handles[idx]
|
||||
self.mediapage(self.report, title,
|
||||
media_handle,
|
||||
(prev, next_, index, media_count))
|
||||
prev = media_handle
|
||||
step()
|
||||
index += 1
|
||||
idx += 1
|
||||
|
||||
self.medialistpage(self.report, title, sorted_media_handles)
|
||||
|
||||
def medialistpage(self, report, title, sorted_media_handles):
|
||||
"""
|
||||
Generate and output the Media index page.
|
||||
@ -191,85 +234,84 @@ class MediaPages(BasePage):
|
||||
table += tbody
|
||||
|
||||
index = 1
|
||||
for media_handle in sorted_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
if media:
|
||||
if media.get_change_time() > ldatec:
|
||||
ldatec = media.get_change_time()
|
||||
title = media.get_description() or "[untitled]"
|
||||
if self.create_unused_media:
|
||||
media_count = len(self.r_db.get_media_handles())
|
||||
else:
|
||||
media_count = len(self.report.obj_dict[Media])
|
||||
message = _("Creating list of media pages")
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
message, media_count + 1
|
||||
) as step:
|
||||
for media_handle in sorted_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
if media:
|
||||
if media.get_change_time() > ldatec:
|
||||
ldatec = media.get_change_time()
|
||||
title = media.get_description() or "[untitled]"
|
||||
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
trow = Html("tr")
|
||||
tbody += trow
|
||||
|
||||
media_data_row = [
|
||||
[index, "ColumnRowLabel"],
|
||||
[self.media_ref_link(media_handle,
|
||||
title), "ColumnName"],
|
||||
[self.rlocale.get_date(media.get_date_object()),
|
||||
"ColumnDate"],
|
||||
[media.get_mime_type(), "ColumnMime"]]
|
||||
media_data_row = [
|
||||
[index, "ColumnRowLabel"],
|
||||
[self.media_ref_link(media_handle,
|
||||
title), "ColumnName"],
|
||||
[self.rlocale.get_date(media.get_date_object()),
|
||||
"ColumnDate"],
|
||||
[media.get_mime_type(), "ColumnMime"]]
|
||||
|
||||
trow.extend(
|
||||
Html("td", data, class_=colclass)
|
||||
for data, colclass in media_data_row
|
||||
)
|
||||
trow.extend(
|
||||
Html("td", data, class_=colclass)
|
||||
for data, colclass in media_data_row
|
||||
)
|
||||
step()
|
||||
index += 1
|
||||
|
||||
def sort_by_desc_and_gid(obj):
|
||||
"""
|
||||
Sort by media description and gramps ID
|
||||
"""
|
||||
return (obj.desc, obj.gramps_id)
|
||||
def sort_by_desc_and_gid(obj):
|
||||
"""
|
||||
Sort by media description and gramps ID
|
||||
"""
|
||||
return (obj.desc, obj.gramps_id)
|
||||
|
||||
unused_media_handles = []
|
||||
if self.create_unused_media:
|
||||
# add unused media
|
||||
media_list = self.r_db.get_media_handles()
|
||||
for media_ref in media_list:
|
||||
if media_ref not in self.report.obj_dict[Media]:
|
||||
unused_media_handles.append(media_ref)
|
||||
unused_media_handles = sorted(
|
||||
unused_media_handles,
|
||||
key=lambda x: sort_by_desc_and_gid(
|
||||
self.r_db.get_media_from_handle(x)))
|
||||
|
||||
idx = 1
|
||||
prev = None
|
||||
total = len(unused_media_handles)
|
||||
if total > 0:
|
||||
trow += Html("tr")
|
||||
trow.extend(
|
||||
Html("td", Html("h4", " "), inline=True) +
|
||||
Html("td",
|
||||
Html("h4",
|
||||
self._("Below unused media objects"),
|
||||
inline=True),
|
||||
class_="") +
|
||||
Html("td", Html("h4", " "), inline=True) +
|
||||
Html("td", Html("h4", " "), inline=True)
|
||||
)
|
||||
for media_handle in unused_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
gc.collect() # Reduce memory usage when many images.
|
||||
next_ = None if idx == total else unused_media_handles[idx]
|
||||
trow += Html("tr")
|
||||
media_data_row = [
|
||||
[index, "ColumnRowLabel"],
|
||||
[self.media_ref_link(media_handle,
|
||||
media.get_description()),
|
||||
"ColumnName"],
|
||||
[self.rlocale.get_date(media.get_date_object()),
|
||||
"ColumnDate"],
|
||||
[media.get_mime_type(), "ColumnMime"]]
|
||||
trow.extend(
|
||||
Html("td", data, class_=colclass)
|
||||
for data, colclass in media_data_row
|
||||
)
|
||||
self.mediapage(self.report, title,
|
||||
media_handle, (prev, next_, index, total))
|
||||
prev = media_handle
|
||||
index += 1
|
||||
idx += 1
|
||||
idx = 1
|
||||
prev = None
|
||||
total = len(self.unused_media_handles)
|
||||
if total > 0:
|
||||
trow += Html("tr")
|
||||
trow.extend(
|
||||
Html("td", Html("h4", " "), inline=True) +
|
||||
Html("td",
|
||||
Html("h4",
|
||||
self._("Below unused media objects"),
|
||||
inline=True),
|
||||
class_="") +
|
||||
Html("td", Html("h4", " "), inline=True) +
|
||||
Html("td", Html("h4", " "), inline=True)
|
||||
)
|
||||
for media_handle in self.unused_media_handles:
|
||||
media = self.r_db.get_media_from_handle(media_handle)
|
||||
gc.collect() # Reduce memory usage when many images.
|
||||
if idx == total:
|
||||
next_ = None
|
||||
else:
|
||||
self.unused_media_handles[idx]
|
||||
trow += Html("tr")
|
||||
media_data_row = [
|
||||
[index, "ColumnRowLabel"],
|
||||
[self.media_ref_link(media_handle,
|
||||
media.get_description()),
|
||||
"ColumnName"],
|
||||
[self.rlocale.get_date(media.get_date_object()),
|
||||
"ColumnDate"],
|
||||
[media.get_mime_type(), "ColumnMime"]]
|
||||
trow.extend(
|
||||
Html("td", data, class_=colclass)
|
||||
for data, colclass in media_data_row
|
||||
)
|
||||
prev = media_handle
|
||||
step()
|
||||
index += 1
|
||||
idx += 1
|
||||
|
||||
# add footer section
|
||||
# add clearline for proper styling
|
||||
|
@ -200,6 +200,8 @@ class NavWebReport(Report):
|
||||
self.use_intro = self.options['intronote'] or self.options['introimg']
|
||||
self.use_home = self.options['homenote'] or self.options['homeimg']
|
||||
self.use_contact = self.opts['contactnote'] or self.opts['contactimg']
|
||||
self.inc_stats = self.opts['inc_stats']
|
||||
self.create_unused_media = self.opts['unused']
|
||||
|
||||
# Do we need to include this in a cms ?
|
||||
self.usecms = self.options['usecms']
|
||||
@ -441,7 +443,8 @@ class NavWebReport(Report):
|
||||
self.tab["Source"].display_pages(self.title)
|
||||
|
||||
# build classes StatisticsPage
|
||||
self.statistics_preview_page(self.title)
|
||||
if self.inc_stats:
|
||||
self.statistics_preview_page(self.title)
|
||||
|
||||
# copy all of the neccessary files
|
||||
self.copy_narrated_files()
|
||||
@ -458,6 +461,7 @@ class NavWebReport(Report):
|
||||
if len(_WRONGMEDIAPATH) > 10:
|
||||
error += '\n ...'
|
||||
self.user.warn(_("Missing media objects:"), error)
|
||||
self.database.clear_cache()
|
||||
|
||||
def _build_obj_dict(self):
|
||||
"""
|
||||
@ -488,12 +492,14 @@ class NavWebReport(Report):
|
||||
ind_list = self._db.iter_person_handles()
|
||||
ind_list = self.filter.apply(self._db, ind_list, user=self.user)
|
||||
|
||||
with self.user.progress(_("Narrated Web Site Report"),
|
||||
_('Constructing list of other objects...'),
|
||||
message = _('Constructing list of other objects...')
|
||||
with self.user.progress(_("Narrated Web Site Report"), message,
|
||||
sum(1 for _ in ind_list)) as step:
|
||||
index = 1
|
||||
for handle in ind_list:
|
||||
step()
|
||||
self._add_person(handle, "", "")
|
||||
step()
|
||||
index += 1
|
||||
|
||||
LOG.debug("final object dictionary \n" +
|
||||
"".join(("%s: %s\n" % item)
|
||||
@ -1057,13 +1063,15 @@ class NavWebReport(Report):
|
||||
@param: ind_list -- The list of person to use
|
||||
"""
|
||||
if self.inc_gendex:
|
||||
with self.user.progress(_("Narrated Web Site Report"),
|
||||
_('Creating GENDEX file'),
|
||||
message = _('Creating GENDEX file')
|
||||
with self.user.progress(_("Narrated Web Site Report"), message,
|
||||
len(ind_list)) as step:
|
||||
fp_gendex, gendex_io = self.create_file("gendex", ext=".txt")
|
||||
date = 0
|
||||
index = 1
|
||||
for person_handle in ind_list:
|
||||
step()
|
||||
index += 1
|
||||
person = self._db.get_person_from_handle(person_handle)
|
||||
datex = person.get_change_time()
|
||||
if datex > date:
|
||||
@ -1113,29 +1121,35 @@ class NavWebReport(Report):
|
||||
"""
|
||||
local_list = sort_people(self._db, ind_list, self.rlocale)
|
||||
|
||||
with self.user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating surname pages"),
|
||||
message = _("Creating surname pages")
|
||||
with self.user.progress(_("Narrated Web Site Report"), message,
|
||||
len(local_list)) as step:
|
||||
|
||||
SurnameListPage(self, self.title, ind_list,
|
||||
SurnameListPage.ORDER_BY_NAME,
|
||||
self.surname_fname)
|
||||
SurnameListPage.ORDER_BY_NAME,
|
||||
self.surname_fname)
|
||||
|
||||
SurnameListPage(self, self.title, ind_list,
|
||||
SurnameListPage.ORDER_BY_COUNT,
|
||||
"surnames_count")
|
||||
SurnameListPage.ORDER_BY_COUNT,
|
||||
"surnames_count")
|
||||
|
||||
index = 1
|
||||
for (surname, handle_list) in local_list:
|
||||
SurnamePage(self, self.title, surname, sorted(handle_list))
|
||||
step()
|
||||
index += 1
|
||||
|
||||
def thumbnail_preview_page(self):
|
||||
"""
|
||||
creates the thumbnail preview page
|
||||
"""
|
||||
if self.create_unused_media:
|
||||
media_count = len(self._db.get_media_handles())
|
||||
else:
|
||||
media_count = len(self.obj_dict[Media])
|
||||
with self.user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating thumbnail preview page..."),
|
||||
len(self.obj_dict[Media])) as step:
|
||||
media_count) as step:
|
||||
ThumbnailPreviewPage(self, self.title, step)
|
||||
|
||||
def statistics_preview_page(self, title):
|
||||
@ -1144,7 +1158,7 @@ class NavWebReport(Report):
|
||||
"""
|
||||
with self.user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating statistics page..."),
|
||||
len(self.obj_dict[Media])) as step:
|
||||
1) as step:
|
||||
StatisticsPage(self, title, step)
|
||||
|
||||
def addressbook_pages(self, ind_list):
|
||||
@ -1184,12 +1198,14 @@ class NavWebReport(Report):
|
||||
# begin Address Book pages
|
||||
addr_size = len(url_addr_res)
|
||||
|
||||
with self.user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating address book pages ..."),
|
||||
message = _("Creating address book pages ...")
|
||||
with self.user.progress(_("Narrated Web Site Report"), message,
|
||||
addr_size) as step:
|
||||
index = 1
|
||||
for (sort_name, person_handle, add, res, url) in url_addr_res:
|
||||
AddressBookPage(self, self.title, person_handle, add, res, url)
|
||||
step()
|
||||
index += 1
|
||||
|
||||
def base_pages(self):
|
||||
"""
|
||||
@ -1968,6 +1984,10 @@ class NavWebOptions(MenuReportOptions):
|
||||
"events."))
|
||||
addopt("inc_addressbook", inc_addressbook)
|
||||
|
||||
inc_statistics = BooleanOption(_("Include the statistics page"), False)
|
||||
inc_statistics.set_help(_("Whether or not to add statistics page"))
|
||||
addopt("inc_stats", inc_statistics)
|
||||
|
||||
def __add_place_map_options(self, menu):
|
||||
"""
|
||||
options for the Place Map tab.
|
||||
|
@ -130,16 +130,19 @@ class PersonPages(BasePage):
|
||||
LOG.debug("obj_dict[Person]")
|
||||
for item in self.report.obj_dict[Person].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_('Creating individual pages'),
|
||||
message = _('Creating individual pages')
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
len(self.report.obj_dict[Person]) + 1
|
||||
) as step:
|
||||
self.individuallistpage(self.report, title,
|
||||
self.report.obj_dict[Person].keys())
|
||||
index = 1
|
||||
for person_handle in sorted(self.report.obj_dict[Person]):
|
||||
step()
|
||||
index += 1
|
||||
person = self.r_db.get_person_from_handle(person_handle)
|
||||
self.individualpage(self.report, title, person)
|
||||
step()
|
||||
self.individuallistpage(self.report, title,
|
||||
self.report.obj_dict[Person].keys())
|
||||
|
||||
#################################################
|
||||
#
|
||||
|
@ -113,17 +113,18 @@ class PlacePages(BasePage):
|
||||
LOG.debug("obj_dict[Place]")
|
||||
for item in self.report.obj_dict[Place].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating place pages"),
|
||||
message = _("Creating place pages")
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
len(self.report.obj_dict[Place]) + 1
|
||||
) as step:
|
||||
|
||||
self.placelistpage(self.report, title,
|
||||
self.report.obj_dict[Place].keys())
|
||||
|
||||
index = 1
|
||||
for place_handle in self.report.obj_dict[Place]:
|
||||
step()
|
||||
index += 1
|
||||
self.placepage(self.report, title, place_handle)
|
||||
step()
|
||||
self.placelistpage(self.report, title,
|
||||
self.report.obj_dict[Place].keys())
|
||||
|
||||
def placelistpage(self, report, title, place_handles):
|
||||
"""
|
||||
|
@ -98,8 +98,8 @@ class RepositoryPages(BasePage):
|
||||
LOG.debug(" %s", str(item))
|
||||
|
||||
# set progress bar pass for Repositories
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_('Creating repository pages'),
|
||||
message = _('Creating repository pages')
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
len(self.report.obj_dict[Repository]) + 1
|
||||
) as step:
|
||||
# Sort the repositories
|
||||
@ -114,10 +114,11 @@ class RepositoryPages(BasePage):
|
||||
# RepositoryListPage Class
|
||||
self.repositorylistpage(self.report, title, repos_dict, keys)
|
||||
|
||||
idx = 1
|
||||
for index, key in enumerate(keys):
|
||||
(repo, handle) = repos_dict[key]
|
||||
|
||||
step()
|
||||
idx += 1
|
||||
self.repositorypage(self.report, title, repo, handle)
|
||||
|
||||
def repositorylistpage(self, report, title, repos_dict, keys):
|
||||
|
@ -99,15 +99,17 @@ class SourcePages(BasePage):
|
||||
LOG.debug("obj_dict[Source]")
|
||||
for item in self.report.obj_dict[Source].items():
|
||||
LOG.debug(" %s", str(item))
|
||||
with self.r_user.progress(_("Narrated Web Site Report"),
|
||||
_("Creating source pages"),
|
||||
message = _("Creating source pages")
|
||||
with self.r_user.progress(_("Narrated Web Site Report"), message,
|
||||
len(self.report.obj_dict[Source]) + 1
|
||||
) as step:
|
||||
self.sourcelistpage(self.report, title,
|
||||
self.report.obj_dict[Source].keys())
|
||||
|
||||
index = 1
|
||||
for source_handle in self.report.obj_dict[Source]:
|
||||
step()
|
||||
index += 1
|
||||
self.sourcepage(self.report, title, source_handle)
|
||||
|
||||
def sourcelistpage(self, report, title, source_handles):
|
||||
|
@ -86,6 +86,7 @@ class StatisticsPage(BasePage):
|
||||
females,
|
||||
unknown) = self.get_gender(report.database.iter_person_handles())
|
||||
|
||||
step()
|
||||
mobjects = report.database.get_number_of_media()
|
||||
npersons = report.database.get_number_of_people()
|
||||
nfamilies = report.database.get_number_of_families()
|
||||
|
@ -122,7 +122,7 @@ class ThumbnailPreviewPage(BasePage):
|
||||
"will take you to that image’s page.")
|
||||
previewpage += Html("p", msg, id="description")
|
||||
|
||||
with Html("table", class_="calendar") as table:
|
||||
with Html("table", class_="calendar thumbnails") as table:
|
||||
previewpage += table
|
||||
|
||||
thead = Html("thead")
|
||||
@ -153,7 +153,7 @@ class ThumbnailPreviewPage(BasePage):
|
||||
num_of_cols = 7
|
||||
grid_row = 0
|
||||
while grid_row < num_of_rows:
|
||||
trow = Html("tr", id="RowNumber: %08d" % grid_row)
|
||||
trow = Html("tr", class_="thumbnail", id="RowNumber: %08d" % grid_row)
|
||||
tbody += trow
|
||||
|
||||
cols = 0
|
||||
@ -163,7 +163,7 @@ class ThumbnailPreviewPage(BasePage):
|
||||
photo = media_list[indexpos][2]
|
||||
|
||||
# begin table cell and attach to table row(trow)...
|
||||
tcell = Html("td", class_="highlight weekend")
|
||||
tcell = Html("td", class_="highlight weekend thumbnail")
|
||||
trow += tcell
|
||||
|
||||
# attach index number...
|
||||
@ -203,6 +203,7 @@ class ThumbnailPreviewPage(BasePage):
|
||||
for emptycols in range(cols, num_of_cols):
|
||||
trow += Html("td", class_="emptyDays", inline=True)
|
||||
|
||||
message = _("Creating thumbnail preview page...")
|
||||
# begin Thumbnail Reference section...
|
||||
with Html("div", class_="subsection", id="references") as section:
|
||||
body += section
|
||||
@ -225,11 +226,12 @@ class ThumbnailPreviewPage(BasePage):
|
||||
tcell2 = Html("td", ptitle, class_="ColumnName")
|
||||
trow += (tcell1, tcell2)
|
||||
|
||||
# increase progress meter...
|
||||
cb_progress()
|
||||
|
||||
# increase index for row number...
|
||||
index += 1
|
||||
|
||||
# increase progress meter...
|
||||
cb_progress()
|
||||
|
||||
# add body id element
|
||||
body.attr = 'id ="ThumbnailPreview"'
|
||||
|
313
mac/gramps.accel
313
mac/gramps.accel
@ -1,200 +1,149 @@
|
||||
; gramps.py GtkAccelMap rc-file -*- scheme -*-
|
||||
; Gramps.py GtkAccelMap rc-file -*- scheme -*-
|
||||
; this file is an automated accelerator map dump
|
||||
;
|
||||
(gtk_accel_path "<Actions>/People Tree View/PersonAll/Edit" "<Meta>Return")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/PluginStatus" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/place_report" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/ViewMenu" "")
|
||||
(gtk_accel_path "<Actions>/Pedigree/Forward/Forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/birthday_report" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/marker_report" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/Graphs" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/FAQ" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/mediaman" "")
|
||||
(gtk_accel_path "<Actions>/Families/Forward/Forward" "<Alt>Right")
|
||||
(gtk_accel_path "<Actions>/Events/ChangeOrder/Add" "<Alt><Meta>i")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/det_descendant_report" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/statistics_chart" "")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonAll/FilterEdit" "")
|
||||
(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>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")
|
||||
(gtk_accel_path "<Actions>/MainWindow/Import" "<Meta>i")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Filter" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/summary" "")
|
||||
(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>d")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/book" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/FileMenu" "")
|
||||
(gtk_accel_path "<Actions>/Person View/Backward/Back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/records" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/ancestor_report" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/chname" "")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonEdit/FastMerge" "")
|
||||
(gtk_accel_path "<Actions>/Relationships/Forward/Forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonEdit/ExportTab" "")
|
||||
(gtk_accel_path "<Actions>/Notes/ChangeOrder/Remove" "<Meta>Delete")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/editowner" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/hourglass_graph" "")
|
||||
(gtk_accel_path "<Actions>/Repositories/ChangeOrder/Add" "<Alt><Meta>i")
|
||||
(gtk_accel_path "<Actions>/Media/Forward/Forward" "<Alt>Right")
|
||||
(gtk_accel_path "<Actions>/AllMainWindow/<CONTROL>Delete" "<Meta>Delete")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Toolbar" "")
|
||||
(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>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")
|
||||
(gtk_accel_path "<Actions>/Place View/ChangeOrder/Remove" "<Meta>Delete")
|
||||
(gtk_accel_path "<Actions>/Sources/ChangeOrder/Remove" "<Meta>Delete")
|
||||
(gtk_accel_path "<Actions>/Person View/ChangeOrder/Remove" "<Meta>Delete")
|
||||
; (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>d")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/reorder_ids" "")
|
||||
(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" "")
|
||||
(gtk_accel_path "<Actions>/Place View/Forward/Forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/kinship_report" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/BookMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/evname" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/Analysis-and-Exploration" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/indiv_complete" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F12" "F12")
|
||||
(gtk_accel_path "<Actions>/Place Tree View/Bookmark/AddBook" "<Meta>d")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F11" "F11")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/place_report" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/mediaman" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/SourceAdd" "<Shift><ctrl><alt>s")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/summary" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/rebuild_refmap" "")
|
||||
; (gtk_accel_path "<Actions>/Redo/Redo" "<Primary><Shift>z")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/ToolAnExp" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Toolbar" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/editowner" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Preferences" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/MediaAdd" "<Shift><ctrl><alt>m")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/sortevents" "")
|
||||
(gtk_accel_path "<Actions>/Fan Chart/Backward/Back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/Media/Backward/Back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/Fan Chart/Bookmark/AddBook" "<Meta>d")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonEdit/CmpMerge" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/ToolsMenu" "")
|
||||
(gtk_accel_path "<Actions>/Events/Forward/Forward" "<Alt>Right")
|
||||
(gtk_accel_path "<Actions>/Families/Backward/Back" "<Alt>Left")
|
||||
(gtk_accel_path "<Actions>/Place View/Backward/Back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/descend_chart" "")
|
||||
; (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>d")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>Delete" "<Primary>Delete")
|
||||
; (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")
|
||||
(gtk_accel_path "<Actions>/People Tree View/ChangeOrder/Add" "<Alt><Meta>i")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Sidebar" "")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonAll/Dummy" "")
|
||||
(gtk_accel_path "<Actions>/Redo/Redo" "<Shift><Meta>z")
|
||||
(gtk_accel_path "<Actions>/Person View/PersonEdit/Remove" "<Meta>Delete")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/family_group" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/excity" "")
|
||||
(gtk_accel_path "<Actions>/Repositories/ChangeOrder/Remove" "<Meta>Delete")
|
||||
(gtk_accel_path "<Actions>/Repositories/Forward/Forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/UserManual" "F1")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/OpenRecent" "")
|
||||
(gtk_accel_path "<Actions>/Families/Bookmark/AddBook" "<Meta>d")
|
||||
(gtk_accel_path "<Actions>/Place Tree View/Forward/Forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/hourglass_graph" "")
|
||||
; (gtk_accel_path "<Actions>/Undo/Undo" "<Primary>z")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/reorder_ids" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/rel_graph" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/Web-Pages" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/WebCal" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/Text-Reports" "")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonAll/QuickReport" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/ConfigView" "<Primary><Shift>c")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/descend_report" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/ancestor_chart" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/Clipboard" "<Primary>b")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/MailingLists" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/GoMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/verify" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/mergecitations" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/HomePage" "")
|
||||
(gtk_accel_path "<Actions>/Relationships/Family/Edit" "<Meta>Return")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/patchnames" "")
|
||||
(gtk_accel_path "<Actions>/Relationships/Backward/Back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/populatesources" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Open" "<Primary>o")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/endofline_report" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/CitationAdd" "<Shift><ctrl><alt>c")
|
||||
; (gtk_accel_path "<Actions>/UndoHistory/UndoHistory" "<Primary>h")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/family_descend_chart" "")
|
||||
(gtk_accel_path "<Actions>/AllMainWindow/Close" "<Primary>w")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/HelpMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/loop" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/descend_chart" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/EventAdd" "<Shift><ctrl><alt>e")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/ExtraPlugins" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/RepositoryAdd" "<Shift><ctrl><alt>r")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/BookMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/ToolProc" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/NoteAdd" "<Shift><ctrl><alt>n")
|
||||
(gtk_accel_path "<Actions>/MainWindow/PlaceAdd" "<Shift><ctrl><alt>l")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/navwebpage" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/birthday_report" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu8" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/ViewMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/fan_chart" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu7" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/calendar" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu6" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu5" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu4" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu3" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu2" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu1" "")
|
||||
; (gtk_accel_path "<Actions>/RecentFiles/RecentMenu0" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/RepWeb" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/indiv_complete" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/rebuild_genstats" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/FAQ" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/det_ancestor_report" "")
|
||||
(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>d")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/timeline" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/eventcmp" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/ReportsMenu" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/EditMenu" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/FamilyAdd" "<Shift><ctrl><alt>f")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/chname" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>Insert" "<Primary>Insert")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F9" "F9")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F8" "F8")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F7" "F7")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F6" "F6")
|
||||
(gtk_accel_path "<Actions>/Pedigree/Bookmark/AddBook" "<Meta>d")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F5" "F5")
|
||||
; (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>d")
|
||||
(gtk_accel_path "<Actions>/Sources/ChangeOrder/Add" "<Alt><Meta>i")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/Books" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/About" "")
|
||||
(gtk_accel_path "<Actions>/Notes/Backward/Back" "<Alt>Left")
|
||||
; (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>d")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/soundgen" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/ExtraPlugins" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/ReportsMenu" "")
|
||||
(gtk_accel_path "<Actions>/categoryviews/personlistview_0" "<Meta>1")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/descend_report" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/fan_chart" "")
|
||||
(gtk_accel_path "<Actions>/MainWindow/ScratchPad" "<Meta>b")
|
||||
(gtk_accel_path "<Actions>/Person View/Edit" "<Meta>Return")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/rebuild" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/eventcmp" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/GoMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/timeline" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/Database-Repair" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/Graphical-Reports" "")
|
||||
(gtk_accel_path "<Actions>/Person View/HomePerson" "<Alt>Home")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/ancestor_chart" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/check" "")
|
||||
(gtk_accel_path "<Actions>/Fan Chart/Forward/Forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/chtype" "")
|
||||
(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>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")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/verify" "")
|
||||
(gtk_accel_path "<Actions>/People Tree View/Forward/Forward" "<Alt>Right")
|
||||
(gtk_accel_path "<Actions>/Sources/Backward/Back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/not_related" "")
|
||||
(gtk_accel_path "<Actions>/People Tree View/Bookmark/AddBook" "<Meta>d")
|
||||
; (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>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>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/Navigator" "<Primary>m")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/PluginStatus" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F12" "F12")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/F11" "F11")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/ToolUtil" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/Import" "<Primary>i")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/statistics_chart" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/UserManual" "F1")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/Books" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/OpenRecent" "")
|
||||
; (gtk_accel_path "<Actions>/Dashboard/RestoreGramplet" "")
|
||||
; (gtk_accel_path "<Actions>/WindowManger/4722902520" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/RepGraph" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/familylines_graph" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/kinship_report" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/testcasegenerator" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/KeyBindings" "")
|
||||
(gtk_accel_path "<Actions>/Repositories/Backward/Back" "<Alt>Left")
|
||||
(gtk_accel_path "<Actions>/Events/Bookmark/AddBook" "<Meta>d")
|
||||
(gtk_accel_path "<Actions>/People Tree View/ChangeOrder/Remove" "<Meta>Delete")
|
||||
(gtk_accel_path "<Actions>/AllMainWindow/<CONTROL>P" "<Meta>p")
|
||||
(gtk_accel_path "<Actions>/Person View/ChangeOrder/Add" "<Alt><Meta>i")
|
||||
(gtk_accel_path "<Actions>/AllMainWindow/<CONTROL>N" "<Meta>n")
|
||||
(gtk_accel_path "<Actions>/Place Tree View/ChangeOrder/Remove" "<Meta>Delete")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/Abandon" "")
|
||||
(gtk_accel_path "<Actions>/Events/ChangeOrder/Remove" "<Meta>Delete")
|
||||
(gtk_accel_path "<Actions>/AllMainWindow/<CONTROL>J" "<Meta>j")
|
||||
(gtk_accel_path "<Actions>/Media/Bookmark/AddBook" "<Meta>d")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/tag_report" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/dgenstats" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Quit" "<Primary>q")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/TipOfDay" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/ancestor_report" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/check" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Fullscreen" "F11")
|
||||
(gtk_accel_path "<Actions>/MainWindow/PersonAdd" "<Shift><ctrl><alt>p")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>P" "<Primary>p")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/remove_unused" "")
|
||||
; (gtk_accel_path "<Actions>/Person View/PersonOther/SetActive" "")
|
||||
(gtk_accel_path "<Actions>/categoryviews/personview_1" "<Meta>2")
|
||||
(gtk_accel_path "<Actions>/Sources/Bookmark/AddBook" "<Meta>d")
|
||||
(gtk_accel_path "<Actions>/Place View/ChangeOrder/Add" "<Alt><Meta>i")
|
||||
(gtk_accel_path "<Actions>/Person View/PersonEdit/Add" "<Alt><Meta>i")
|
||||
(gtk_accel_path "<Actions>/Sources/Forward/Forward" "<Alt>Right")
|
||||
(gtk_accel_path "<Actions>/Person View/Bookmark/AddBook" "<Meta>d")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/Preferences" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>N" "<Primary>n")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/WebCal" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/records" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>J" "<Primary>j")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/number_of_ancestors" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/evname" "")
|
||||
; (gtk_accel_path "<Actions>/Dashboard/AddGramplet" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/notelinkreport" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/det_descendant_report" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/AddMenu" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/WindowsMenu" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/test_for_date_parser_and_displayer" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/Abandon" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/family_group" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>9" "<Primary>9")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>8" "<Primary>8")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/not_related" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>7" "<Primary>7")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>6" "<Primary>6")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>5" "<Primary>5")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>4" "<Primary>4")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>3" "<Primary>3")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>2" "<Primary>2")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>1" "<Primary>1")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>0" "<Primary>0")
|
||||
; (gtk_accel_path "<Actions>/WindowManger/M:4722902520" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/About" "")
|
||||
; (gtk_accel_path "<Actions>/MainWindow/ToolsMenu" "")
|
||||
; (gtk_accel_path "<Actions>/FileWindow/FileMenu" "")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/<PRIMARY>BackSpace" "<Primary>BackSpace")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/Export" "<Primary>e")
|
||||
; (gtk_accel_path "<Actions>/AllMainWindow/Backup" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/ToolDebug" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/Graphs" "")
|
||||
; (gtk_accel_path "<Actions>/ReportWindow/RepText" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/dupfind" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/rebuild" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/patchnames" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/chtype" "")
|
||||
; (gtk_accel_path "<Actions>/ToolWindow/ToolRep" "")
|
||||
|
@ -345,6 +345,7 @@ gramps/gen/plug/_pluginreg.py
|
||||
gramps/gen/plug/docbackend/docbackend.py
|
||||
gramps/gen/plug/docgen/graphdoc.py
|
||||
gramps/gen/plug/docgen/paperstyle.py
|
||||
gramps/gen/plug/docgen/treedoc.py
|
||||
gramps/gen/plug/menu/_enumeratedlist.py
|
||||
gramps/gen/plug/report/_book.py
|
||||
gramps/gen/plug/report/_constants.py
|
||||
|
@ -431,6 +431,7 @@ gramps/gui/views/treemodels/test/node_test.py
|
||||
#
|
||||
gramps/gui/widgets/__init__.py
|
||||
gramps/gui/widgets/basicentry.py
|
||||
gramps/gui/widgets/cellrenderertextedit.py
|
||||
gramps/gui/widgets/dateentry.py
|
||||
gramps/gui/widgets/fanchart2way.py
|
||||
gramps/gui/widgets/fanchartdesc.py
|
||||
@ -441,6 +442,7 @@ gramps/gui/widgets/menuitem.py
|
||||
gramps/gui/widgets/multitreeview.py
|
||||
gramps/gui/widgets/placeentry.py
|
||||
gramps/gui/widgets/selectionwidget.py
|
||||
gramps/gui/widgets/shadebox.py
|
||||
gramps/gui/widgets/shortlistcomboentry.py
|
||||
gramps/gui/widgets/springseparator.py
|
||||
gramps/gui/widgets/statusbar.py
|
||||
|
Loading…
x
Reference in New Issue
Block a user