parent
ec44396680
commit
70a634da1e
@ -46,7 +46,8 @@ log = logging.getLogger(".")
|
|||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
from gramps.gen.plug import BasePluginManager
|
from gramps.gen.plug import BasePluginManager
|
||||||
from gramps.gen.plug.docgen import (StyleSheet, StyleSheetList, PaperStyle,
|
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,
|
from gramps.gen.plug.menu import (FamilyOption, PersonOption, NoteOption,
|
||||||
MediaOption, PersonListOption, NumberOption,
|
MediaOption, PersonListOption, NumberOption,
|
||||||
BooleanOption, DestinationOption, StringOption,
|
BooleanOption, DestinationOption, StringOption,
|
||||||
@ -54,8 +55,8 @@ from gramps.gen.plug.menu import (FamilyOption, PersonOption, NoteOption,
|
|||||||
from gramps.gen.display.name import displayer as name_displayer
|
from gramps.gen.display.name import displayer as name_displayer
|
||||||
from gramps.gen.errors import ReportError, FilterError
|
from gramps.gen.errors import ReportError, FilterError
|
||||||
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
||||||
CATEGORY_GRAPHVIZ, CATEGORY_CODE,
|
CATEGORY_GRAPHVIZ, CATEGORY_TREE,
|
||||||
ReportOptions, append_styles)
|
CATEGORY_CODE, ReportOptions, append_styles)
|
||||||
from gramps.gen.plug.report._paper import paper_sizes
|
from gramps.gen.plug.report._paper import paper_sizes
|
||||||
from gramps.gen.const import USER_HOME
|
from gramps.gen.const import USER_HOME
|
||||||
from gramps.gen.dbstate import DbState
|
from gramps.gen.dbstate import DbState
|
||||||
@ -233,6 +234,15 @@ class CommandLineReport(object):
|
|||||||
if name not in self.option_class.options_dict:
|
if name not in self.option_class.options_dict:
|
||||||
self.option_class.options_dict[name] = \
|
self.option_class.options_dict[name] = \
|
||||||
menu.get_option_by_name(name).get_value()
|
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()
|
self.option_class.load_previous_values()
|
||||||
_validate_options(self.option_class, database)
|
_validate_options(self.option_class, database)
|
||||||
self.show = options_str_dict.pop('show', None)
|
self.show = options_str_dict.pop('show', None)
|
||||||
@ -301,6 +311,10 @@ class CommandLineReport(object):
|
|||||||
for graph_format in graphdoc.FORMATS:
|
for graph_format in graphdoc.FORMATS:
|
||||||
self.options_help['off'][2].append(
|
self.options_help['off'][2].append(
|
||||||
graph_format["type"] + "\t" + graph_format["descr"] )
|
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:
|
else:
|
||||||
self.options_help['off'][2] = "NA"
|
self.options_help['off'][2] = "NA"
|
||||||
|
|
||||||
@ -478,6 +492,15 @@ class CommandLineReport(object):
|
|||||||
# Pick the first one as the default.
|
# Pick the first one as the default.
|
||||||
self.format = graphdoc.FORMATS[0]["class"]
|
self.format = graphdoc.FORMATS[0]["class"]
|
||||||
_chosen_format = graphdoc.FORMATS[0]["type"]
|
_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:
|
else:
|
||||||
self.format = None
|
self.format = None
|
||||||
if _chosen_format and _format_str:
|
if _chosen_format and _format_str:
|
||||||
@ -640,7 +663,7 @@ def cl_report(database, name, category, report_class, options_class,
|
|||||||
clr.selected_style,
|
clr.selected_style,
|
||||||
PaperStyle(clr.paper,clr.orien,clr.marginl,
|
PaperStyle(clr.paper,clr.orien,clr.marginl,
|
||||||
clr.marginr,clr.margint,clr.marginb))
|
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.handler.doc = clr.format(
|
||||||
clr.option_class,
|
clr.option_class,
|
||||||
PaperStyle(clr.paper,clr.orien,clr.marginl,
|
PaperStyle(clr.paper,clr.orien,clr.marginl,
|
||||||
|
@ -27,7 +27,7 @@ The "plug" package for handling plugins in Gramps.
|
|||||||
from ._plugin import Plugin
|
from ._plugin import Plugin
|
||||||
from ._pluginreg import (PluginData, PluginRegister, REPORT, TOOL,
|
from ._pluginreg import (PluginData, PluginRegister, REPORT, TOOL,
|
||||||
CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE,
|
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_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX, TOOL_REVCTL,
|
||||||
TOOL_UTILS, CATEGORY_QR_MISC, CATEGORY_QR_PERSON,
|
TOOL_UTILS, CATEGORY_QR_MISC, CATEGORY_QR_PERSON,
|
||||||
CATEGORY_QR_FAMILY, CATEGORY_QR_EVENT, CATEGORY_QR_SOURCE,
|
CATEGORY_QR_FAMILY, CATEGORY_QR_EVENT, CATEGORY_QR_SOURCE,
|
||||||
@ -49,7 +49,7 @@ __all__ = [ "docbackend", "docgen", "menu", Plugin, PluginData,
|
|||||||
PluginRegister, BasePluginManager,
|
PluginRegister, BasePluginManager,
|
||||||
ImportPlugin, ExportPlugin, DocGenPlugin,
|
ImportPlugin, ExportPlugin, DocGenPlugin,
|
||||||
REPORT, TOOL, CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE,
|
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_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX, TOOL_REVCTL,
|
||||||
TOOL_UTILS, CATEGORY_QR_MISC, CATEGORY_QR_PERSON,
|
TOOL_UTILS, CATEGORY_QR_MISC, CATEGORY_QR_PERSON,
|
||||||
CATEGORY_QR_FAMILY, CATEGORY_QR_EVENT, CATEGORY_QR_SOURCE,
|
CATEGORY_QR_FAMILY, CATEGORY_QR_EVENT, CATEGORY_QR_SOURCE,
|
||||||
|
@ -94,8 +94,10 @@ CATEGORY_CODE = 2
|
|||||||
CATEGORY_WEB = 3
|
CATEGORY_WEB = 3
|
||||||
CATEGORY_BOOK = 4
|
CATEGORY_BOOK = 4
|
||||||
CATEGORY_GRAPHVIZ = 5
|
CATEGORY_GRAPHVIZ = 5
|
||||||
|
CATEGORY_TREE = 6
|
||||||
REPORT_CAT = [ CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE,
|
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
|
#possible tool categories
|
||||||
TOOL_DEBUG = -1
|
TOOL_DEBUG = -1
|
||||||
TOOL_ANAL = 0
|
TOOL_ANAL = 0
|
||||||
@ -1009,6 +1011,7 @@ def make_environment(**kwargs):
|
|||||||
'CATEGORY_WEB': CATEGORY_WEB,
|
'CATEGORY_WEB': CATEGORY_WEB,
|
||||||
'CATEGORY_BOOK': CATEGORY_BOOK,
|
'CATEGORY_BOOK': CATEGORY_BOOK,
|
||||||
'CATEGORY_GRAPHVIZ': CATEGORY_GRAPHVIZ,
|
'CATEGORY_GRAPHVIZ': CATEGORY_GRAPHVIZ,
|
||||||
|
'CATEGORY_TREE': CATEGORY_TREE,
|
||||||
'TOOL_DEBUG': TOOL_DEBUG,
|
'TOOL_DEBUG': TOOL_DEBUG,
|
||||||
'TOOL_ANAL': TOOL_ANAL,
|
'TOOL_ANAL': TOOL_ANAL,
|
||||||
'TOOL_DBPROC': TOOL_DBPROC,
|
'TOOL_DBPROC': TOOL_DBPROC,
|
||||||
|
@ -37,3 +37,4 @@ from .textdoc import TextDoc, IndexMark,INDEX_TYPE_ALP, INDEX_TYPE_TOC,\
|
|||||||
URL_PATTERN, LOCAL_HYPERLINK, LOCAL_TARGET
|
URL_PATTERN, LOCAL_HYPERLINK, LOCAL_TARGET
|
||||||
from .drawdoc import DrawDoc
|
from .drawdoc import DrawDoc
|
||||||
from .graphdoc import GVDoc
|
from .graphdoc import GVDoc
|
||||||
|
from .treedoc import TreeDoc
|
||||||
|
632
gramps/gen/plug/docgen/treedoc.py
Normal file
632
gramps/gen/plug/docgen/treedoc.py
Normal file
@ -0,0 +1,632 @@
|
|||||||
|
#
|
||||||
|
# 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':
|
||||||
|
male_bg = config.get('preferences.color-gender-male-death')[1:]
|
||||||
|
female_bg = config.get('preferences.color-gender-female-death')[1:]
|
||||||
|
neuter_bg = config.get('preferences.color-gender-unknown-death')[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_object_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}]
|
@ -39,7 +39,7 @@ import os
|
|||||||
|
|
||||||
# Report categories
|
# Report categories
|
||||||
from .. import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE, CATEGORY_WEB,
|
from .. import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_CODE, CATEGORY_WEB,
|
||||||
CATEGORY_BOOK, CATEGORY_GRAPHVIZ)
|
CATEGORY_BOOK, CATEGORY_GRAPHVIZ, CATEGORY_TREE)
|
||||||
|
|
||||||
standalone_categories = {
|
standalone_categories = {
|
||||||
CATEGORY_TEXT : ("RepText", _("Text Reports")),
|
CATEGORY_TEXT : ("RepText", _("Text Reports")),
|
||||||
@ -48,6 +48,7 @@ standalone_categories = {
|
|||||||
CATEGORY_WEB : ("RepWeb", _("Web Pages")),
|
CATEGORY_WEB : ("RepWeb", _("Web Pages")),
|
||||||
CATEGORY_BOOK : ("RepBook", _("Books")),
|
CATEGORY_BOOK : ("RepBook", _("Books")),
|
||||||
CATEGORY_GRAPHVIZ : ("Graphs", _("Graphs")),
|
CATEGORY_GRAPHVIZ : ("Graphs", _("Graphs")),
|
||||||
|
CATEGORY_TREE : ("Trees", _("Trees")),
|
||||||
}
|
}
|
||||||
book_categories = {
|
book_categories = {
|
||||||
CATEGORY_TEXT : _("Text"),
|
CATEGORY_TEXT : _("Text"),
|
||||||
|
288
gramps/gui/plug/report/_graphreportdialog.py
Normal file
288
gramps/gui/plug/report/_graphreportdialog.py
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
#
|
||||||
|
# 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
|
||||||
|
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
||||||
|
_ = glocale.translation.gettext
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GTK+ modules
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GObject
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# GRAMPS modules
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
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
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# BaseFormatComboBox
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
class BaseFormatComboBox(Gtk.ComboBox):
|
||||||
|
"""
|
||||||
|
Combo box base class for graph-based report format choices.
|
||||||
|
"""
|
||||||
|
FORMATS=[]
|
||||||
|
|
||||||
|
def set(self, active=None):
|
||||||
|
self.store = Gtk.ListStore(GObject.TYPE_STRING)
|
||||||
|
self.set_model(self.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"]
|
||||||
|
self.store.append(row=[name])
|
||||||
|
if item['type'] == active:
|
||||||
|
active_index = index
|
||||||
|
index += 1
|
||||||
|
self.set_active(active_index)
|
||||||
|
|
||||||
|
def get_label(self):
|
||||||
|
return self.FORMATS[self.get_active()]["descr"]
|
||||||
|
|
||||||
|
def get_reference(self):
|
||||||
|
return self.FORMATS[self.get_active()]["class"]
|
||||||
|
|
||||||
|
def get_paper(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def get_styles(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def get_ext(self):
|
||||||
|
return '.%s' % self.FORMATS[self.get_active()]['ext']
|
||||||
|
|
||||||
|
def get_oformat_str(self): # the report's output-format type
|
||||||
|
return self.FORMATS[self.get_active()]["type"]
|
||||||
|
|
||||||
|
def is_file_output(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_clname(self):
|
||||||
|
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)
|
||||||
|
|
||||||
|
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(_("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
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
#
|
#
|
||||||
# Copyright (C) 2007-2008 Brian G. Matherly
|
# Copyright (C) 2017 Nick Hall
|
||||||
# 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
|
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# 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.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
#
|
#
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
"""class for generating dialogs for graphviz-based reports """
|
||||||
#
|
|
||||||
# python modules
|
|
||||||
#
|
|
||||||
#------------------------------------------------------------------------
|
|
||||||
import os
|
|
||||||
from gramps.gen.const import GRAMPS_LOCALE as glocale
|
|
||||||
_ = glocale.translation.gettext
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# GTK+ modules
|
# Gramps modules
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
from gi.repository import Gtk
|
from ._graphreportdialog import GraphReportDialog, BaseFormatComboBox
|
||||||
from gi.repository import GObject
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# GRAMPS modules
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------------
|
|
||||||
from gramps.gen.config import config
|
|
||||||
from gramps.gen.plug.report import CATEGORY_GRAPHVIZ
|
from gramps.gen.plug.report import CATEGORY_GRAPHVIZ
|
||||||
from ._reportdialog import ReportDialog
|
|
||||||
from ._papermenu import PaperFrame
|
|
||||||
import gramps.gen.plug.docgen.graphdoc as graphdoc
|
import gramps.gen.plug.docgen.graphdoc as graphdoc
|
||||||
from gramps.gen.plug.menu import Menu
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# GraphvizFormatComboBox
|
|
||||||
#
|
|
||||||
#-------------------------------------------------------------------------------
|
|
||||||
class GraphvizFormatComboBox(Gtk.ComboBox):
|
|
||||||
"""
|
|
||||||
Format combo box class for Graphviz report.
|
|
||||||
"""
|
|
||||||
def set(self, active=None):
|
|
||||||
self.store = Gtk.ListStore(GObject.TYPE_STRING)
|
|
||||||
self.set_model(self.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"]
|
|
||||||
self.store.append(row=[name])
|
|
||||||
if item['type'] == active:
|
|
||||||
active_index = index
|
|
||||||
index += 1
|
|
||||||
self.set_active(active_index)
|
|
||||||
|
|
||||||
def get_label(self):
|
|
||||||
return graphdoc.FORMATS[self.get_active()]["descr"]
|
|
||||||
|
|
||||||
def get_reference(self):
|
|
||||||
return graphdoc.FORMATS[self.get_active()]["class"]
|
|
||||||
|
|
||||||
def get_paper(self):
|
|
||||||
return 1
|
|
||||||
|
|
||||||
def get_styles(self):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def get_ext(self):
|
|
||||||
return '.%s' % graphdoc.FORMATS[self.get_active()]['ext']
|
|
||||||
|
|
||||||
def get_oformat_str(self): # the report's output-format type
|
|
||||||
return graphdoc.FORMATS[self.get_active()]["type"]
|
|
||||||
|
|
||||||
def is_file_output(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_clname(self):
|
|
||||||
return graphdoc.FORMATS[self.get_active()]["type"]
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# GraphvizReportDialog
|
# GraphvizReportDialog
|
||||||
#
|
#
|
||||||
#-----------------------------------------------------------------------
|
#-----------------------------------------------------------------------
|
||||||
class GraphvizReportDialog(ReportDialog):
|
class GraphvizReportDialog(GraphReportDialog):
|
||||||
"""A class of ReportDialog customized for graphviz 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 = CATEGORY_GRAPHVIZ
|
|
||||||
self.__gvoptions = graphdoc.GVOptions()
|
|
||||||
self.dbname = dbstate.db.get_dbname()
|
|
||||||
ReportDialog.__init__(self, dbstate, uistate, opt,
|
|
||||||
name, translated_name)
|
|
||||||
|
|
||||||
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):
|
def make_doc_menu(self):
|
||||||
ReportDialog.init_interface(self)
|
"""
|
||||||
self.doc_type_changed(self.format_menu)
|
Build a menu of document types that are appropriate for
|
||||||
self.notebook.set_current_page(1) # don't start on "Paper Options"
|
this graph report.
|
||||||
|
"""
|
||||||
def setup_format_frame(self):
|
|
||||||
"""Set up the format frame of the dialog."""
|
|
||||||
self.format_menu = GraphvizFormatComboBox()
|
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(_("Open with default viewer"))
|
def get_category(self):
|
||||||
self.open_with_app.set_active(
|
"""
|
||||||
config.get('interface.open-with-default-viewer'))
|
Return the report category.
|
||||||
self.grid.attach(self.open_with_app, 2, self.row, 2, 1)
|
"""
|
||||||
self.row += 1
|
return CATEGORY_GRAPHVIZ
|
||||||
|
|
||||||
ext = self.format_menu.get_ext()
|
def get_options(self):
|
||||||
if ext is None:
|
"""
|
||||||
ext = ""
|
Return the graph options.
|
||||||
else:
|
"""
|
||||||
spath = self.get_default_directory()
|
return graphdoc.GVOptions()
|
||||||
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):
|
def doc_type_changed(self, obj):
|
||||||
"""
|
"""
|
||||||
@ -201,81 +64,31 @@ class GraphvizReportDialog(ReportDialog):
|
|||||||
paper size/orientation options, but it does need a template
|
paper size/orientation options, but it does need a template
|
||||||
file. Those changes are made here.
|
file. Those changes are made here.
|
||||||
"""
|
"""
|
||||||
self.open_with_app.set_sensitive(True)
|
GraphReportDialog.doc_type_changed(self, obj)
|
||||||
|
|
||||||
fname = self.target_fileentry.get_full_path(0)
|
|
||||||
(spath, ext) = os.path.splitext(fname)
|
|
||||||
|
|
||||||
ext_val = obj.get_ext()
|
output_format_str = obj.get_clname()
|
||||||
if ext_val:
|
|
||||||
fname = spath + ext_val
|
|
||||||
else:
|
|
||||||
fname = spath
|
|
||||||
self.target_fileentry.set_filename(fname)
|
|
||||||
|
|
||||||
output_format_str = obj.get_oformat_str()
|
|
||||||
if output_format_str in ['gvpdf', 'gspdf', 'ps']:
|
if output_format_str in ['gvpdf', 'gspdf', 'ps']:
|
||||||
# Always use 72 DPI for PostScript and PDF files.
|
# Always use 72 DPI for PostScript and PDF files.
|
||||||
self.__gvoptions.dpi.set_value(72)
|
self._goptions.dpi.set_value(72)
|
||||||
self.__gvoptions.dpi.set_available(False)
|
self._goptions.dpi.set_available(False)
|
||||||
else:
|
else:
|
||||||
self.__gvoptions.dpi.set_available(True)
|
self._goptions.dpi.set_available(True)
|
||||||
|
|
||||||
if output_format_str in ['gspdf', 'dot']:
|
if output_format_str in ['gspdf', 'dot']:
|
||||||
# Multiple pages only valid for dot and PDF via GhostsScript.
|
# Multiple pages only valid for dot and PDF via GhostsScript.
|
||||||
self.__gvoptions.h_pages.set_available(True)
|
self._goptions.h_pages.set_available(True)
|
||||||
self.__gvoptions.v_pages.set_available(True)
|
self._goptions.v_pages.set_available(True)
|
||||||
else:
|
else:
|
||||||
self.__gvoptions.h_pages.set_value(1)
|
self._goptions.h_pages.set_value(1)
|
||||||
self.__gvoptions.v_pages.set_value(1)
|
self._goptions.v_pages.set_value(1)
|
||||||
self.__gvoptions.h_pages.set_available(False)
|
self._goptions.h_pages.set_available(False)
|
||||||
self.__gvoptions.v_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()
|
# GraphvizFormatComboBox
|
||||||
|
#
|
||||||
# Preparation
|
#-------------------------------------------------------------------------------
|
||||||
self.parse_format_frame()
|
class GraphvizFormatComboBox(BaseFormatComboBox):
|
||||||
self.parse_user_options()
|
FORMATS = graphdoc.FORMATS
|
||||||
|
|
||||||
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
|
|
||||||
|
@ -54,8 +54,9 @@ from .. import add_gui_options, make_gui_option
|
|||||||
from ...user import User
|
from ...user import User
|
||||||
from ...dialog import ErrorDialog, OptionDialog
|
from ...dialog import ErrorDialog, OptionDialog
|
||||||
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
from gramps.gen.plug.report import (CATEGORY_TEXT, CATEGORY_DRAW, CATEGORY_BOOK,
|
||||||
CATEGORY_CODE, CATEGORY_WEB, CATEGORY_GRAPHVIZ,
|
CATEGORY_CODE, CATEGORY_WEB,
|
||||||
standalone_categories)
|
CATEGORY_GRAPHVIZ, CATEGORY_TREE,
|
||||||
|
standalone_categories)
|
||||||
from gramps.gen.plug.docgen import StyleSheet, StyleSheetList
|
from gramps.gen.plug.docgen import StyleSheet, StyleSheetList
|
||||||
from ...managedwindow import ManagedWindow
|
from ...managedwindow import ManagedWindow
|
||||||
from ._stylecombobox import StyleComboBox
|
from ._stylecombobox import StyleComboBox
|
||||||
@ -673,6 +674,9 @@ def report(dbstate, uistate, person, report_class, options_class,
|
|||||||
elif category == CATEGORY_GRAPHVIZ:
|
elif category == CATEGORY_GRAPHVIZ:
|
||||||
from ._graphvizreportdialog import GraphvizReportDialog
|
from ._graphvizreportdialog import GraphvizReportDialog
|
||||||
dialog_class = GraphvizReportDialog
|
dialog_class = GraphvizReportDialog
|
||||||
|
elif category == CATEGORY_TREE:
|
||||||
|
from ._treereportdialog import TreeReportDialog
|
||||||
|
dialog_class = TreeReportDialog
|
||||||
elif category == CATEGORY_WEB:
|
elif category == CATEGORY_WEB:
|
||||||
from ._webreportdialog import WebReportDialog
|
from ._webreportdialog import WebReportDialog
|
||||||
dialog_class = 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
|
@ -318,6 +318,7 @@ gramps/gen/plug/_pluginreg.py
|
|||||||
gramps/gen/plug/docbackend/docbackend.py
|
gramps/gen/plug/docbackend/docbackend.py
|
||||||
gramps/gen/plug/docgen/graphdoc.py
|
gramps/gen/plug/docgen/graphdoc.py
|
||||||
gramps/gen/plug/docgen/paperstyle.py
|
gramps/gen/plug/docgen/paperstyle.py
|
||||||
|
gramps/gen/plug/docgen/treedoc.py
|
||||||
gramps/gen/plug/menu/_enumeratedlist.py
|
gramps/gen/plug/menu/_enumeratedlist.py
|
||||||
gramps/gen/plug/report/_book.py
|
gramps/gen/plug/report/_book.py
|
||||||
gramps/gen/plug/report/_constants.py
|
gramps/gen/plug/report/_constants.py
|
||||||
|
Loading…
x
Reference in New Issue
Block a user