more work-in-progress for GraphViz and FamilyLines
svn: r9650
This commit is contained in:
@@ -1,3 +1,8 @@
|
|||||||
|
2007-12-30 Stéphane Charette <stephanecharette@gmail.com>
|
||||||
|
* src/ReportBase/_GraphvizReportDialog.py:
|
||||||
|
* src/plugins/GVFamilyLines.py: more work-in-progress on GraphViz and
|
||||||
|
getting FamilyLines to function in the new framework
|
||||||
|
|
||||||
2007-12-30 Douglas S. Blank <dblank@cs.brynmawr.edu>
|
2007-12-30 Douglas S. Blank <dblank@cs.brynmawr.edu>
|
||||||
* src/Config/_GrampsConfigKeys.py: added MyGrampsView
|
* src/Config/_GrampsConfigKeys.py: added MyGrampsView
|
||||||
* src/Config/_GrampsGconfKeys.py: added try/excepts on get_types
|
* src/Config/_GrampsGconfKeys.py: added try/excepts on get_types
|
||||||
|
@@ -207,67 +207,69 @@ class GVDocBase(BaseDoc.BaseDoc,BaseDoc.GVDoc):
|
|||||||
|
|
||||||
self.write( '}' )
|
self.write( '}' )
|
||||||
|
|
||||||
def add_node(self, id, label, shape="", color = "",
|
def add_node(self, id, label, shape="", color="",
|
||||||
style="", fillcolor="", url="" ):
|
style="", fillcolor="", url="", htmloutput=False ):
|
||||||
"""
|
"""
|
||||||
Add a node to this graph. Nodes can be different shapes like boxes and
|
Add a node to this graph. Nodes can be different shapes like boxes and
|
||||||
circles.
|
circles.
|
||||||
|
|
||||||
Implementes BaseDoc.GVDoc.add_node().
|
Implements BaseDoc.GVDoc.add_node().
|
||||||
"""
|
"""
|
||||||
line = ' "%s" [' % id
|
text = '['
|
||||||
|
|
||||||
if label.startswith("<"):
|
|
||||||
# This must be HTML
|
|
||||||
line += 'label=<%s>' % label
|
|
||||||
else:
|
|
||||||
line += 'label="%s"' % label
|
|
||||||
|
|
||||||
if shape:
|
if shape:
|
||||||
line += ', shape="%s"' % shape
|
text += ' shape="%s"' % shape
|
||||||
|
|
||||||
if color:
|
if color:
|
||||||
line += ', color="%s"' % color
|
text += ' color="%s"' % color
|
||||||
|
|
||||||
if fillcolor:
|
if fillcolor:
|
||||||
line += ', fillcolor="%s"' % fillcolor
|
text += ' fillcolor="%s"' % fillcolor
|
||||||
|
|
||||||
if style:
|
if style:
|
||||||
line += ', style="%s"' % style
|
text += ' style="%s"' % style
|
||||||
|
|
||||||
|
# note that we always output a label -- even if an empty string --
|
||||||
|
# otherwise GraphViz uses the node ID as the label which is unlikely
|
||||||
|
# to be what the user wants to see in the graph
|
||||||
|
if label.startswith("<") or htmloutput:
|
||||||
|
text += ' label=<%s>' % label
|
||||||
|
else:
|
||||||
|
text += ' label="%s"' % label
|
||||||
|
|
||||||
if url:
|
if url:
|
||||||
line += ', URL="%s"' % url
|
text += ' URL="%s"' % url
|
||||||
|
|
||||||
line += '];\n'
|
text += " ]"
|
||||||
|
self.write(' %s %s;\n' % (id, text))
|
||||||
|
|
||||||
self.write(line)
|
def add_link(self, id1, id2, style="", head="", tail="", comment=""):
|
||||||
|
|
||||||
def add_link(self, id1, id2, style="", head="", tail=""):
|
|
||||||
"""
|
"""
|
||||||
Add a link between two nodes.
|
Add a link between two nodes.
|
||||||
|
|
||||||
Implementes BaseDoc.GVDoc.add_link().
|
Implementes BaseDoc.GVDoc.add_link().
|
||||||
"""
|
"""
|
||||||
self.write(' "%s" -> "%s"' % (id1, id2))
|
self.write(' %s -> %s' % (id1, id2))
|
||||||
|
|
||||||
if style or head or tail:
|
if style or head or tail:
|
||||||
self.write(' [')
|
self.write(' [')
|
||||||
|
|
||||||
if style:
|
if style:
|
||||||
self.write('style=%s' % style)
|
self.write(' style=%s' % style)
|
||||||
if head:
|
if head:
|
||||||
if style:
|
self.write(' arrowhead=%s' % head)
|
||||||
self.write(', ')
|
|
||||||
self.write('arrowhead=%s' % head)
|
|
||||||
if tail:
|
if tail:
|
||||||
if style or head:
|
self.write(' arrowtail=%s' % tail)
|
||||||
self.write(', ')
|
|
||||||
self.write('arrowtail=%s' % tail)
|
|
||||||
|
|
||||||
self.write(']')
|
self.write(' ]')
|
||||||
|
|
||||||
self.write(';\n')
|
self.write(';')
|
||||||
|
|
||||||
|
if comment:
|
||||||
|
self.write(' // %s' % comment)
|
||||||
|
|
||||||
|
self.write('\n')
|
||||||
|
|
||||||
def start_subgraph(self,id):
|
def start_subgraph(self,id):
|
||||||
self.write(' subgraph cluster_%s\n' % id)
|
self.write(' subgraph cluster_%s\n' % id)
|
||||||
self.write(' {\n')
|
self.write(' {\n')
|
||||||
|
@@ -69,14 +69,12 @@ from ReportBase import Report, MenuReportOptions, MODE_GUI, MODE_CLI, CATEGORY_G
|
|||||||
from ReportBase._ReportDialog import ReportDialog
|
from ReportBase._ReportDialog import ReportDialog
|
||||||
from PluginUtils import register_report, FilterListOption, EnumeratedListOption, BooleanOption, NumberOption, ColourButtonOption, PersonListOption
|
from PluginUtils import register_report, FilterListOption, EnumeratedListOption, BooleanOption, NumberOption, ColourButtonOption, PersonListOption
|
||||||
from QuestionDialog import ErrorDialog, WarningDialog
|
from QuestionDialog import ErrorDialog, WarningDialog
|
||||||
|
from BasicUtils import name_displayer as _nd
|
||||||
#from NameDisplay import displayer as _nd # Gramps version < 3.0
|
|
||||||
from BasicUtils import name_displayer as _nd # Gramps version >= 3.0
|
|
||||||
|
|
||||||
from DateHandler import displayer as _dd
|
from DateHandler import displayer as _dd
|
||||||
from DateHandler import parser
|
from DateHandler import parser
|
||||||
from Selectors import selector_factory
|
from Selectors import selector_factory
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# A quick overview of the classes we'll be using:
|
# A quick overview of the classes we'll be using:
|
||||||
@@ -111,11 +109,9 @@ class FamilyLinesOptions(MenuReportOptions):
|
|||||||
category = _('People of Interest')
|
category = _('People of Interest')
|
||||||
# --------------------------------
|
# --------------------------------
|
||||||
|
|
||||||
peoplePicker = PersonListOption( _('People of interest'),
|
personList = PersonListOption( _('People of interest'), '', dbstate)
|
||||||
'',
|
personList.set_help( _('People of interest are used as a starting point when determining \"family lines\".'))
|
||||||
dbstate )
|
menu.add_option(category, 'FLgidlist', personList)
|
||||||
peoplePicker.set_help( _('People of interest are used as a starting point when determining \"family lines\".'))
|
|
||||||
menu.add_option(category, 'FLgidlist', peoplePicker)
|
|
||||||
|
|
||||||
followParents = BooleanOption( _('Follow parents to determine family lines'), True)
|
followParents = BooleanOption( _('Follow parents to determine family lines'), True)
|
||||||
followParents.set_help( _('Parents and their ancestors will be considered when determining "family lines".'))
|
followParents.set_help( _('Parents and their ancestors will be considered when determining "family lines".'))
|
||||||
@@ -189,6 +185,13 @@ class FamilyLinesOptions(MenuReportOptions):
|
|||||||
category = _('Options')
|
category = _('Options')
|
||||||
# ---------------------
|
# ---------------------
|
||||||
|
|
||||||
|
useSubgraphs = BooleanOption(_('Use subgraphs'), False)
|
||||||
|
useSubgraphs.set_help(_("Subgraphs can help GraphViz position "
|
||||||
|
"certain linked nodes closer together, "
|
||||||
|
"but with non-trivial graphs will result "
|
||||||
|
"in longer lines and larger graphs."))
|
||||||
|
menu.add_option(category, "FLuseSubgraphs", useSubgraphs)
|
||||||
|
|
||||||
includeDates = BooleanOption( _('Include dates'), True)
|
includeDates = BooleanOption( _('Include dates'), True)
|
||||||
includeDates.set_help( _('Whether to include dates for people and families.'))
|
includeDates.set_help( _('Whether to include dates for people and families.'))
|
||||||
menu.add_option(category, 'FLincludeDates', includeDates)
|
menu.add_option(category, 'FLincludeDates', includeDates)
|
||||||
@@ -209,13 +212,6 @@ class FamilyLinesOptions(MenuReportOptions):
|
|||||||
includePrivate.set_help( _('Whether to include names, dates, and families that are marked as private.'))
|
includePrivate.set_help( _('Whether to include names, dates, and families that are marked as private.'))
|
||||||
menu.add_option(category, 'FLincludePrivate', includePrivate)
|
menu.add_option(category, 'FLincludePrivate', includePrivate)
|
||||||
|
|
||||||
usesubgraphs = BooleanOption(_('Use subgraphs'), False)
|
|
||||||
usesubgraphs.set_help(_("Subgraphs can help GraphViz position "
|
|
||||||
"certain linked nodes closer together, "
|
|
||||||
"but with non-trivial graphs will result "
|
|
||||||
"in longer lines and larger graphs."))
|
|
||||||
menu.add_option(category, "usesubgraphs", usesubgraphs)
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@@ -243,7 +239,6 @@ class FamilyLinesReport(Report):
|
|||||||
self.deletedPeople = 0
|
self.deletedPeople = 0
|
||||||
self.deletedFamilies = 0
|
self.deletedFamilies = 0
|
||||||
|
|
||||||
self.useSubgraphs = options.handler.options_dict['usesubgraphs' ]
|
|
||||||
self.followParents = options.handler.options_dict['FLfollowParents' ]
|
self.followParents = options.handler.options_dict['FLfollowParents' ]
|
||||||
self.followChildren = options.handler.options_dict['FLfollowChildren' ]
|
self.followChildren = options.handler.options_dict['FLfollowChildren' ]
|
||||||
self.removeExtraPeople = options.handler.options_dict['FLremoveExtraPeople' ]
|
self.removeExtraPeople = options.handler.options_dict['FLremoveExtraPeople' ]
|
||||||
@@ -258,6 +253,7 @@ class FamilyLinesReport(Report):
|
|||||||
self.maxChildren = options.handler.options_dict['FLmaxChildren' ]
|
self.maxChildren = options.handler.options_dict['FLmaxChildren' ]
|
||||||
self.includeImages = options.handler.options_dict['FLincludeImages' ]
|
self.includeImages = options.handler.options_dict['FLincludeImages' ]
|
||||||
self.imageOnTheSide = options.handler.options_dict['FLimageOnTheSide' ]
|
self.imageOnTheSide = options.handler.options_dict['FLimageOnTheSide' ]
|
||||||
|
self.useSubgraphs = options.handler.options_dict['FLuseSubgraphs' ]
|
||||||
self.includeDates = options.handler.options_dict['FLincludeDates' ]
|
self.includeDates = options.handler.options_dict['FLincludeDates' ]
|
||||||
self.includePlaces = options.handler.options_dict['FLincludePlaces' ]
|
self.includePlaces = options.handler.options_dict['FLincludePlaces' ]
|
||||||
self.includeNumChildren = options.handler.options_dict['FLincludeNumChildren' ]
|
self.includeNumChildren = options.handler.options_dict['FLincludeNumChildren' ]
|
||||||
@@ -319,6 +315,21 @@ class FamilyLinesReport(Report):
|
|||||||
|
|
||||||
# now that begin_report() has done the work, output what we've
|
# now that begin_report() has done the work, output what we've
|
||||||
# obtained into whatever file or format the user expects to use
|
# obtained into whatever file or format the user expects to use
|
||||||
|
|
||||||
|
self.doc.write('# Number of people in database: %d\n' % self.db.get_number_of_people())
|
||||||
|
self.doc.write('# Number of people of interest: %d\n' % len(self.peopleToOutput))
|
||||||
|
self.doc.write('# Number of families in database: %d\n' % self.db.get_number_of_families())
|
||||||
|
self.doc.write('# Number of families of interest: %d\n' % len(self.familiesToOutput))
|
||||||
|
if self.removeExtraPeople:
|
||||||
|
self.doc.write('# Additional people removed: %d\n' % self.deletedPeople)
|
||||||
|
self.doc.write('# Additional families removed: %d\n' % self.deletedFamilies)
|
||||||
|
self.doc.write('# Initial list of people of interest:\n')
|
||||||
|
for handle in self.interestSet:
|
||||||
|
person = self.db.get_person_from_handle(handle)
|
||||||
|
gid = person.get_gramps_id()
|
||||||
|
name = person.get_primary_name().get_regular_name()
|
||||||
|
self.doc.write('# -> %s, %s\n' % (gid, name))
|
||||||
|
|
||||||
self.writePeople()
|
self.writePeople()
|
||||||
self.writeFamilies()
|
self.writeFamilies()
|
||||||
self.progress.close()
|
self.progress.close()
|
||||||
@@ -597,6 +608,9 @@ class FamilyLinesReport(Report):
|
|||||||
|
|
||||||
|
|
||||||
def writePeople(self):
|
def writePeople(self):
|
||||||
|
|
||||||
|
self.doc.write('\n')
|
||||||
|
|
||||||
# if we're going to attempt to include images, then use the HTML style of .dot file
|
# if we're going to attempt to include images, then use the HTML style of .dot file
|
||||||
bUseHtmlOutput = False
|
bUseHtmlOutput = False
|
||||||
if self.includeImages:
|
if self.includeImages:
|
||||||
@@ -722,10 +736,18 @@ class FamilyLinesReport(Report):
|
|||||||
if imagePath:
|
if imagePath:
|
||||||
label += '</TD></TR></TABLE>'
|
label += '</TD></TR></TABLE>'
|
||||||
|
|
||||||
self.doc.add_node(person.get_gramps_id(),label,"box","","filled",colour)
|
self.doc.add_node(
|
||||||
|
id=person.get_gramps_id(),
|
||||||
|
label=label,
|
||||||
|
shape='box',
|
||||||
|
fillcolor=colour,
|
||||||
|
htmloutput=bUseHtmlOutput)
|
||||||
|
|
||||||
|
|
||||||
def writeFamilies(self):
|
def writeFamilies(self):
|
||||||
|
|
||||||
|
self.doc.write('\n')
|
||||||
|
|
||||||
# loop through all the families we need to output
|
# loop through all the families we need to output
|
||||||
for familyHandle in self.familiesToOutput:
|
for familyHandle in self.familiesToOutput:
|
||||||
self.progress.step()
|
self.progress.step()
|
||||||
@@ -798,17 +820,21 @@ class FamilyLinesReport(Report):
|
|||||||
if self.useSubgraphs and fatherHandle and motherHandle:
|
if self.useSubgraphs and fatherHandle and motherHandle:
|
||||||
self.doc.start_subgraph(fgid)
|
self.doc.start_subgraph(fgid)
|
||||||
|
|
||||||
|
self.doc.write('\n')
|
||||||
|
|
||||||
# see if we have a father to link to this family
|
# see if we have a father to link to this family
|
||||||
if fatherHandle:
|
if fatherHandle:
|
||||||
if fatherHandle in self.peopleToOutput:
|
if fatherHandle in self.peopleToOutput:
|
||||||
father = self.db.get_person_from_handle(fatherHandle)
|
father = self.db.get_person_from_handle(fatherHandle)
|
||||||
self.doc.add_link(fgid, father.get_gramps_id())
|
comment = "father: %s" % father.get_primary_name().get_regular_name()
|
||||||
|
self.doc.add_link(fgid, father.get_gramps_id(), comment=comment)
|
||||||
|
|
||||||
# see if we have a mother to link to this family
|
# see if we have a mother to link to this family
|
||||||
if motherHandle:
|
if motherHandle:
|
||||||
if motherHandle in self.peopleToOutput:
|
if motherHandle in self.peopleToOutput:
|
||||||
mother = self.db.get_person_from_handle(motherHandle)
|
mother = self.db.get_person_from_handle(motherHandle)
|
||||||
self.doc.add_link(fgid, mother.get_gramps_id())
|
comment = "mother: %s" % mother.get_primary_name().get_regular_name()
|
||||||
|
self.doc.add_link(fgid, mother.get_gramps_id(), comment=comment)
|
||||||
|
|
||||||
if self.useSubgraphs and fatherHandle and motherHandle:
|
if self.useSubgraphs and fatherHandle and motherHandle:
|
||||||
self.doc.end_subgraph()
|
self.doc.end_subgraph()
|
||||||
@@ -817,7 +843,8 @@ class FamilyLinesReport(Report):
|
|||||||
for childRef in family.get_child_ref_list():
|
for childRef in family.get_child_ref_list():
|
||||||
if childRef.ref in self.peopleToOutput:
|
if childRef.ref in self.peopleToOutput:
|
||||||
child = self.db.get_person_from_handle(childRef.ref)
|
child = self.db.get_person_from_handle(childRef.ref)
|
||||||
self.doc.add_link(child.get_gramps_id(), fgid)
|
comment = "child: %s" % child.get_primary_name().get_regular_name()
|
||||||
|
self.doc.add_link(child.get_gramps_id(), fgid, comment=comment)
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
@@ -829,12 +856,12 @@ class FamilyLinesReport(Report):
|
|||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
register_report(
|
register_report(
|
||||||
name = 'familylines_graph',
|
name = 'familylines_graph',
|
||||||
|
translated_name = _("Family Lines Graph"),
|
||||||
category = CATEGORY_GRAPHVIZ,
|
category = CATEGORY_GRAPHVIZ,
|
||||||
report_class = FamilyLinesReport, # must implement write_report(), called by report() in _ReportDialog.py
|
report_class = FamilyLinesReport, # must implement write_report(), called by report() in _ReportDialog.py
|
||||||
options_class = FamilyLinesOptions, # must implement add_menu_options(), called by MenuOptions::__init__()
|
options_class = FamilyLinesOptions, # must implement add_menu_options(), called by MenuOptions::__init__()
|
||||||
modes = MODE_GUI,
|
modes = MODE_GUI,
|
||||||
status = _("Stable"),
|
status = _("Stable"),
|
||||||
translated_name = _("Family Lines Graph"),
|
|
||||||
author_name = "Stephane Charette",
|
author_name = "Stephane Charette",
|
||||||
author_email = "stephanecharette@gmail.com",
|
author_email = "stephanecharette@gmail.com",
|
||||||
description =_("Generates family line graphs using GraphViz."),
|
description =_("Generates family line graphs using GraphViz."),
|
||||||
|
Reference in New Issue
Block a user