add_comment() and work in progress for the new GraphViz framework
svn: r9679
This commit is contained in:
parent
a8a6c017e6
commit
95496e6449
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
||||
2008-01-02 Stéphane Charette <stephanecharette@gmail.com>
|
||||
* src/BaseDoc.py: definition of add_comment()
|
||||
* src/ReportBase/_GraphvizReportDialog.py: implement add_comment()
|
||||
* src/plugins/GVFamilyLines.py:
|
||||
* src/PluginUtils/__init__.py:
|
||||
* src/PluginUtils/_MenuOptions.py: work in progress to migrate the
|
||||
FamilyLines plugin to the new GraphViz framework; new menu option
|
||||
widget called "SurnameColourOption" (which is actually quite specific
|
||||
to the FamilyLines plugin)
|
||||
|
||||
2008-01-01 Peter Landgren <peter.talken@telia.com>
|
||||
* src/plugins/rel_sv.py: Added some comments
|
||||
|
||||
|
@ -1587,7 +1587,7 @@ class GVDoc:
|
||||
@return: nothing
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def add_link(self, id1, id2, style="", head="", tail="", comment=""):
|
||||
"""
|
||||
Add a link between two nodes.
|
||||
@ -1604,7 +1604,18 @@ class GVDoc:
|
||||
@return: nothing
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def add_comment(self, comment):
|
||||
"""
|
||||
Add a comment to the source file.
|
||||
|
||||
@param comment: A text string to add as a comment.
|
||||
Example: "Next comes the individuals."
|
||||
@type comment: string
|
||||
@return: nothing
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def start_subgraph(self,id):
|
||||
"""
|
||||
Start a subgraph in this graph.
|
||||
@ -1615,7 +1626,7 @@ class GVDoc:
|
||||
@return: nothing
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def end_subgraph(self):
|
||||
"""
|
||||
End a subgraph that was previously started in this graph.
|
||||
|
@ -27,12 +27,103 @@ Abstracted option handling.
|
||||
# gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
import gobject
|
||||
import Utils
|
||||
import _Tool as Tool
|
||||
import GrampsWidgets
|
||||
import ManagedWindow
|
||||
from Selectors import selector_factory
|
||||
from BasicUtils import name_displayer as _nd
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Dialog window used to select a surname
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
class LastNameDialog(ManagedWindow.ManagedWindow):
|
||||
|
||||
def __init__(self, database, uistate, track, surnames, skipList=set()):
|
||||
|
||||
self.title = _('Select surname')
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, track, self)
|
||||
self.dlg = gtk.Dialog(
|
||||
None,
|
||||
uistate.window,
|
||||
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
|
||||
self.dlg.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
self.set_window(self.dlg, None, self.title)
|
||||
self.window.set_default_size(400,400)
|
||||
|
||||
# build up a container to display all of the people of interest
|
||||
self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
|
||||
self.treeView = gtk.TreeView(self.model)
|
||||
col1 = gtk.TreeViewColumn(_('Surname'), gtk.CellRendererText(), text=0)
|
||||
col2 = gtk.TreeViewColumn(_('Count'), gtk.CellRendererText(), text=1)
|
||||
col1.set_resizable(True)
|
||||
col2.set_resizable(True)
|
||||
col1.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
|
||||
col2.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
|
||||
col1.set_sort_column_id(0)
|
||||
col2.set_sort_column_id(1)
|
||||
self.treeView.append_column(col1)
|
||||
self.treeView.append_column(col2)
|
||||
self.scrolledWindow = gtk.ScrolledWindow()
|
||||
self.scrolledWindow.add(self.treeView)
|
||||
self.scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.scrolledWindow.set_shadow_type(gtk.SHADOW_OUT)
|
||||
self.dlg.vbox.pack_start(self.scrolledWindow, expand=True, fill=True)
|
||||
self.scrolledWindow.show_all()
|
||||
|
||||
if len(surnames) == 0:
|
||||
# we could use database.get_surname_list(), but if we do that
|
||||
# all we get is a list of names without a count...therefore
|
||||
# we'll traverse the entire database ourself and build up a
|
||||
# list that we can use
|
||||
# for name in database.get_surname_list():
|
||||
# self.model.append([name, 0])
|
||||
|
||||
# build up the list of surnames, keeping track of the count for each name
|
||||
# (this can be a lengthy process, so by passing in the dictionary we can
|
||||
# be certain we only do this once)
|
||||
progress = Utils.ProgressMeter(_('Finding surnames'))
|
||||
progress.set_pass(_('Finding surnames'), database.get_number_of_people())
|
||||
for personHandle in database.get_person_handles(False):
|
||||
progress.step()
|
||||
person = database.get_person_from_handle(personHandle)
|
||||
key = person.get_primary_name().get_surname()
|
||||
count = 0
|
||||
if key in surnames:
|
||||
count = surnames[key]
|
||||
surnames[key] = count + 1
|
||||
progress.close()
|
||||
|
||||
# insert the names and count into the model
|
||||
for key in surnames:
|
||||
if key.encode('iso-8859-1','xmlcharrefreplace') not in skipList:
|
||||
self.model.append([key, surnames[key]])
|
||||
|
||||
# keep the list sorted starting with the most popular last name
|
||||
self.model.set_sort_column_id(1, gtk.SORT_DESCENDING)
|
||||
|
||||
# the "OK" button should be enabled/disabled based on the selection of a row
|
||||
self.treeSelection = self.treeView.get_selection()
|
||||
self.treeSelection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||
self.treeSelection.select_path(0)
|
||||
|
||||
def run(self):
|
||||
response = self.dlg.run()
|
||||
surnameSet = set()
|
||||
if response == gtk.RESPONSE_ACCEPT:
|
||||
(mode, paths) = self.treeSelection.get_selected_rows()
|
||||
for path in paths:
|
||||
iter = self.model.get_iter(path)
|
||||
surname = self.model.get_value(iter, 0)
|
||||
surnameSet.add(surname)
|
||||
self.dlg.destroy()
|
||||
return surnameSet
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Option class
|
||||
@ -690,7 +781,7 @@ class PersonListOption(Option):
|
||||
@type label: string
|
||||
@param value: A set of GIDs as initial values for this option.
|
||||
Example: "111 222 333 444"
|
||||
@type value: set()
|
||||
@type value: string
|
||||
@return: nothing
|
||||
"""
|
||||
self.db = dbstate.get_database()
|
||||
@ -775,6 +866,9 @@ class PersonListOption(Option):
|
||||
|
||||
# if this person has a spouse, ask if we should include the spouse
|
||||
# in the list of "people of interest"
|
||||
#
|
||||
# NOTE: we may want to make this an optional thing, determined
|
||||
# by the use of a parameter at the time this class is instatiated
|
||||
familyList = person.get_family_handle_list()
|
||||
if familyList:
|
||||
for familyHandle in familyList:
|
||||
@ -807,6 +901,131 @@ class PersonListOption(Option):
|
||||
iter = self.model.get_iter(path)
|
||||
self.model.remove(iter)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# SurnameColourOption class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class SurnameColourOption(Option):
|
||||
"""
|
||||
This class describes a widget that allows multiple surnames to be
|
||||
selected from the database, and to assign a colour (not necessarily
|
||||
unique) to each one.
|
||||
"""
|
||||
def __init__(self, label, value, dbstate):
|
||||
"""
|
||||
@param label: A friendly label to be applied to this option.
|
||||
Example: "Family lines"
|
||||
@type label: string
|
||||
@param value: A set of surnames and colours.
|
||||
Example: "surname1 colour1 surname2 colour2"
|
||||
@type value: string
|
||||
@return: nothing
|
||||
"""
|
||||
self.db = dbstate.get_database()
|
||||
self.dbstate = dbstate
|
||||
Option.__init__(self,label,value)
|
||||
|
||||
def make_gui_obj(self, gtk, dialog):
|
||||
"""
|
||||
Add a "surname-colour" widget to the dialog.
|
||||
"""
|
||||
self.dialog = dialog
|
||||
self.surnames = {} # list of surnames and count
|
||||
|
||||
self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
|
||||
self.treeView = gtk.TreeView(self.model)
|
||||
self.treeView.set_size_request(150, 150)
|
||||
self.treeView.connect('row-activated', self.clicked)
|
||||
col1 = gtk.TreeViewColumn(_('Surname'), gtk.CellRendererText(), text=0)
|
||||
col2 = gtk.TreeViewColumn(_('Colour'), gtk.CellRendererText(), text=1)
|
||||
col1.set_resizable(True)
|
||||
col2.set_resizable(True)
|
||||
col1.set_sort_column_id(0)
|
||||
col1.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
|
||||
col2.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
|
||||
self.treeView.append_column(col1)
|
||||
self.treeView.append_column(col2)
|
||||
self.scrolledWindow = gtk.ScrolledWindow()
|
||||
self.scrolledWindow.add(self.treeView)
|
||||
self.scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.scrolledWindow.set_shadow_type(gtk.SHADOW_OUT)
|
||||
self.hbox = gtk.HBox()
|
||||
self.hbox.pack_start(self.scrolledWindow, expand=True, fill=True)
|
||||
|
||||
self.addSurname = GrampsWidgets.SimpleButton(gtk.STOCK_ADD, self.addSurnameClicked)
|
||||
self.delSurname = GrampsWidgets.SimpleButton(gtk.STOCK_REMOVE, self.delSurnameClicked)
|
||||
self.vbbox = gtk.VButtonBox()
|
||||
self.vbbox.add(self.addSurname)
|
||||
self.vbbox.add(self.delSurname)
|
||||
self.vbbox.set_layout(gtk.BUTTONBOX_SPREAD)
|
||||
self.hbox.pack_end(self.vbbox, expand=False)
|
||||
|
||||
# populate the surname/colour treeview
|
||||
tmp = self.get_value().split()
|
||||
while len(tmp) > 1:
|
||||
surname = tmp.pop(0)
|
||||
colour = tmp.pop(0)
|
||||
self.model.append([surname, colour])
|
||||
|
||||
# parent expects the widget as "self.gobj"
|
||||
self.gobj = self.hbox
|
||||
|
||||
def parse(self):
|
||||
"""
|
||||
Parse the object and return.
|
||||
"""
|
||||
surnameColours = ''
|
||||
iter = self.model.get_iter_first()
|
||||
while (iter):
|
||||
surname = self.model.get_value(iter, 0) # .encode('iso-8859-1','xmlcharrefreplace')
|
||||
colour = self.model.get_value(iter, 1)
|
||||
# tried to use a dictionary, and tried to save it as a tuple,
|
||||
# but coulnd't get this to work right -- this is lame, but now
|
||||
# the surnames and colours are saved as a plain text string
|
||||
surnameColours += surname + ' ' + colour + ' '
|
||||
iter = self.model.iter_next(iter)
|
||||
return surnameColours
|
||||
|
||||
def clicked(self, treeview, path, column):
|
||||
# get the surname and colour value for this family
|
||||
iter = self.model.get_iter(path)
|
||||
surname = self.model.get_value(iter, 0)
|
||||
colour = gtk.gdk.color_parse(self.model.get_value(iter, 1))
|
||||
|
||||
colourDialog = gtk.ColorSelectionDialog('Select colour for %s' % surname)
|
||||
colourDialog.colorsel.set_current_color(colour)
|
||||
response = colourDialog.run()
|
||||
|
||||
if response == gtk.RESPONSE_OK:
|
||||
colour = colourDialog.colorsel.get_current_color()
|
||||
colourName = '#%02x%02x%02x' % (
|
||||
int(colour.red *256/65536),
|
||||
int(colour.green*256/65536),
|
||||
int(colour.blue *256/65536))
|
||||
self.model.set_value(iter, 1, colourName)
|
||||
|
||||
colourDialog.destroy()
|
||||
|
||||
def addSurnameClicked(self, obj):
|
||||
skipList = set()
|
||||
iter = self.model.get_iter_first()
|
||||
while (iter):
|
||||
surname = self.model.get_value(iter, 0)
|
||||
skipList.add(surname.encode('iso-8859-1','xmlcharrefreplace'))
|
||||
iter = self.model.iter_next(iter)
|
||||
|
||||
ln = LastNameDialog(self.db, self.dialog.uistate, self.dialog.track, self.surnames, skipList)
|
||||
surnameSet = ln.run()
|
||||
for surname in surnameSet:
|
||||
self.model.append([surname, '#ffffff'])
|
||||
|
||||
def delSurnameClicked(self, obj):
|
||||
(path, column) = self.treeView.get_cursor()
|
||||
if (path):
|
||||
iter = self.model.get_iter(path)
|
||||
self.model.remove(iter)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Menu class
|
||||
|
@ -30,7 +30,7 @@
|
||||
from _MenuOptions import MenuOptions, \
|
||||
NumberOption, FloatOption, BooleanOption, TextOption, \
|
||||
EnumeratedListOption, FilterListOption, StringOption, ColourButtonOption, \
|
||||
PersonOption, PersonListOption
|
||||
PersonOption, PersonListOption, SurnameColourOption
|
||||
from _PluginMgr import \
|
||||
register_export, register_import, \
|
||||
register_tool, register_report, \
|
||||
|
@ -270,6 +270,23 @@ class GVDocBase(BaseDoc.BaseDoc,BaseDoc.GVDoc):
|
||||
|
||||
self.write('\n')
|
||||
|
||||
def add_comment(self, comment):
|
||||
"""
|
||||
Add a comment.
|
||||
|
||||
Implementes BaseDoc.GVDoc.add_comment().
|
||||
"""
|
||||
tmp = comment.split('\n')
|
||||
for line in tmp:
|
||||
text = line.strip()
|
||||
print 'text="%s"\n' % text
|
||||
if text == "":
|
||||
self.write('\n')
|
||||
elif text.startswith('#'):
|
||||
self.write('%s\n' % text)
|
||||
else:
|
||||
self.write('# %s\n' % text)
|
||||
|
||||
def start_subgraph(self,id):
|
||||
self.write(' subgraph cluster_%s\n' % id)
|
||||
self.write(' {\n')
|
||||
|
@ -67,7 +67,7 @@ from PluginUtils import register_report
|
||||
from ReportBase import Report, ReportUtils, ReportOptions, CATEGORY_CODE, MODE_GUI, MODE_CLI
|
||||
from ReportBase import Report, MenuReportOptions, MODE_GUI, MODE_CLI, CATEGORY_GRAPHVIZ
|
||||
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, SurnameColourOption
|
||||
from QuestionDialog import ErrorDialog, WarningDialog
|
||||
from BasicUtils import name_displayer as _nd
|
||||
from DateHandler import displayer as _dd
|
||||
@ -109,8 +109,8 @@ class FamilyLinesOptions(MenuReportOptions):
|
||||
category = _('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\".'))
|
||||
personList = PersonListOption( _('People of interest'), '', dbstate)
|
||||
personList.set_help( _('People of interest are used as a starting point when determining \"family lines\".'))
|
||||
menu.add_option(category, 'FLgidlist', personList)
|
||||
|
||||
followParents = BooleanOption( _('Follow parents to determine family lines'), True)
|
||||
@ -129,7 +129,9 @@ class FamilyLinesOptions(MenuReportOptions):
|
||||
category = _('Family Colours')
|
||||
# ----------------------------
|
||||
|
||||
# todo, family colours
|
||||
surnameColour = SurnameColourOption(_('Family colours'), '', dbstate)
|
||||
surnameColour.set_help( _('Colours to use for various family lines.'))
|
||||
menu.add_option(category, 'FLsurnameColours', surnameColour)
|
||||
|
||||
# -------------------------
|
||||
category = _('Individuals')
|
||||
@ -270,7 +272,7 @@ class FamilyLinesReport(Report):
|
||||
|
||||
# convert the 'surnameColours' string to a dictionary of names and colours
|
||||
self.surnameColours = {}
|
||||
tmp = '' # TODO, FIXME options.handler.options_dict['FLsurnameColours'].split()
|
||||
tmp = options.handler.options_dict['FLsurnameColours'].split()
|
||||
while len(tmp) > 1:
|
||||
surname = tmp.pop(0).encode('iso-8859-1','xmlcharrefreplace')
|
||||
colour = tmp.pop(0)
|
||||
@ -316,19 +318,19 @@ class FamilyLinesReport(Report):
|
||||
# now that begin_report() has done the work, output what we've
|
||||
# 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))
|
||||
self.doc.add_comment('# Number of people in database: %d' % self.db.get_number_of_people())
|
||||
self.doc.add_comment('# Number of people of interest: %d' % len(self.peopleToOutput))
|
||||
self.doc.add_comment('# Number of families in database: %d' % self.db.get_number_of_families())
|
||||
self.doc.add_comment('# Number of families of interest: %d' % 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')
|
||||
self.doc.add_comment('# Additional people removed: %d' % self.deletedPeople)
|
||||
self.doc.add_comment('# Additional families removed: %d' % self.deletedFamilies)
|
||||
self.doc.add_comment('# Initial list of people of interest:')
|
||||
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.doc.add_comment('# -> %s, %s' % (gid, name))
|
||||
|
||||
self.writePeople()
|
||||
self.writeFamilies()
|
||||
@ -609,7 +611,7 @@ class FamilyLinesReport(Report):
|
||||
|
||||
def writePeople(self):
|
||||
|
||||
self.doc.write('\n')
|
||||
self.doc.add_comment('')
|
||||
|
||||
# if we're going to attempt to include images, then use the HTML style of .dot file
|
||||
bUseHtmlOutput = False
|
||||
@ -746,7 +748,7 @@ class FamilyLinesReport(Report):
|
||||
|
||||
def writeFamilies(self):
|
||||
|
||||
self.doc.write('\n')
|
||||
self.doc.add_comment('')
|
||||
|
||||
# loop through all the families we need to output
|
||||
for familyHandle in self.familiesToOutput:
|
||||
@ -804,7 +806,7 @@ class FamilyLinesReport(Report):
|
||||
if label != '':
|
||||
label += '\\n'
|
||||
label += '%s' % childrenStr
|
||||
self.doc.add_node(fgid,label,"ellipse","","filled",self.colourFamilies)
|
||||
self.doc.add_node(fgid, label, "ellipse", "", "filled", self.colourFamilies)
|
||||
|
||||
|
||||
# now that we have the families written, go ahead and link the parents and children to the families
|
||||
@ -820,7 +822,7 @@ class FamilyLinesReport(Report):
|
||||
if self.useSubgraphs and fatherHandle and motherHandle:
|
||||
self.doc.start_subgraph(fgid)
|
||||
|
||||
self.doc.write('\n')
|
||||
self.doc.add_comment('')
|
||||
|
||||
# see if we have a father to link to this family
|
||||
if fatherHandle:
|
||||
@ -843,7 +845,7 @@ class FamilyLinesReport(Report):
|
||||
for childRef in family.get_child_ref_list():
|
||||
if childRef.ref in self.peopleToOutput:
|
||||
child = self.db.get_person_from_handle(childRef.ref)
|
||||
comment = "child: %s" % child.get_primary_name().get_regular_name()
|
||||
comment = "child: %s" % child.get_primary_name().get_regular_name()
|
||||
self.doc.add_link(child.get_gramps_id(), fgid, comment=comment)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user