From df06be53dfaac0db04614a4a43757d0d3ff70e8a Mon Sep 17 00:00:00 2001 From: Serge Noiraud Date: Sat, 16 Jun 2012 17:50:24 +0000 Subject: [PATCH] Geography : Add ID property to some new sources. Add a new layer which permit to display messages over the map Modify plugins to use this new functionality Remove the person's name in geoclose and geofamclose. svn: r19851 --- src/plugins/lib/maps/Makefile.am | 1 + src/plugins/lib/maps/datelayer.py | 2 +- src/plugins/lib/maps/dummylayer.py | 2 +- src/plugins/lib/maps/dummynogps.py | 2 +- src/plugins/lib/maps/lifewaylayer.py | 27 +--- src/plugins/lib/maps/markerlayer.py | 2 +- src/plugins/lib/maps/messagelayer.py | 171 +++++++++++++++++++++++++ src/plugins/lib/maps/osmGps.py | 23 +++- src/plugins/lib/maps/placeselection.py | 2 +- src/plugins/lib/maps/selectionlayer.py | 2 +- src/plugins/view/geoclose.py | 18 ++- src/plugins/view/geofamclose.py | 49 ++++++- src/plugins/view/geofamily.py | 32 +++++ src/plugins/view/geomoves.py | 5 +- src/plugins/view/geoperson.py | 2 + src/plugins/view/geoplaces.py | 3 + 16 files changed, 294 insertions(+), 49 deletions(-) create mode 100644 src/plugins/lib/maps/messagelayer.py diff --git a/src/plugins/lib/maps/Makefile.am b/src/plugins/lib/maps/Makefile.am index 84af20848..8294070ae 100644 --- a/src/plugins/lib/maps/Makefile.am +++ b/src/plugins/lib/maps/Makefile.am @@ -10,6 +10,7 @@ pkgpython_PYTHON = \ __init__.py\ lifewaylayer.py\ markerlayer.py\ + messagelayer.py\ osmGps.py\ placeselection.py\ selectionlayer.py diff --git a/src/plugins/lib/maps/datelayer.py b/src/plugins/lib/maps/datelayer.py index 7c1248f62..f1e998701 100644 --- a/src/plugins/lib/maps/datelayer.py +++ b/src/plugins/lib/maps/datelayer.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # diff --git a/src/plugins/lib/maps/dummylayer.py b/src/plugins/lib/maps/dummylayer.py index 77052b30c..65c714758 100644 --- a/src/plugins/lib/maps/dummylayer.py +++ b/src/plugins/lib/maps/dummylayer.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # diff --git a/src/plugins/lib/maps/dummynogps.py b/src/plugins/lib/maps/dummynogps.py index 87ce3765c..278ebb356 100644 --- a/src/plugins/lib/maps/dummynogps.py +++ b/src/plugins/lib/maps/dummynogps.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # diff --git a/src/plugins/lib/maps/lifewaylayer.py b/src/plugins/lib/maps/lifewaylayer.py index d8062521b..5cdc4390f 100644 --- a/src/plugins/lib/maps/lifewaylayer.py +++ b/src/plugins/lib/maps/lifewaylayer.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # @@ -77,7 +77,6 @@ class LifeWayLayer(gobject.GObject, osmgpsmap.GpsMapLayer): gobject.GObject.__init__(self) self.lifeways_ref = [] self.lifeways = [] - self.lifeways_comment = [] self.comments = [] def clear_ways(self): @@ -86,7 +85,6 @@ class LifeWayLayer(gobject.GObject, osmgpsmap.GpsMapLayer): """ self.lifeways_ref = [] self.lifeways = [] - self.lifeways_comment = [] self.comments = [] def add_way_ref(self, points, color, radius): @@ -103,12 +101,6 @@ class LifeWayLayer(gobject.GObject, osmgpsmap.GpsMapLayer): """ self.lifeways.append((points, color)) - def add_text(self, points, text): - """ - Add a text to the track or life way. - """ - self.lifeways_comment.append((points, text)) - def do_draw(self, gpsmap, drawable): """ Draw all tracks or life ways. @@ -181,23 +173,6 @@ class LifeWayLayer(gobject.GObject, osmgpsmap.GpsMapLayer): ctx.line_to(crdx + 1, crdy + 1) ctx.stroke() - for comment in self.lifeways_comment: - ctx = drawable.cairo_create() - # Does the following font is available for all language ? Is it the good one ? - ctx.select_font_face("Purisa", - cairo.FONT_SLANT_NORMAL, - cairo.FONT_WEIGHT_NORMAL) - ctx.set_font_size(13) - points = comment[0] - conv_pt = osmgpsmap.point_new_degrees(points[0][0], points[0][1]) - if len(points) > 1 : - crd_x = -(points[0][0] - points[len(points)-1][0] )/2 - crd_y = -(points[0][1] - points[len(points)-1][1] )/2 - conv_pt = osmgpsmap.point_new_degrees(points[0][0]+crd_x, points[0][1]+crd_y) - coord_x, coord_y = gpsmap.convert_geographic_to_screen(conv_pt) - ctx.move_to(coord_x, coord_y) - ctx.show_text(comment[1]) - def do_render(self, gpsmap): """ render the layer diff --git a/src/plugins/lib/maps/markerlayer.py b/src/plugins/lib/maps/markerlayer.py index 31ad6f40e..7dfcc4308 100644 --- a/src/plugins/lib/maps/markerlayer.py +++ b/src/plugins/lib/maps/markerlayer.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # diff --git a/src/plugins/lib/maps/messagelayer.py b/src/plugins/lib/maps/messagelayer.py new file mode 100644 index 000000000..39a93d4b1 --- /dev/null +++ b/src/plugins/lib/maps/messagelayer.py @@ -0,0 +1,171 @@ +# -*- python -*- +# -*- coding: utf-8 -*- +# +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2011-2012 Serge Noiraud +# +# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# $Id$ + +#------------------------------------------------------------------------- +# +# Python modules +# +#------------------------------------------------------------------------- +import os +import gobject +import operator +from math import * + +#------------------------------------------------------------------------ +# +# Set up logging +# +#------------------------------------------------------------------------ +import logging +_LOG = logging.getLogger("maps.messagelayer") + +#------------------------------------------------------------------------- +# +# GTK/Gnome modules +# +#------------------------------------------------------------------------- +import gtk + +#------------------------------------------------------------------------- +# +# Gramps Modules +# +#------------------------------------------------------------------------- +import const +import cairo +import pango +import pangocairo + +#------------------------------------------------------------------------- +# +# osmGpsMap +# +#------------------------------------------------------------------------- + +try: + import osmgpsmap +except: + raise + +class MessageLayer(gobject.GObject, osmgpsmap.GpsMapLayer): + """ + This is the layer used to display messages over the map + """ + def __init__(self): + """ + Initialize the layer + """ + gobject.GObject.__init__(self) + self.message = [] + self.color = "black" + self.font = "Arial" + self.size = 18 + #font_map = pangocairo.cairo_font_map_get_default() + #families = font_map.list_families() + + def clear_messages(self): + """ + reset the layer attributes. + """ + self.message = [] + + def clear_font_attributes(self): + """ + reset the font attributes. + """ + self.color = "black" + self.font = "Arial" + self.size = 18 + + def set_font_attributes(self, font, size, color): + """ + Set the font color, size and name + """ + if color is not None: + self.color = color + if font is not None: + self.font = font + if size is not None: + self.size = size + + def add_message(self, message): + """ + Add a message + """ + self.message.append(message) + + def do_draw(self, gpsmap, drawable): + """ + Draw the two extreme dates + """ + ctx = drawable.cairo_create() + ctx.select_font_face(self.font, + cairo.FONT_SLANT_NORMAL, + cairo.FONT_WEIGHT_NORMAL) + ctx.set_font_size(int(self.size)) + color = gtk.gdk.color_parse(self.color) + ctx.set_source_rgba(float(color.red / 65535.0), + float(color.green / 65535.0), + float(color.blue / 65535.0), + 0.6) # transparency + coord_x = 100 + coord_y = int(self.size) # Show the first line under the zoom button + (d_width, d_height) = drawable.get_size() + d_width -= 100 + for line in self.message: + line_to_print = line + (x_bearing, y_bearing, width, height, x_advance, y_advance) = ctx.text_extents(line_to_print) + while ( width > d_width): + line_length = len(line_to_print) + character_length = int(width/line_length) + 1 + max_length = int(d_width / character_length) - 5 + ctx.move_to(coord_x, coord_y) + ctx.show_text(line_to_print[:max_length]) + line_to_print = line_to_print[max_length:] + (x_bearing, y_bearing, width, height, x_advance, y_advance) = ctx.text_extents(line_to_print) + coord_y += int(self.size) # calculate the next line position + ctx.move_to(coord_x, coord_y) + ctx.show_text(line_to_print) + coord_y += int(self.size) # calculate the next line position + + def do_render(self, gpsmap): + """ + render the layer + """ + pass + + def do_busy(self): + """ + set the layer busy + """ + return False + + def do_button_press(self, gpsmap, gdkeventbutton): + """ + When we press a button. + """ + return False + +gobject.type_register(MessageLayer) + diff --git a/src/plugins/lib/maps/osmGps.py b/src/plugins/lib/maps/osmGps.py index da70cbf47..5fdbf72e6 100644 --- a/src/plugins/lib/maps/osmGps.py +++ b/src/plugins/lib/maps/osmGps.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # @@ -59,6 +59,7 @@ from selectionlayer import SelectionLayer from lifewaylayer import LifeWayLayer from markerlayer import MarkerLayer from datelayer import DateLayer +from messagelayer import MessageLayer from gen.ggettext import sgettext as _ from gen.config import config from gui.dialog import ErrorDialog @@ -88,6 +89,7 @@ class OsmGps(): self.lifeway_layer = None self.marker_layer = None self.date_layer = None + self.message_layer = None self.context_id = 0 self.begin_selection = None self.end_selection = None @@ -143,6 +145,7 @@ class OsmGps(): self.lifeway_layer = self.add_lifeway_layer() self.marker_layer = self.add_marker_layer() self.date_layer = self.add_date_layer() + self.message_layer = self.add_message_layer() self.cross_map = osmgpsmap.GpsMapOsd( show_crosshair=False) self.set_crosshair(config.get("geography.show_cross")) self.osm.set_center_and_zoom(config.get("geography.center-lat"), @@ -171,9 +174,23 @@ class OsmGps(): """ return self.selection_layer + def add_message_layer(self): + """ + add the message layer to the map + """ + message_layer = MessageLayer() + self.osm.layer_add(message_layer) + return message_layer + + def get_message_layer(self): + """ + get the message layer + """ + return self.message_layer + def add_date_layer(self): """ - add the track or life ways layer + add the date layer to the map """ date_layer = DateLayer() self.osm.layer_add(date_layer) @@ -181,7 +198,7 @@ class OsmGps(): def get_date_layer(self): """ - get the track or life ways layer + get the date layer """ return self.date_layer diff --git a/src/plugins/lib/maps/placeselection.py b/src/plugins/lib/maps/placeselection.py index de7192d60..3720cd1ca 100644 --- a/src/plugins/lib/maps/placeselection.py +++ b/src/plugins/lib/maps/placeselection.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: geography.py 18338 2011-10-16 20:21:22Z paul-franklin $ +# $Id$ #------------------------------------------------------------------------- # diff --git a/src/plugins/lib/maps/selectionlayer.py b/src/plugins/lib/maps/selectionlayer.py index ae8eda70c..18847a1a2 100644 --- a/src/plugins/lib/maps/selectionlayer.py +++ b/src/plugins/lib/maps/selectionlayer.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $ +# $Id$ #------------------------------------------------------------------------- # diff --git a/src/plugins/view/geoclose.py b/src/plugins/view/geoclose.py index 8f02b0ff1..9d0c2d89c 100644 --- a/src/plugins/view/geoclose.py +++ b/src/plugins/view/geoclose.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id: geoperson.py 18338 2011-10-16 20:21:22Z paul-franklin $ +# $Id$ """ Geography for two persons @@ -204,15 +204,23 @@ class GeoClose(GeoGraphyView): self.remove_all_gps() self.remove_all_markers() self.lifeway_layer.clear_ways() - if self.refperson: - color = self._config.get('geography.color1') - self._createmap(self.refperson, color, self.place_list_ref, True) + self.message_layer.clear_messages() active = self.get_active() if active: p1 = self.dbstate.db.get_person_from_handle(active) self.change_active(active) color = self._config.get('geography.color2') self._createmap(p1, color, self.place_list_active, False) + if self.refperson: + color = self._config.get('geography.color1') + self.message_layer.add_message(_("Reference : %s" % _nd.display(self.refperson))) + self.message_layer.add_message(_("The other : %s" % _nd.display(p1))) + self._createmap(self.refperson, color, self.place_list_ref, True) + else: + self.message_layer.add_message(_("You must choose one reference person.")) + self.message_layer.add_message(_("Go to the person view and select " + "the people you want to compare. " + "Return to this view and use the history.")) self.possible_meeting(self.place_list_ref, self.place_list_active) self.uistate.modify_statusbar(self.dbstate) @@ -273,8 +281,6 @@ class GeoClose(GeoGraphyView): if reference: self.lifeway_layer.add_way_ref(points, color, float(self._config.get("geography.maximum_meeting_zone")) / 10) - if mark: - self.lifeway_layer.add_text(points, mark[1]) return False def possible_meeting(self, place_list_ref, place_list_active): diff --git a/src/plugins/view/geofamclose.py b/src/plugins/view/geofamclose.py index 3d7ab012d..671921512 100644 --- a/src/plugins/view/geofamclose.py +++ b/src/plugins/view/geofamclose.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id:$ +# $Id$ """ Geography for two families @@ -191,6 +191,36 @@ class GeoFamClose(GeoGraphyView): """ return self.dbstate.db.get_bookmarks() + def family_label(self,family): + if family is None: + return "Unknown" + f = self.dbstate.db.get_person_from_handle( + family.get_father_handle()) + m = self.dbstate.db.get_person_from_handle( + family.get_mother_handle()) + if f and m: + label = _("%(gramps_id)s : %(father)s and %(mother)s") % { + 'father' : _nd.display(f), + 'mother' : _nd.display(m), + 'gramps_id' : family.gramps_id, + } + elif f: + label = "%(gramps_id)s : %(father)s" % { + 'father' : _nd.display(f), + 'gramps_id' : family.gramps_id, + } + elif m: + label = "%(gramps_id)s : %(mother)s" % { + 'mother' : _nd.display(m), + 'gramps_id' : family.gramps_id, + } + else: + # No translation for bare gramps_id + label = "%(gramps_id)s :" % { + 'gramps_id' : family.gramps_id, + } + return label + def goto_handle(self, handle=None): """ Rebuild the tree with the given family handle as reference. @@ -204,9 +234,7 @@ class GeoFamClose(GeoGraphyView): self.remove_all_gps() self.remove_all_markers() self.lifeway_layer.clear_ways() - if self.reffamily: - color = self._config.get('geography.color1') - self._createmap(self.reffamily, color, self.place_list_ref, True) + self.message_layer.clear_messages() active = self.get_active() f1 = None if active: @@ -214,6 +242,16 @@ class GeoFamClose(GeoGraphyView): self.change_active(active) color = self._config.get('geography.color2') self._createmap(f1, color, self.place_list_active, False) + if self.reffamily: + color = self._config.get('geography.color1') + self._createmap(self.reffamily, color, self.place_list_ref, True) + self.message_layer.add_message(_("Family reference : %s" % self.family_label(self.reffamily))) + self.message_layer.add_message(_("The other family : %s" % self.family_label(f1))) + else: + self.message_layer.add_message(_("You must choose one reference family.")) + self.message_layer.add_message(_("Go to the family view and select " + "the families you want to compare. " + "Return to this view and use the history.")) if f1 is not None: self._possible_family_meeting(self.reffamily, f1) self.uistate.modify_statusbar(self.dbstate) @@ -251,7 +289,6 @@ class GeoFamClose(GeoGraphyView): """ active = self.get_active() family = self.dbstate.db.get_family_from_handle(active) - self.lifeway_layer.clear_ways() self.goto_handle(handle=family) def draw(self, menu, marks, color, reference): @@ -273,8 +310,6 @@ class GeoFamClose(GeoGraphyView): if reference: self.lifeway_layer.add_way_ref(points, color, float(self._config.get("geography.maximum_meeting_zone")) / 10) - if mark: - self.lifeway_layer.add_text(points, mark[1]) return False def _place_list_for_person(self, person): diff --git a/src/plugins/view/geofamily.py b/src/plugins/view/geofamily.py index c0f8cfff5..ec3da4dd4 100644 --- a/src/plugins/view/geofamily.py +++ b/src/plugins/view/geofamily.py @@ -272,11 +272,42 @@ class GeoFamily(GeoGraphyView): else: self._append_to_places_without_coord( place.gramps_id, descr) + def family_label(self,family): + if family is None: + return "Unknown" + f = self.dbstate.db.get_person_from_handle( + family.get_father_handle()) + m = self.dbstate.db.get_person_from_handle( + family.get_mother_handle()) + if f and m: + label = _("%(gramps_id)s : %(father)s and %(mother)s") % { + 'father' : _nd.display(f), + 'mother' : _nd.display(m), + 'gramps_id' : family.gramps_id, + } + elif f: + label = "%(gramps_id)s : %(father)s" % { + 'father' : _nd.display(f), + 'gramps_id' : family.gramps_id, + } + elif m: + label = "%(gramps_id)s : %(mother)s" % { + 'mother' : _nd.display(m), + 'gramps_id' : family.gramps_id, + } + else: + # No translation for bare gramps_id + label = "%(gramps_id)s :" % { + 'gramps_id' : family.gramps_id, + } + return label + def _createmap_for_one_family(self, family): """ Create all markers for one family : all event's places with a lat/lon. """ dbstate = self.dbstate + self.message_layer.add_message(_("Family places for %s" % self.family_label(family))) try: person = dbstate.db.get_person_from_handle(family.get_father_handle()) except: @@ -337,6 +368,7 @@ class GeoFamily(GeoGraphyView): self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0 self.minyear = 9999 self.maxyear = 0 + self.message_layer.clear_messages() family = self.dbstate.db.get_family_from_handle(family_x) if family is None: person = self.dbstate.db.get_person_from_handle(self.uistate.get_active('Person')) diff --git a/src/plugins/view/geomoves.py b/src/plugins/view/geomoves.py index c21d4ed38..119cd2f28 100644 --- a/src/plugins/view/geomoves.py +++ b/src/plugins/view/geomoves.py @@ -20,7 +20,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # -# $Id:$ +# $Id$ """ Geography for one person and all his descendant @@ -235,6 +235,7 @@ class GeoMoves(GeoGraphyView): self.remove_all_markers() self.lifeway_layer.clear_ways() self.date_layer.clear_dates() + self.message_layer.clear_messages() def draw(self, menu, marks, color): """ @@ -459,12 +460,14 @@ class GeoMoves(GeoGraphyView): self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0 latitude = "" longitude = "" + self.message_layer.clear_messages() self.place_without_coordinates = [] self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0 if person is None: person = self.dbstate.db.get_person_from_handle(self.uistate.get_active('Person')) if not person: return + self.message_layer.add_message(_("All descendance for %s" % _nd.display(person))) color = gtk.gdk.color_parse(self._config.get('geography.color_base')) gobject.timeout_add(int(self._config.get("geography.generation_interval")), self.animate_moves, 0, person, color) diff --git a/src/plugins/view/geoperson.py b/src/plugins/view/geoperson.py index c9f070a3a..6014bc4ae 100644 --- a/src/plugins/view/geoperson.py +++ b/src/plugins/view/geoperson.py @@ -302,10 +302,12 @@ class GeoPerson(GeoGraphyView): self.maxyear = 0 latitude = "" longitude = "" + self.message_layer.clear_messages() person_handle = self.uistate.get_active('Person') person = dbstate.db.get_person_from_handle(person_handle) if person is not None: # For each event, if we have a place, set a marker. + self.message_layer.add_message(_("Person places for %s" % _nd.display(person))) for event_ref in person.get_event_ref_list(): if not event_ref: continue diff --git a/src/plugins/view/geoplaces.py b/src/plugins/view/geoplaces.py index 0a13b269b..ea0827151 100644 --- a/src/plugins/view/geoplaces.py +++ b/src/plugins/view/geoplaces.py @@ -239,6 +239,8 @@ class GeoPlaces(GeoGraphyView): self.without = 0 latitude = "" longitude = "" + self.nbmarkers = 0 + self.message_layer.clear_messages() self.no_show_places_in_status_bar = False # base "villes de france" : 38101 places : # createmap : 8'50"; create_markers : 1'23" @@ -279,6 +281,7 @@ class GeoPlaces(GeoGraphyView): _LOG.debug("%s" % time.strftime(" end sort : " "%a %d %b %Y %H:%M:%S", time.gmtime())) if self.nbmarkers > 500 : # performance issue. Is it the good value ? + self.message_layer.add_message(_("The place name in the status bar is disabled.")) self.no_show_places_in_status_bar = True self._create_markers()