merge geps-025 to have geography based on osmgpsmap.

svn: r17256
This commit is contained in:
Serge Noiraud 2011-04-25 21:11:45 +00:00
parent 3b8f1f6d8f
commit 56d78320e8
18 changed files with 2784 additions and 2550 deletions

7
README
View File

@ -26,7 +26,12 @@ The following packages are *STRONGLY RECOMMENDED* to be installed:
GraphViz Enable creation of graphs using GraphViz engine
http://www.graphviz.org
The following packages are *STRONGLY RECOMMENDED* to be installed:
osmgpsmap Used to show maps in the geography view.
The package is named osmgpsmap or osm-gps-map
http://nzjrs.github.com/osm-gps-map/
The following packages are *STRONGLY RECOMMENDED* to be installed if you want
to use the htmlview. The geography view doesn't use them any more :
PyWebKitGtk or python-gtkmozembed: PACKAGERS, Test if on your distribution
webkit and Gramps is stable. If you get crashes, patch
src/plugins/view/htmlrenderer.py and

View File

@ -139,6 +139,7 @@ src/plugins/gramplet/Makefile
src/plugins/graph/Makefile
src/plugins/import/Makefile
src/plugins/lib/Makefile
src/plugins/lib/maps/Makefile
src/plugins/mapservices/Makefile
src/plugins/quickview/Makefile
src/plugins/rel/Makefile

View File

@ -158,12 +158,14 @@ register('export.proxy-order', [
["reference", 0],
])
register('geoview.latitude', "0.0")
register('geoview.lock', False)
register('geoview.longitude', "0.0")
register('geoview.map', "person")
register('geoview.stylesheet', "")
register('geoview.zoom', 0)
register('geography.center-lon', 0.0)
register('geography.lock', False)
register('geography.center-lat', 0.0)
register('geography.map', "person")
register('geography.map_service', 1)
register('geography.zoom', 0)
register('geography.show_cross', False)
register('geography.path', "")
register('htmlview.start-url', "http://gramps-project.org")
register('htmlview.url-handler', False)

View File

@ -116,9 +116,13 @@ def register_stock_icons ():
('gramps-font-color', _('Font Color'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-font-bgcolor', _('Font Background Color'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-gramplet', _('Gramplets'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-geo', _('GeoView'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-geo-mainmap', _('GeoView'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-geo-altmap', _('GeoView'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-geo', _('Geography'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-geo-mainmap', _('Geography'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-geo-altmap', _('Geography'), gtk.gdk.CONTROL_MASK, 0, ''),
('geo-show-person', _('GeoPerson'), gtk.gdk.CONTROL_MASK, 0, ''),
('geo-show-family', _('GeoFamily'), gtk.gdk.CONTROL_MASK, 0, ''),
('geo-show-event', _('GeoEvents'), gtk.gdk.CONTROL_MASK, 0, ''),
('geo-show-place', _('GeoPlaces'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-lock', _('Public'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-media', _('Media'), gtk.gdk.CONTROL_MASK, 0, ''),
('gramps-merge', _('Merge'), gtk.gdk.CONTROL_MASK, 0, ''),

View File

@ -12,6 +12,8 @@ EXTRA_DIST=$(xml_in_files) $(xml_files)
pkgdatadir = $(datadir)/@PACKAGE@/plugins/lib
SUBDIRS = maps
pkgdata_PYTHON = \
libcairodoc.py\
libformatting.py\

View File

@ -0,0 +1,19 @@
pkgdatadir = $(datadir)/@PACKAGE@/maps
pkgdata_PYTHON = \
constants.py\
geography.py\
grampsmaps.py\
__init__.py
pkgpyexecdir = @pkgpyexecdir@/maps
pkgpythondir = @pkgpythondir@/maps
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

View File

@ -0,0 +1,27 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2010 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 $
"""
The gen module provides packages that are common to all gramps
interfaces (gui, cli and web).
"""
__all__ = []

View File

@ -0,0 +1,108 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2010 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: $
"Geography constants"
#-------------------------------------------------------------------------
#
# standard python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import gen.lib
import osmgpsmap
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
ICONS = {
gen.lib.EventType.BIRTH : 'gramps-geo-birth',
gen.lib.EventType.DEATH : 'gramps-geo-death',
gen.lib.EventType.MARRIAGE : 'gramps-geo-marriage',
}
# map providers
OPENSTREETMAP = 1
OPENSTREETMAP_RENDERER = 2
OPENAERIALMAP = 3
MAPS_FOR_FREE = 4
GOOGLE_STREET = 5
GOOGLE_SATELLITE = 6
GOOGLE_HYBRID = 7
VIRTUAL_EARTH_STREET = 8
VIRTUAL_EARTH_SATELLITE = 9
VIRTUAL_EARTH_HYBRID = 10
YAHOO_STREET = 11
YAHOO_SATELLITE = 12
YAHOO_HYBRID = 13
tiles_path = {
OPENSTREETMAP : "openstreetmap",
OPENSTREETMAP_RENDERER : "openstreetmaprenderer",
OPENAERIALMAP : "openaerialmap",
MAPS_FOR_FREE : "mapsforfree",
GOOGLE_STREET : "googlestreet",
GOOGLE_SATELLITE : "googlesat",
GOOGLE_HYBRID : "googlehybrid",
VIRTUAL_EARTH_STREET : "virtualearthstreet",
VIRTUAL_EARTH_SATELLITE : "virtualearthsat",
VIRTUAL_EARTH_HYBRID : "virtualearthhybrid",
YAHOO_STREET : "yahoostreet",
YAHOO_SATELLITE : "yahoosat",
YAHOO_HYBRID : "yahoohybrid",
}
map_title = {
OPENSTREETMAP : "OpenStreetMap",
OPENSTREETMAP_RENDERER : "OpenStreetMap renderer",
OPENAERIALMAP : "OpenAerialMap",
MAPS_FOR_FREE : "Maps For Free",
GOOGLE_STREET : "Google street",
GOOGLE_SATELLITE : "Google sat",
GOOGLE_HYBRID : "Google hybrid",
VIRTUAL_EARTH_STREET : "Virtualearth street",
VIRTUAL_EARTH_SATELLITE : "Virtualearth sat",
VIRTUAL_EARTH_HYBRID : "Virtualearth hybrid",
YAHOO_STREET : "Yahoo street",
YAHOO_SATELLITE : "Yahoo sat",
YAHOO_HYBRID : "Yahoo hybrid",
}
map_type = {
OPENSTREETMAP : osmgpsmap.SOURCE_OPENSTREETMAP,
OPENSTREETMAP_RENDERER : osmgpsmap.SOURCE_OPENSTREETMAP_RENDERER,
OPENAERIALMAP : osmgpsmap.SOURCE_OPENAERIALMAP,
MAPS_FOR_FREE : osmgpsmap.SOURCE_MAPS_FOR_FREE,
GOOGLE_STREET : osmgpsmap.SOURCE_GOOGLE_STREET,
GOOGLE_SATELLITE : osmgpsmap.SOURCE_GOOGLE_SATELLITE,
GOOGLE_HYBRID : osmgpsmap.SOURCE_GOOGLE_HYBRID,
VIRTUAL_EARTH_STREET : osmgpsmap.SOURCE_VIRTUAL_EARTH_STREET,
VIRTUAL_EARTH_SATELLITE : osmgpsmap.SOURCE_VIRTUAL_EARTH_SATELLITE,
VIRTUAL_EARTH_HYBRID : osmgpsmap.SOURCE_VIRTUAL_EARTH_HYBRID,
YAHOO_STREET : osmgpsmap.SOURCE_YAHOO_STREET,
YAHOO_SATELLITE : osmgpsmap.SOURCE_YAHOO_SATELLITE,
YAHOO_HYBRID : osmgpsmap.SOURCE_YAHOO_HYBRID,
}

View File

@ -0,0 +1,733 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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
#
#-------------------------------------------------------------------------
from gen.ggettext import sgettext as _
from gen.ggettext import ngettext
import sys
import os
import gobject
import time
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
_LOG = logging.getLogger(".geography")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
import gen.lib
import Utils
from gui.views.navigationview import NavigationView
from libformatting import FormattingHelper
import Errors
import Bookmarks
import const
import constfunc
from grampsmaps import *
import constants
from config import config
from gui.editors import EditPlace, EditEvent, EditFamily, EditPerson
from gui.selectors.selectplace import SelectPlace
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
GEOGRAPHY_PATH = os.path.join(const.HOME_DIR, "maps")
#-------------------------------------------------------------------------
#
# Functions
#
#-------------------------------------------------------------------------
def _get_sign(value):
"""
return 1 if we have a negative number, 0 in other case
"""
if value < 0.0:
return 1
else:
return 0
def _get_zoom_lat(value):
"""
return the zoom value for latitude depending on the distance.
"""
zoomlat = 1
for i, distance in enumerate([80.0, 40.0, 20.0, 10.0, 3.0,
2.0, 1.0, 0.5, 0.2, 0.1]):
if value < distance:
zoomlat = i+1
return zoomlat + 3
def _get_zoom_long(value):
"""
return the zoom value for longitude depending on the distance.
"""
zoomlong = 1
for i, distance in enumerate([120.0, 60.0, 30.0, 15.0, 7.0,
4.0, 2.0, 1.0, .5, .2, .1]):
if value < distance:
zoomlong = i+1
return zoomlong + 3
#-------------------------------------------------------------------------
#
# GeoGraphyView
#
#-------------------------------------------------------------------------
class GeoGraphyView(osmGpsMap, NavigationView):
"""
View for pedigree tree.
Displays the ancestors of a selected individual.
"""
#settings in the config file
CONFIGSETTINGS = (
('geography.path', GEOGRAPHY_PATH),
('geography.zoom', 10),
('geography.show_cross', True),
('geography.lock', False),
('geography.center-lat', 0.0),
('geography.center-lon', 0.0),
#('geography.gps_mode', GPS_DISABLED),
#('geography.gps_update_rate', float(1.0)),
#('geography.max_gps_zoom', 16),
#('geography.gps_increment', GPS_INCREMENT),
('geography.map_service', constants.OPENSTREETMAP),
)
def __init__(self, title, pdata, dbstate, uistate,
get_bookmarks, bm_type, nav_group):
NavigationView.__init__(self, title, pdata, dbstate, uistate,
get_bookmarks, bm_type, nav_group)
self.dbstate = dbstate
self.dbstate.connect('database-changed', self.change_db)
self.default_text = "Enter location here!"
self.centerlon = config.get("geography.center-lon")
self.centerlat = config.get("geography.center-lat")
self.zoom = config.get("geography.zoom")
self.lock = config.get("geography.lock")
if config.get('geography.path') == "" :
config.set('geography.path', GEOGRAPHY_PATH )
osmGpsMap.__init__(self)
self.format_helper = FormattingHelper(self.dbstate)
self.centerlat = self.centerlon = 0.0
self.cross_map = None
self.current_map = None
self.without = 0
self.geo_mainmap = gtk.gdk.pixbuf_new_from_file_at_size(
os.path.join(const.ROOT_DIR, "images", "22x22",
('gramps-geo-mainmap' + '.png' )),
22, 22)
self.geo_altmap = gtk.gdk.pixbuf_new_from_file_at_size(
os.path.join(const.ROOT_DIR, "images", "22x22",
('gramps-geo-altmap' + '.png' )),
22, 22)
if ( config.get('geography.map_service') in
( constants.OPENSTREETMAP, constants.OPENSTREETMAP_RENDERER )):
default_image = self.geo_mainmap
else:
default_image = self.geo_altmap
self.geo_othermap = {}
for id in ( gen.lib.EventType.BIRTH,
gen.lib.EventType.DEATH,
gen.lib.EventType.MARRIAGE ):
self.geo_othermap[id] = gtk.gdk.pixbuf_new_from_file_at_size(
os.path.join(const.ROOT_DIR, "images", "22x22",
(constants.ICONS.get(int(id), default_image) + '.png' )),
22, 22)
def change_page(self):
"""Called when the page changes."""
NavigationView.change_page(self)
self.uistate.clear_filter_results()
def on_delete(self):
"""
Save all modified environment
"""
NavigationView.on_delete(self)
self._config.save()
def change_db(self, db):
"""
Callback associated with DbState. Whenever the database
changes, this task is called. In this case, we rebuild the
columns, and connect signals to the connected database. Tree
is no need to store the database, since we will get the value
from self.state.db
"""
self.bookmarks.update_bookmarks(self.dbstate.db.get_bookmarks())
if self.active:
self.bookmarks.redraw()
def can_configure(self):
"""
See :class:`~gui.views.pageview.PageView
:return: bool
"""
return True
def config_connect(self):
"""
Overwriten from :class:`~gui.views.pageview.PageView method
This method will be called after the ini file is initialized,
use it to monitor changes in the ini file
"""
#-------------------------------------------------------------------------
#
# Map Menu
#
#-------------------------------------------------------------------------
def build_nav_menu(self, obj, event, lat, lon):
"""Builds the menu for actions on the map."""
menu = gtk.Menu()
menu.set_title(_('Map Menu'))
if config.get("geography.show_cross"):
title = _('Remove cross hair')
else:
title = _('Add cross hair')
add_item = gtk.MenuItem(title)
add_item.connect("activate", self.config_crosshair, event, lat , lon)
add_item.show()
menu.append(add_item)
if config.get("geography.lock"):
title = _('Unlock zoom and position')
else:
title = _('Lock zoom and position')
add_item = gtk.MenuItem(title)
add_item.connect("activate", self.config_zoom_and_position,
event, lat , lon)
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(_("Add place"))
add_item.connect("activate", self._add_place, event, lat , lon)
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(_("Link place"))
add_item.connect("activate", self._link_place, event, lat , lon)
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(_("Center here"))
add_item.connect("activate", self.set_center, event, lat , lon)
add_item.show()
menu.append(add_item)
# Add specific module menu
self.add_specific_menu(menu, event, lat, lon)
# Add a separator line
add_item = gtk.MenuItem(None)
add_item.show()
menu.append(add_item)
map_name = constants.map_title[config.get("geography.map_service")]
title = _("Replace '%(map)s' by =>" % {
'map' : map_name
})
add_item = gtk.MenuItem(title)
add_item.show()
menu.append(add_item)
changemap = gtk.Menu()
changemap.set_title(title)
changemap.show()
add_item.set_submenu(changemap)
# show in the map menu all available providers
for map in constants.map_type:
changemapitem = gtk.MenuItem(constants.map_title[map])
changemapitem.show()
changemapitem.connect("activate", self.change_map, map)
changemap.append(changemapitem)
menu.popup(None, None, None, 0, event.time)
return 1
def add_specific_menu(self, menu, event, lat, lon):
"""
Add specific entry to the navigation menu.
Must be done in the associated menu.
"""
raise NotImplementedError
def set_center(self, menu, event, lat, lon):
"""
Center the map at the new position then save it.
"""
self.osm.set_center_and_zoom(lat, lon, 12)
self.save_center(lat, lon)
#-------------------------------------------------------------------------
#
# Markers management
#
#-------------------------------------------------------------------------
def is_there_a_marker_here(self, event, lat, lon):
"""
Is there a marker at this position ?
"""
found = False
mark_selected = []
self.uistate.set_busy_cursor(1)
for mark in self.sort:
# as we are not precise with our hand, reduce the precision
# depending on the zoom.
precision = {
1 : '%3.0f', 2 : '%3.0f', 3 : '%3.0f', 4 : '%3.0f',
5 : '%3.0f', 6 : '%3.1f', 7 : '%3.1f', 8 : '%3.1f',
9 : '%3.1f', 10 : '%3.1f', 11 : '%3.2f', 12 : '%3.2f',
13 : '%3.2f', 14 : '%3.3f', 15 : '%3.3f', 16 : '%3.4f',
17 : '%3.4f', 18 : '%3.5f'
}.get(config.get("geography.zoom"), '%3.1f')
latp = precision % lat
lonp = precision % lon
mlatp = precision % float(mark[3])
mlonp = precision % float(mark[4])
_LOG.debug(" compare latitude : %s with %s (precision = %s)"
" place='%s'" % (float(mark[3]), lat, precision,
mark[0]))
_LOG.debug("compare longitude : %s with %s (precision = %s)"
" zoom=%d" % (float(mark[4]), lon, precision,
config.get("geography.zoom")))
if mlatp == latp and mlonp == lonp:
_LOG.debug(" compare latitude : %s with %s OK" % (mlatp, latp))
_LOG.debug("compare longitude : %s with %s OK" % (mlonp, lonp))
mark_selected.append(mark)
found = True
if found:
self.bubble_message(event, lat, lon, mark_selected)
self.uistate.set_busy_cursor(0)
def bubble_message(self, event, lat, lon, mark):
"""
Display the bubble message. depends on the view.
"""
raise NotImplementedError
def add_marker(self, menu, event, lat, lon, event_type, differtype):
"""
Add a new marker
"""
mapservice = config.get('geography.map_service')
if ( mapservice in ( constants.OPENSTREETMAP,
constants.OPENSTREETMAP_RENDERER )):
default_image = self.geo_mainmap
else:
default_image = self.geo_altmap
value = default_image
if event_type is not None:
value = self.geo_othermap.get(int(event_type), default_image)
if differtype: # in case multiple evts
value = default_image # we use default icon.
marker = self.osm.image_add_with_alignment(float(lat),
float(lon), value, 0.2, 1.0)
def remove_all_gps(self):
"""
Remove all gps points on the map
"""
self.osm.gps_clear()
def remove_all_tracks(self):
"""
Remove all tracks on the map
"""
self.osm.track_remove_all()
def remove_all_markers(self):
"""
Remove all markers on the map
"""
self.osm.image_remove_all()
def _present_in_places_list(self, index, string):
"""
Search a string in place_list depending index
"""
found = any(p[index] == string for p in self.place_list)
return found
def _append_to_places_list(self, place, evttype, name, lat,
longit, descr, year, icontype,
gramps_id, place_id, event_id, family_id
):
"""
Create a list of places with coordinates.
"""
found = any(p[0] == place for p in self.place_list)
if not found:
self.nbplaces += 1
self.place_list.append([place, name, evttype, lat,
longit, descr, year, icontype,
gramps_id, place_id, event_id, family_id
])
self.nbmarkers += 1
tfa = float(lat)
tfb = float(longit)
if year is not None:
tfc = int(year)
if tfc != 0:
if tfc < self.minyear:
self.minyear = tfc
if tfc > self.maxyear:
self.maxyear = tfc
tfa += 0.00000001 if tfa >= 0 else -0.00000001
tfb += 0.00000001 if tfb >= 0 else -0.00000001
if self.minlat == 0.0 or tfa < self.minlat:
self.minlat = tfa
if self.maxlat == 0.0 or tfa > self.maxlat:
self.maxlat = tfa
if self.minlon == 0.0 or tfb < self.minlon:
self.minlon = tfb
if self.maxlon == 0.0 or tfb > self.maxlon:
self.maxlon = tfb
def _append_to_places_without_coord(self, gid, place):
"""
Create a list of places without coordinates.
"""
if not [gid, place] in self.place_without_coordinates:
self.place_without_coordinates.append([gid, place])
self.without += 1
def _create_markers(self):
"""
Create all markers for the specified person.
"""
self.remove_all_markers()
self.remove_all_gps()
self.remove_all_tracks()
if ( self.current_map is not None and
self.current_map != config.get("geography.map_service") ):
self.change_map(self.osm, config.get("geography.map_service"))
last = ""
current = ""
differtype = False
savetype = None
lat = 0.0
lon = 0.0
icon = None
self.uistate.set_busy_cursor(True)
_LOG.debug("%s" % time.strftime("start create_marker : "
"%a %d %b %Y %H:%M:%S", time.gmtime()))
for mark in self.sort:
current = ([mark[3], mark[4]])
if last == "":
last = current
lat = mark[3]
lon = mark[4]
icon = mark[7]
differtype = False
continue
if last != current:
self.add_marker(None, None, lat, lon, icon, differtype)
differtype = False
last = current
lat = mark[3]
lon = mark[4]
icon = mark[7]
differtype = False
else: # This marker already exists. add info.
if ( mark[6] and icon != mark[7] ):
differtype = True
if ( lat != 0.0 and lon != 0.0 ):
self.add_marker(None, None, lat, lon, icon, differtype)
self._set_center_and_zoom()
_LOG.debug("%s" % time.strftime(" stop create_marker : "
"%a %d %b %Y %H:%M:%S", time.gmtime()))
self.uistate.set_busy_cursor(False)
def _set_center_and_zoom(self):
"""
Calculate the zoom.
The best should be an auto zoom to have all markers on the screen.
need some works here.
we start at zoom 1 until zoom y ( for this a preference )
If all markers are present, continue to zoom.
If some markers are missing : return to the zoom - 1
The following is too complex. In some case, all markers are not present.
"""
# Select the center of the map and the zoom
signminlon = _get_sign(self.minlon)
signminlat = _get_sign(self.minlat)
signmaxlon = _get_sign(self.maxlon)
signmaxlat = _get_sign(self.maxlat)
# auto zoom ?
if signminlon == signmaxlon:
maxlong = abs(abs(self.minlon) - abs(self.maxlon))
else:
maxlong = abs(abs(self.minlon) + abs(self.maxlon))
if signminlat == signmaxlat:
maxlat = abs(abs(self.minlat) - abs(self.maxlat))
else:
maxlat = abs(abs(self.minlat) + abs(self.maxlat))
# Calculate the zoom. all places must be displayed on the map.
zoomlat = _get_zoom_lat(maxlat)
zoomlong = _get_zoom_long(maxlong)
self.new_zoom = zoomlat if zoomlat < zoomlong else zoomlong
self.new_zoom -= 1
if self.new_zoom < 2:
self.new_zoom = 2
# We center the map on a point at the center of all markers
self.centerlat = maxlat/2
self.centerlon = maxlong/2
latit = longt = 0.0
for mark in self.sort:
if ( signminlat == signmaxlat ):
if signminlat == 1:
latit = self.minlat+self.centerlat
else:
latit = self.maxlat-self.centerlat
elif self.maxlat > self.centerlat:
latit = self.maxlat-self.centerlat
else:
latit = self.minlat+self.centerlat
if ( signminlon == signmaxlon ):
if signminlon == 1:
longt = self.minlon+self.centerlon
else:
longt = self.maxlon-self.centerlon
elif self.maxlon > self.centerlon:
longt = self.maxlon-self.centerlon
else:
longt = self.minlon+self.centerlon
# all maps: 0.0 for longitude and latitude means no location.
if latit == longt == 0.0:
latit = longt = 0.00000001
self.mustcenter = False
self.latit = latit
self.longt = longt
if not (latit == longt == 0.0):
self.mustcenter = True
if config.get("geography.lock"):
self.osm.set_center_and_zoom(config.get("geography.center-lat"),
config.get("geography.center-lon"),
config.get("geography.zoom") )
else:
self.osm.set_center_and_zoom(self.latit, self.longt, self.new_zoom)
self.save_center(self.latit, self.longt)
config.set("geography.zoom",self.new_zoom)
#-------------------------------------------------------------------------
#
# Specific functionalities
#
#-------------------------------------------------------------------------
def center_here(self, menu, event, lat, lon, mark):
"""
Center the map at the marker position
"""
self.set_center(menu, event, float(mark[3]), float(mark[4]))
def add_place_bubble_message(self, event, lat, lon, marks,
menu, message, mark):
"""
Create the place menu of a marker
"""
add_item = gtk.MenuItem()
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit place"))
modify.show()
modify.connect("activate", self.edit_place, event, lat, lon, mark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here, event, lat, lon, mark)
itemoption.append(center)
add_item = gtk.MenuItem()
add_item.show()
menu.append(add_item)
def edit_place(self, menu, event, lat, lon, mark):
"""
Edit the selected place at the marker position
"""
_LOG.debug("edit_place : %s" % mark[9])
# need to add code here to edit the event.
place = self.dbstate.db.get_place_from_gramps_id(mark[9])
try:
EditPlace(self.dbstate, self.uistate, [], place)
except Errors.WindowActiveError:
pass
def edit_person(self, menu, event, lat, lon, mark):
"""
Edit the selected person at the marker position
"""
_LOG.debug("edit_person : %s" % mark[8])
# need to add code here to edit the person.
person = self.dbstate.db.get_person_from_gramps_id(mark[8])
try:
EditPerson(self.dbstate, self.uistate, [], person)
except Errors.WindowActiveError:
pass
def edit_family(self, menu, event, lat, lon, mark):
"""
Edit the selected family at the marker position
"""
_LOG.debug("edit_family : %s" % mark[11])
# need to add code here to edit the family.
family = self.dbstate.db.get_family_from_gramps_id(mark[11])
try:
EditFamily(self.dbstate, self.uistate, [], family)
except Errors.WindowActiveError:
pass
def edit_event(self, menu, event, lat, lon, mark):
"""
Edit the selected event at the marker position
"""
_LOG.debug("edit_event : %s" % mark[10])
# need to add code here to edit the event.
event = self.dbstate.db.get_event_from_gramps_id(mark[10])
try:
EditEvent(self.dbstate, self.uistate, [], event)
except Errors.WindowActiveError:
pass
def _add_place(self, menu, event, lat, lon):
"""
Add a new place using longitude and latitude of location centered
on the map
"""
new_place = gen.lib.Place()
new_place.set_latitude(str(lat))
new_place.set_longitude(str(lon))
try:
EditPlace(self.dbstate, self.uistate, [], new_place)
except Errors.WindowActiveError:
pass
def _link_place(self, menu, event, lat, lon):
"""
Link an existing place using longitude and latitude of location centered
on the map
"""
selector = SelectPlace(self.dbstate, self.uistate, [])
place = selector.run()
if place:
place.set_latitude(str(lat))
place.set_longitude(str(lon))
try:
EditPlace(self.dbstate, self.uistate, [], place)
except Errors.WindowActiveError:
pass
#-------------------------------------------------------------------------
#
# Geography preferences
#
#-------------------------------------------------------------------------
def _get_configure_page_funcs(self):
"""
The function which is used to create the configuration window.
"""
return [self.map_options]
def config_zoom_and_position(self, client, cnxn_id, entry, data):
"""
Do we need to lock the zoom and position ?
"""
if config.get("geography.lock"):
config.set("geography.lock", False)
self._set_center_and_zoom()
else:
config.set("geography.lock", True)
self.lock = config.get("geography.lock")
pass
def config_crosshair(self, client, cnxn_id, entry, data):
"""
We asked to change the crosshair.
"""
if config.get("geography.show_cross"):
config.set("geography.show_cross", False)
else:
config.set("geography.show_cross", True)
self.set_crosshair(config.get("geography.show_cross"))
pass
def map_options(self, configdialog):
"""
Function that builds the widget in the configuration dialog
for the map options.
"""
table = gtk.Table(2, 2)
table.set_border_width(12)
table.set_col_spacings(6)
table.set_row_spacings(6)
configdialog.add_text(table,
_('Where to save the tiles for offline mode.'),
1)
configdialog.add_entry(table, '',
2, 'geography.path')
configdialog.add_text(table,
_('If you have no more space in your file system\n'
'You can remove all tiles placed in the above path.\n'
'Be careful! If you have no internet, you\'ll get no map.'),
3)
# there is no button. I need to found a solution for this.
# it can be very dangerous ! if someone put / in geography.path ...
# perhaps we need some contrôl on this path :
# should begin with : /home, /opt, /map, ...
#configdialog.add_button(table, '', 4, 'geography.clean')
return _('The map'), table

View File

@ -0,0 +1,193 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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 sys
import os
import gobject
#------------------------------------------------------------------------
#
# Set up logging
#
#------------------------------------------------------------------------
import logging
_LOG = logging.getLogger("maps.osmgpsmap")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
import const
import constants
from gen.ggettext import sgettext as _
from gen.ggettext import ngettext
from config import config
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
GEOGRAPHY_PATH = os.path.join(const.HOME_DIR, "maps")
#-------------------------------------------------------------------------
#
# osmGpsMap
#
#-------------------------------------------------------------------------
try:
import osmgpsmap
except:
raise
class DummyMapNoGpsPoint(osmgpsmap.GpsMap):
def do_draw_gps_point(self, drawable):
pass
gobject.type_register(DummyMapNoGpsPoint)
class DummyLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
def __init__(self):
gobject.GObject.__init__(self)
def do_draw(self, gpsmap, gdkdrawable):
pass
def do_render(self, gpsmap):
pass
def do_busy(self):
return False
def do_button_press(self, gpsmap, gdkeventbutton):
return False
gobject.type_register(DummyLayer)
class osmGpsMap():
def __init__(self):
self.vbox = None
self.cross_map = None
self.osm = None
self.show_tooltips = True
def build_widget(self):
self.vbox = gtk.VBox(False, 0)
cache_path = os.path.join(const.HOME_DIR, 'maps')
if not os.path.isdir(cache_path):
try:
os.mkdir(cache_path, 0750)
except:
ErrorDialog(_("Can't create tiles cache directory %s") %
cache_path )
return self.vbox
self.change_map(None,config.get("geography.map_service"))
return self.vbox
def change_map(self, obj, map_type):
if obj is not None:
self.osm.layer_remove_all()
self.osm.image_remove_all()
self.vbox.remove(self.osm)
self.osm.destroy()
tiles_path=os.path.join(GEOGRAPHY_PATH, constants.tiles_path[map_type])
if not os.path.isdir(tiles_path):
try:
os.mkdir(tiles_path, 0750)
except:
ErrorDialog(_("Can't create tiles cache directory for '%s'.") %
constants.map_title[map_type])
config.set("geography.map_service", map_type)
self.current_map = map_type
if 0:
self.osm = DummyMapNoGpsPoint()
else:
self.osm = osmgpsmap.GpsMap(tile_cache=tiles_path,
map_source=constants.map_type[map_type])
current_map = osmgpsmap.GpsMapOsd( show_dpad=False, show_zoom=True)
self.osm.layer_add(current_map)
self.osm.layer_add( DummyLayer())
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"),
config.get("geography.center-lon"),
config.get("geography.zoom") )
self.osm.connect('button_release_event', self.map_clicked)
self.osm.connect('changed', self.zoom_changed)
self.osm.show()
self.vbox.pack_start(self.osm)
if obj is not None:
self._createmap(None)
def zoom_changed(self, zoom):
config.set("geography.zoom",self.osm.props.zoom)
self.save_center(self.osm.props.latitude, self.osm.props.longitude)
def save_center(self, lat, lon):
"""
Save the longitude and lontitude in case we switch between maps.
"""
config.set("geography.center-lat",lat)
config.set("geography.center-lon",lon)
def map_clicked(self, osm, event):
lat,lon = self.osm.get_event_location(event).get_degrees()
if event.button == 1:
# do we click on a marker ?
marker = self.is_there_a_marker_here(event, lat, lon)
elif event.button == 3:
self.build_nav_menu(osm, event, lat, lon )
else:
self.save_center(lat,lon)
def is_there_a_marker_here(self, lat, lon):
raise NotImplementedError
def set_crosshair(self,active):
"""
Show or hide the crosshair ?
"""
if active:
self.cross_map = osmgpsmap.GpsMapOsd( show_crosshair=True)
self.osm.layer_add( self.cross_map )
# The two following are to force the map to update
self.osm.zoom_in()
self.osm.zoom_out()
else:
self.osm.layer_remove(self.cross_map)
pass

View File

@ -10,8 +10,12 @@ pkgdata_PYTHON = \
familyview.py \
fanchartview.gpr.py \
fanchartview.py \
geoview.py \
geoview.gpr.py \
geoevents.py \
geoplaces.py \
geoperson.py \
geofamily.py \
geography.gpr.py \
htmlrenderer.gpr.py \
grampletview.py \
htmlrenderer.py \
mediaview.py \

View File

@ -0,0 +1,382 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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: $
"""
Geography for events
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import os
import sys
import urlparse
import const
import operator
import locale
from gtk.keysyms import Tab as KEY_TAB
import socket
import gtk
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
_LOG = logging.getLogger("GeoGraphy.geoevents")
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
import gen.lib
import Utils
import config
import Errors
from gen.display.name import displayer as _nd
from PlaceUtils import conv_lat_lon
from gui.views.pageview import PageView
from gui.editors import EditPlace
from gui.selectors.selectplace import SelectPlace
from Filters.SideBar import EventSidebarFilter
from gui.views.navigationview import NavigationView
import Bookmarks
from Utils import navigation_label
from maps.geography import GeoGraphyView
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_UI_DEF = '''\
<ui>
<menubar name="MenuBar">
<menu action="GoMenu">
<placeholder name="CommonGo">
<menuitem action="Back"/>
<menuitem action="Forward"/>
<separator/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
</placeholder>
</toolbar>
</ui>
'''
#-------------------------------------------------------------------------
#
# GeoView
#
#-------------------------------------------------------------------------
class GeoEvents(GeoGraphyView):
"""
The view used to render events map.
"""
def __init__(self, pdata, dbstate, uistate, nav_group=0):
GeoGraphyView.__init__(self, _('Events places map'),
pdata, dbstate, uistate,
dbstate.db.get_event_bookmarks(),
Bookmarks.EventBookmarks,
nav_group)
self.dbstate = dbstate
self.uistate = uistate
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
self.nbplaces = 0
self.nbmarkers = 0
self.sort = []
self.generic_filter = None
self.additional_uis.append(self.additional_ui())
def get_title(self):
"""
Used to set the titlebar in the configuration window.
"""
return _('GeoEvents')
def get_stock(self):
"""
Returns the name of the stock icon to use for the display.
This assumes that this icon has already been registered
as a stock icon.
"""
return 'geo-show-events'
def get_viewtype_stock(self):
"""Type of view in category
"""
return 'geo-show-events'
def additional_ui(self):
"""
Specifies the UIManager XML code that defines the menus and buttons
associated with the interface.
"""
return _UI_DEF
def navigation_type(self):
"""
Indicates the navigation type. Navigation type can be the string
name of any of the primary objects.
"""
return 'Event'
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_event_bookmarks()
def goto_handle(self, handle=None):
"""
Rebuild the tree with the given events handle as the root.
"""
if handle:
self.change_active(handle)
self._createmap(handle)
self.uistate.modify_statusbar(self.dbstate)
def show_all_events(self, menu, event, lat, lon):
"""
Ask to show all events.
"""
self._createmap(None)
def build_tree(self):
"""
This is called by the parent class when the view becomes visible. Since
all handling of visibility is now in rebuild_trees, see that for more
information.
"""
active = self.uistate.get_active('Event')
if active:
self._createmap(active)
else:
self._createmap(None)
def _createmap_for_one_event(self,event):
"""
Create all markers for each people's event in the database which has
a lat/lon.
"""
dbstate = self.dbstate
descr = descr2 = ""
place_handle = event.get_place_handle()
eventyear = event.get_date_object().to_calendar(self.cal).get_year()
if place_handle:
place = dbstate.db.get_place_from_handle(place_handle)
if place:
descr1 = place.get_title()
longitude = place.get_longitude()
latitude = place.get_latitude()
latitude, longitude = conv_lat_lon(latitude, longitude, "D.D8")
# place.get_longitude and place.get_latitude return
# one string. We have coordinates when the two values
# contains non null string.
if ( longitude and latitude ):
person_list = [
dbstate.db.get_person_from_handle(ref_handle)
for (ref_type, ref_handle) in
dbstate.db.find_backlink_handles(event.handle)
if ref_type == 'Person'
]
if person_list:
for person in person_list:
if descr2 == "":
descr2 = ("%s") % _nd.display(person)
else:
descr2 = ("%s - %s") % ( descr2,
_nd.display(person))
else:
# family list ?
family_list = [
dbstate.db.get_family_from_handle(ref_handle)
for (ref_type, ref_handle) in
dbstate.db.find_backlink_handles(event.handle)
if ref_type == 'Family'
]
if family_list:
for family in family_list:
hdle = family.get_father_handle()
father = dbstate.db.get_person_from_handle(hdle)
hdle = family.get_mother_handle()
mother = dbstate.db.get_person_from_handle(hdle)
descr2 = ("%(father)s - %(mother)s") % {
'father': _nd.display(father) if father is not None else "?",
'mother': _nd.display(mother) if mother is not None else "?"
}
else:
descr2 = _("incomplete or unreferenced event ?")
self._append_to_places_list(descr1, None,
None,
latitude, longitude,
descr2,
eventyear,
event.get_type(),
None, # person.gramps_id
place.gramps_id,
event.gramps_id,
None
)
else:
descr = place.get_title()
self._append_to_places_without_coord(
place.gramps_id, descr)
def _createmap(self,obj):
"""
Create all markers for each people's event in the database which has
a lat/lon.
"""
dbstate = self.dbstate
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
latitude = ""
longitude = ""
self.without = 0
self.cal = config.get('preferences.calendar-format-report')
if self.generic_filter:
events_list = self.generic_filter.apply(dbstate.db)
for event_handle in events_list:
event = dbstate.db.get_event_from_handle(event_handle)
self._createmap_for_one_event(event)
else:
if obj is None:
events_handle = dbstate.db.iter_event_handles()
for event_hdl in events_handle:
event = dbstate.db.get_event_from_handle(event_hdl)
self._createmap_for_one_event(event)
else:
event = dbstate.db.get_event_from_handle(obj)
self._createmap_for_one_event(event)
self.sort = sorted(self.place_list,
key=operator.itemgetter(6)
)
self._create_markers()
def bubble_message(self, event, lat, lon, marks):
menu = gtk.Menu()
menu.set_title("events")
message = ""
oldplace = ""
prevmark = None
for mark in marks:
if message != "":
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event,
event, lat, lon, prevmark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here,
event, lat, lon, prevmark)
itemoption.append(center)
if mark[0] != oldplace:
if message != "":
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event,
event, lat, lon, mark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here,
event, lat, lon, mark)
itemoption.append(center)
message = "%s :" % mark[0]
self.add_place_bubble_message(event, lat, lon,
marks, menu, message, mark)
oldplace = mark[0]
message = "%s : %s" % (gen.lib.EventType( mark[7] ), mark[5] )
prevmark = mark
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event, event, lat, lon, prevmark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here, event, lat, lon, prevmark)
itemoption.append(center)
menu.popup(None, None, None, 0, event.time)
return 1
def add_specific_menu(self, menu, event, lat, lon):
"""
Add specific entry to the navigation menu.
"""
add_item = gtk.MenuItem()
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(_("Show all events"))
add_item.connect("activate", self.show_all_events, event, lat , lon)
add_item.show()
menu.append(add_item)

View File

@ -0,0 +1,430 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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: $
"""
Geography for one family
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import os
import sys
import urlparse
import const
import operator
import locale
from gtk.keysyms import Tab as KEY_TAB
import socket
import gtk
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
_LOG = logging.getLogger("GeoGraphy.geofamily")
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
import gen.lib
import Utils
import config
import Errors
from gen.display.name import displayer as _nd
from PlaceUtils import conv_lat_lon
from gui.views.pageview import PageView
from gui.editors import EditPlace
from gui.selectors.selectplace import SelectPlace
from Filters.SideBar import FamilySidebarFilter
from gui.views.navigationview import NavigationView
import Bookmarks
from Utils import navigation_label
from maps.geography import GeoGraphyView
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_UI_DEF = '''\
<ui>
<menubar name="MenuBar">
<menu action="GoMenu">
<placeholder name="CommonGo">
<menuitem action="Back"/>
<menuitem action="Forward"/>
<separator/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
</placeholder>
</toolbar>
</ui>
'''
#-------------------------------------------------------------------------
#
# GeoView
#
#-------------------------------------------------------------------------
class GeoFamily(GeoGraphyView):
"""
The view used to render person map.
"""
def __init__(self, pdata, dbstate, uistate, nav_group=0):
GeoGraphyView.__init__(self, _('Family places map'),
pdata, dbstate, uistate,
dbstate.db.get_family_bookmarks(),
Bookmarks.FamilyBookmarks,
nav_group)
self.dbstate = dbstate
self.uistate = uistate
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
self.nbplaces = 0
self.nbmarkers = 0
self.sort = []
self.additional_uis.append(self.additional_ui())
def get_title(self):
"""
Used to set the titlebar in the configuration window.
"""
return _('GeoFamily')
def get_stock(self):
"""
Returns the name of the stock icon to use for the display.
This assumes that this icon has already been registered
as a stock icon.
"""
return 'geo-show-family'
def get_viewtype_stock(self):
"""Type of view in category
"""
return 'geo-show-family'
def additional_ui(self):
"""
Specifies the UIManager XML code that defines the menus and buttons
associated with the interface.
"""
return _UI_DEF
def navigation_type(self):
"""
Indicates the navigation type. Navigation type can be the string
name of any of the primary objects.
"""
return 'Family'
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_family_bookmarks()
def goto_handle(self, handle=None):
"""
Rebuild the tree with the given person handle as the root.
"""
if handle:
self.change_active(handle)
self._createmap(handle)
self.uistate.modify_statusbar(self.dbstate)
def build_tree(self):
"""
This is called by the parent class when the view becomes visible. Since
all handling of visibility is now in rebuild_trees, see that for more
information.
"""
if self.uistate.get_active('Family'):
self._createmap(self.uistate.get_active('Family'))
else:
self._createmap(self.uistate.get_active('Person'))
def _get_father_and_mother_name(self, event):
"""
Return the father and mother name of a family event
"""
dbstate = self.dbstate
family_list = [
dbstate.db.get_family_from_handle(ref_handle)
for (ref_type, ref_handle) in
dbstate.db.find_backlink_handles(event.handle)
if ref_type == 'Family'
]
if family_list:
for family in family_list:
handle = family.get_father_handle()
father = dbstate.db.get_person_from_handle(handle)
handle = family.get_mother_handle()
mother = dbstate.db.get_person_from_handle(handle)
fnam = _nd.display(father) if father else "???"
mnam = _nd.display(mother) if mother else "???"
return ( fnam, mnam )
def _createpersonmarkers(self, dbstate, person, comment, fam_id):
"""
Create all markers for the specified person.
"""
self.cal = config.get('preferences.calendar-format-report')
latitude = longitude = ""
if person:
# For each event, if we have a place, set a marker.
for event_ref in person.get_event_ref_list():
if not event_ref:
continue
event = dbstate.db.get_event_from_handle(event_ref.ref)
eyear = event.get_date_object().to_calendar(self.cal).get_year()
place_handle = event.get_place_handle()
if place_handle:
place = dbstate.db.get_place_from_handle(place_handle)
if place:
longitude = place.get_longitude()
latitude = place.get_latitude()
latitude, longitude = conv_lat_lon(latitude,
longitude, "D.D8")
descr = place.get_title()
evt = gen.lib.EventType(event.get_type())
descr1 = _("%(eventtype)s : %(name)s") % {
'eventtype': evt,
'name': _nd.display(person)}
# place.get_longitude and place.get_latitude return
# one string. We have coordinates when the two values
# contains non null string.
if ( longitude and latitude ):
if not self._present_in_places_list(2, str(descr1 + descr + str(evt))):
self._append_to_places_list(descr,
str(descr1 + descr + str(evt)),
_nd.display(person),
latitude, longitude,
descr1, eyear,
event.get_type(),
person.gramps_id,
place.gramps_id,
event.gramps_id,
fam_id
)
else:
self._append_to_places_without_coord(
place.gramps_id, descr)
family_list = person.get_family_handle_list()
for family_hdl in family_list:
family = self.dbstate.db.get_family_from_handle(family_hdl)
if family is not None:
for event_ref in family.get_event_ref_list():
if event_ref:
event = dbstate.db.get_event_from_handle(event_ref.ref)
if event.get_place_handle():
place_handle = event.get_place_handle()
if place_handle:
place = dbstate.db.get_place_from_handle(place_handle)
if place:
longitude = place.get_longitude()
latitude = place.get_latitude()
latitude, longitude = conv_lat_lon(latitude,
longitude, "D.D8")
descr = place.get_title()
evt = gen.lib.EventType(event.get_type())
(father_name, mother_name) = self._get_father_and_mother_name(event)
descr1 = "%s : %s - " % ( evt, father_name )
descr1 = "%s%s" % ( descr1, mother_name )
eyear = event.get_date_object().to_calendar(self.cal).get_year()
if ( longitude and latitude ):
if not self._present_in_places_list(2, str(descr1 + descr + str(evt))):
self._append_to_places_list(descr,
str(descr1 + descr + str(evt)),
_nd.display(person),
latitude, longitude,
descr1, eyear,
event.get_type(),
person.gramps_id,
place.gramps_id,
event.gramps_id,
family.gramps_id
)
else:
self._append_to_places_without_coord( place.gramps_id, descr)
def _createmap_for_one_family(self, family):
"""
Create all markers for one family : all event's places with a lat/lon.
"""
dbstate = self.dbstate
try:
person = dbstate.db.get_person_from_handle(family.get_father_handle())
except:
return
family_id = family.gramps_id
if person is None: # family without father ?
person = dbstate.db.get_person_from_handle(family.get_mother_handle())
if person is None:
person = dbstate.db.get_person_from_handle(self.uistate.get_active('Person'))
if person is not None:
family_list = person.get_family_handle_list()
if len(family_list) > 0:
fhandle = family_list[0] # first is primary
fam = dbstate.db.get_family_from_handle(fhandle)
handle = fam.get_father_handle()
father = dbstate.db.get_person_from_handle(handle)
if father:
comment = _("Father : %s : %s") % ( father.gramps_id,
_nd.display(father) )
self._createpersonmarkers(dbstate, father,
comment, family_id)
handle = fam.get_mother_handle()
mother = dbstate.db.get_person_from_handle(handle)
if mother:
comment = _("Mother : %s : %s") % ( mother.gramps_id,
_nd.display(mother) )
self._createpersonmarkers(dbstate, mother,
comment, family_id)
index = 0
child_ref_list = fam.get_child_ref_list()
if child_ref_list:
for child_ref in child_ref_list:
child = dbstate.db.get_person_from_handle(child_ref.ref)
if child:
index += 1
comment = _("Child : %(id)s - %(index)d "
": %(name)s") % {
'id' : child.gramps_id,
'index' : index,
'name' : _nd.display(child)
}
self._createpersonmarkers(dbstate, child,
comment, family_id)
else:
comment = _("Person : %(id)s %(name)s has no family.") % {
'id' : person.gramps_id ,
'name' : _nd.display(person)
}
self._createpersonmarkers(dbstate, person, comment, family_id)
def _createmap(self, family_x):
"""
Create all markers for each people's event in the database which has
a lat/lon.
"""
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
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'))
if not person:
return
family_list = person.get_family_handle_list()
for family_hdl in family_list:
family = self.dbstate.db.get_family_from_handle(family_hdl)
if family is not None:
self._createmap_for_one_family(family)
else:
self._createmap_for_one_family(family)
self.sort = sorted(self.place_list,
key=operator.itemgetter(3, 4, 6)
)
self._create_markers()
def add_event_bubble_message(self, event, lat, lon, mark, menu):
itemoption = gtk.Menu()
itemoption.show()
menu.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit family"))
modify.show()
modify.connect("activate", self.edit_family, event, lat, lon, mark)
itemoption.append(modify)
modify = gtk.MenuItem(_("Edit person"))
modify.show()
modify.connect("activate", self.edit_person, event, lat, lon, mark)
itemoption.append(modify)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event, event, lat, lon, mark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here, event, lat, lon, mark)
itemoption.append(center)
def bubble_message(self, event, lat, lon, marks):
menu = gtk.Menu()
menu.set_title("family")
message = ""
oldplace = ""
prevmark = None
for mark in marks:
if message != "":
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
self.add_event_bubble_message(event, lat, lon,
prevmark, add_item)
if mark[0] != oldplace:
message = "%s :" % mark[0]
self.add_place_bubble_message(event, lat, lon,
marks, menu, message, mark)
oldplace = mark[0]
message = "%s" % mark[5]
prevmark = mark
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
self.add_event_bubble_message(event, lat, lon, prevmark, add_item)
menu.popup(None, None, None, 0, event.time)
return 1
def add_specific_menu(self, menu, event, lat, lon):
"""
Add specific entry to the navigation menu.
"""
return

View File

@ -0,0 +1,104 @@
# encoding:utf-8
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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: $
#------------------------------------------------------------------------
#
# Geography view
#
#------------------------------------------------------------------------
try :
import osmgpsmap
OSMGPSMAP = True
except:
OSMGPSMAP = False
print _("WARNING: osmgpsmap module not loaded. "
"Geography functionality will not be available.")
if OSMGPSMAP:
# Load the view only if osmgpsmap library is present.
register(VIEW,
id = 'personmap',
name = _("person"),
description = _("A view allowing to see the places visited by "
"one person during his life."),
version = '1.0',
gramps_target_version = '3.3',
status = STABLE,
fname = 'geoperson.py',
authors = [u"Serge Noiraud"],
authors_email = [""],
category = ("Geography", _("Geography")),
viewclass = 'GeoPerson',
order = START,
stock_icon = 'geo-show-person',
)
register(VIEW,
id = 'placesmap',
name = _("places"),
description = _("A view allowing to see all places of the database."),
version = '1.0',
gramps_target_version = '3.3',
status = STABLE,
fname = 'geoplaces.py',
authors = [u"Serge Noiraud"],
authors_email = [""],
category = ("Geography", _("Geography")),
viewclass = 'GeoPlaces',
stock_icon = 'geo-show-place',
)
register(VIEW,
id = 'eventsmap',
name = _("events"),
description = _("A view allowing to see all events "
"places of the database."),
version = '1.0',
gramps_target_version = '3.3',
status = STABLE,
fname = 'geoevents.py',
authors = [u"Serge Noiraud"],
authors_email = [""],
category = ("Geography", _("Geography")),
viewclass = 'GeoEvents',
stock_icon = 'geo-show-event',
)
register(VIEW,
id = 'familymap',
name = _("family"),
description = _("A view allowing to see the places visited by "
"one family during all their life."),
version = '1.0',
gramps_target_version = '3.3',
status = STABLE,
order = START,
fname = 'geofamily.py',
authors = [u"Serge Noiraud"],
authors_email = [""],
category = ("Geography", _("Geography")),
viewclass = 'GeoFamily',
stock_icon = 'geo-show-family',
)

View File

@ -0,0 +1,431 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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: $
"""
Geography for one person
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import os
import sys
import urlparse
import const
import operator
import locale
from gtk.keysyms import Tab as KEY_TAB
import socket
import gtk
import glib
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
_LOG = logging.getLogger("GeoGraphy.geoperson")
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
import gen.lib
import Utils
import config
import Errors
from gen.display.name import displayer as _nd
from PlaceUtils import conv_lat_lon
from gui.views.pageview import PageView
from gui.editors import EditPlace
from gui.selectors.selectplace import SelectPlace
from Filters.SideBar import PersonSidebarFilter
from gui.views.navigationview import NavigationView
import Bookmarks
from Utils import navigation_label
from maps.geography import GeoGraphyView
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_UI_DEF = '''\
<ui>
<menubar name="MenuBar">
<menu action="GoMenu">
<placeholder name="CommonGo">
<menuitem action="Back"/>
<menuitem action="Forward"/>
<separator/>
<menuitem action="HomePerson"/>
<separator/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
<toolitem action="HomePerson"/>
</placeholder>
</toolbar>
</ui>
'''
#-------------------------------------------------------------------------
#
# GeoView
#
#-------------------------------------------------------------------------
class GeoPerson(GeoGraphyView):
"""
The view used to render person map.
"""
def __init__(self, pdata, dbstate, uistate, nav_group=0):
GeoGraphyView.__init__(self, _("Person places map"),
pdata, dbstate, uistate,
dbstate.db.get_bookmarks(),
Bookmarks.PersonBookmarks,
nav_group)
self.dbstate = dbstate
self.uistate = uistate
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
self.nbplaces = 0
self.nbmarkers = 0
self.sort = []
self.additional_uis.append(self.additional_ui())
def get_title(self):
"""
Used to set the titlebar in the configuration window.
"""
return _('GeoPerson')
def get_stock(self):
"""
Returns the name of the stock icon to use for the display.
This assumes that this icon has already been registered
as a stock icon.
"""
return 'geo-show-person'
def get_viewtype_stock(self):
"""Type of view in category
"""
return 'geo-show-person'
def additional_ui(self):
"""
Specifies the UIManager XML code that defines the menus and buttons
associated with the interface.
"""
return _UI_DEF
def navigation_type(self):
"""
Indicates the navigation type. Navigation type can be the string
name of any of the primary objects.
"""
return 'Person'
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_bookmarks()
def goto_handle(self, handle=None):
"""
Rebuild the tree with the given person handle as the root.
"""
if handle:
self.change_active(handle)
self._createmap(handle)
self.uistate.modify_statusbar(self.dbstate)
def build_tree(self):
"""
This is called by the parent class when the view becomes visible. Since
all handling of visibility is now in rebuild_trees, see that for more
information.
"""
active = self.get_active()
self._createmap(active)
def animate(self, menu, marks, index, stepyear):
"""
Create all movements for the people's event.
Yes, you can see the person moving.
"""
if len(marks) == 0:
self.already_started = False
return False
i = int(index)
ni = i + 1
if ni == len(marks) :
self.already_started = False
return False
startlat = float(marks[i][3])
startlon = float(marks[i][4])
heading = 1
if index == 0 and stepyear == 0:
self.remove_all_gps()
self.osm.gps_add(startlat, startlon, heading)
endlat = float(marks[ni][3])
endlon = float(marks[ni][4])
# year format = YYYYMMDD ( for sort )
startyear = str(marks[i][6])[0:4]
endyear = str(marks[ni][6])[0:4]
endmov = str(marks[len(marks)-1][6])[0:4]
years = int(endyear) - int(startyear)
if years < 1:
years = 1
latstep = ( endlat - startlat ) / years
lonstep = ( endlon - startlon ) / years
stepyear = 1 if stepyear < 1 else stepyear
startlat += ( latstep * stepyear )
startlon += ( lonstep * stepyear )
if ( int(startyear) + stepyear ) > int(endmov) :
self.already_started = False
return False
self.osm.gps_add(startlat, startlon, heading)
stepyear += 1
difflat = ( startlat - endlat ) if startlat > endlat else \
( endlat - startlat )
difflon = ( startlon - endlon ) if startlon > endlon else \
( endlon - startlon )
if ( difflat == 0.0 and difflon == 0.0 ):
i += 1
if ( int(startyear) + stepyear ) > int(endmov) :
self.already_started = False
return False
stepyear = 1
# 100ms => 1s per 10 years.
# For a 100 years person, it takes 10 secondes.
glib.timeout_add(100, self.animate, menu, marks, i, stepyear)
return False
def _createmap(self,obj):
"""
Create all markers for each people's event in the database which has
a lat/lon.
"""
dbstate = self.dbstate
self.cal = config.get('preferences.calendar-format-report')
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
latitude = ""
longitude = ""
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.
for event_ref in person.get_event_ref_list():
if not event_ref:
continue
event = dbstate.db.get_event_from_handle(event_ref.ref)
eyear = str("%04d" % event.get_date_object().to_calendar(self.cal).get_year()) + \
str("%02d" % event.get_date_object().to_calendar(self.cal).get_month()) + \
str("%02d" % event.get_date_object().to_calendar(self.cal).get_day())
place_handle = event.get_place_handle()
if place_handle:
place = dbstate.db.get_place_from_handle(place_handle)
if place:
longitude = place.get_longitude()
latitude = place.get_latitude()
latitude, longitude = conv_lat_lon(latitude,
longitude, "D.D8")
descr = place.get_title()
evt = gen.lib.EventType(event.get_type())
descr1 = _("%(eventtype)s : %(name)s") % {
'eventtype': evt,
'name': _nd.display(person)}
# place.get_longitude and place.get_latitude return
# one string. We have coordinates when the two values
# contains non null string.
if ( longitude and latitude ):
self._append_to_places_list(descr, evt,
_nd.display(person),
latitude, longitude,
descr1, eyear,
event.get_type(),
person.gramps_id,
place.gramps_id,
event.gramps_id,
None
)
else:
self._append_to_places_without_coord(
place.gramps_id, descr)
family_list = person.get_family_handle_list()
for family_hdl in family_list:
family = self.dbstate.db.get_family_from_handle(family_hdl)
if family is not None:
fhandle = family_list[0] # first is primary
fam = dbstate.db.get_family_from_handle(fhandle)
handle = fam.get_father_handle()
father = dbstate.db.get_person_from_handle(handle)
if father:
descr1 = "%s - " % _nd.display(father)
handle = fam.get_mother_handle()
mother = dbstate.db.get_person_from_handle(handle)
if mother:
descr1 = "%s%s" % ( descr1, _nd.display(mother))
for event_ref in family.get_event_ref_list():
if event_ref:
event = dbstate.db.get_event_from_handle(event_ref.ref)
if event.get_place_handle():
place_handle = event.get_place_handle()
if place_handle:
place = dbstate.db.get_place_from_handle(place_handle)
if place:
longitude = place.get_longitude()
latitude = place.get_latitude()
latitude, longitude = conv_lat_lon(latitude,
longitude, "D.D8")
descr = place.get_title()
evt = gen.lib.EventType(event.get_type())
eyear = str("%04d" % event.get_date_object().to_calendar(self.cal).get_year()) + \
str("%02d" % event.get_date_object().to_calendar(self.cal).get_month()) + \
str("%02d" % event.get_date_object().to_calendar(self.cal).get_day())
if ( longitude and latitude ):
self._append_to_places_list(descr,
evt, _nd.display(person),
latitude, longitude,
descr1, eyear,
event.get_type(),
person.gramps_id,
place.gramps_id,
event.gramps_id,
None
)
else:
self._append_to_places_without_coord( place.gramps_id, descr)
self.sort = sorted(self.place_list,
key=operator.itemgetter(6)
)
self._create_markers()
def bubble_message(self, event, lat, lon, marks):
menu = gtk.Menu()
menu.set_title("person")
message = ""
oldplace = ""
prevmark = None
for mark in marks:
if oldplace != "":
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event,
event, lat, lon, prevmark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here,
event, lat, lon, prevmark)
itemoption.append(center)
if mark[0] != oldplace:
if message != "":
add_item = gtk.MenuItem()
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event,
event, lat, lon, mark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here,
event, lat, lon, mark)
itemoption.append(center)
message = "%s :" % mark[0]
self.add_place_bubble_message(event, lat, lon,
marks, menu, message, mark)
oldplace = mark[0]
message = "%s : %s" % ( mark[2], mark[1] )
prevmark = mark
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit event"))
modify.show()
modify.connect("activate", self.edit_event, event, lat, lon, prevmark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here, event, lat, lon, prevmark)
itemoption.append(center)
menu.popup(None, None, None, 0, event.time)
return 1
def add_specific_menu(self, menu, event, lat, lon):
"""
Add specific entry to the navigation menu.
"""
add_item = gtk.MenuItem()
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(_("Animate"))
add_item.connect("activate", self.animate, self.sort, 0, 0)
add_item.show()
menu.append(add_item)
return

View File

@ -0,0 +1,327 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2011 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: $
"""
Geography for places
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import os
import sys
import time
import urlparse
import const
import operator
import locale
from gtk.keysyms import Tab as KEY_TAB
import socket
import gtk
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
_LOG = logging.getLogger("GeoGraphy.geoplaces")
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
import gen.lib
import Utils
import config
import Errors
from gen.display.name import displayer as _nd
from PlaceUtils import conv_lat_lon
from gui.views.pageview import PageView
from gui.editors import EditPlace
from gui.selectors.selectplace import SelectPlace
from Filters.SideBar import PlaceSidebarFilter
from gui.views.navigationview import NavigationView
import Bookmarks
from Utils import navigation_label
from maps.geography import GeoGraphyView
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_UI_DEF = '''\
<ui>
<menubar name="MenuBar">
<menu action="GoMenu">
<placeholder name="CommonGo">
<menuitem action="Back"/>
<menuitem action="Forward"/>
<separator/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
</placeholder>
</toolbar>
</ui>
'''
#-------------------------------------------------------------------------
#
# GeoView
#
#-------------------------------------------------------------------------
class GeoPlaces(GeoGraphyView):
"""
The view used to render places map.
"""
def __init__(self, pdata, dbstate, uistate, nav_group=0):
GeoGraphyView.__init__(self, _('Places places map'),
pdata, dbstate, uistate,
dbstate.db.get_place_bookmarks(),
Bookmarks.PlaceBookmarks,
nav_group)
self.dbstate = dbstate
self.uistate = uistate
self.place_list = []
self.place_without_coordinates = []
self.minlat = self.maxlat = self.minlon = self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
self.nbplaces = 0
self.nbmarkers = 0
self.sort = []
self.generic_filter = None
self.additional_uis.append(self.additional_ui())
def get_title(self):
"""
Used to set the titlebar in the configuration window.
"""
return _('GeoPlaces')
def get_stock(self):
"""
Returns the name of the stock icon to use for the display.
This assumes that this icon has already been registered
as a stock icon.
"""
return 'geo-show-place'
def get_viewtype_stock(self):
"""Type of view in category
"""
return 'geo-show-place'
def additional_ui(self):
"""
Specifies the UIManager XML code that defines the menus and buttons
associated with the interface.
"""
return _UI_DEF
def navigation_type(self):
"""
Indicates the navigation type. Navigation type can be the string
name of any of the primary objects.
"""
return 'Place'
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_place_bookmarks()
def goto_handle(self, handle=None):
"""
Rebuild the tree with the given places handle as the root.
"""
if handle:
self.change_active(handle)
self._createmap(handle)
self.uistate.modify_statusbar(self.dbstate)
def show_all_places(self, menu, event, lat, lon):
"""
Ask to show all places.
"""
self._createmap(None)
def build_tree(self):
"""
This is called by the parent class when the view becomes visible. Since
all handling of visibility is now in rebuild_trees, see that for more
information.
"""
active = self.uistate.get_active('Place')
if active:
self._createmap(active)
else:
self._createmap(None)
def _create_one_place(self,place):
"""
Create one entry for one place with a lat/lon.
"""
descr = place.get_title()
longitude = place.get_longitude()
latitude = place.get_latitude()
latitude, longitude = conv_lat_lon(latitude, longitude, "D.D8")
# place.get_longitude and place.get_latitude return
# one string. We have coordinates when the two values
# contains non null string.
if ( longitude and latitude ):
self._append_to_places_list(descr, None, "",
latitude, longitude,
None, None,
gen.lib.EventType.UNKNOWN,
None, # person.gramps_id
place.gramps_id,
None, # event.gramps_id
None # family.gramps_id
)
else:
self._append_to_places_without_coord(place.gramps_id, descr)
def _createmap(self,place_x):
"""
Create all markers for each people's event in the database which has
a lat/lon.
"""
dbstate = self.dbstate
self.cal = config.get('preferences.calendar-format-report')
self.place_list = []
self.place_without_coordinates = []
self.minlat = 0.0
self.maxlat = 0.0
self.minlon = 0.0
self.maxlon = 0.0
self.minyear = 9999
self.maxyear = 0
self.without = 0
latitude = ""
longitude = ""
# base "villes de france" : 38101 places :
# createmap : 8'50"; create_markers : 1'23"
# base "villes de france" : 38101 places :
# createmap : 8'50"; create_markers : 0'07" with pixbuf optimization
_LOG.debug("%s" % time.strftime("start createmap : "
"%a %d %b %Y %H:%M:%S", time.gmtime()))
if self.generic_filter:
place_list = self.generic_filter.apply(dbstate.db)
for place_handle in place_list:
place = dbstate.db.get_place_from_handle(place_handle)
self._create_one_place(place)
else:
if place_x is None:
places_handle = dbstate.db.iter_place_handles()
for place_hdl in places_handle:
place = dbstate.db.get_place_from_handle(place_hdl)
self._create_one_place(place)
else:
place = dbstate.db.get_place_from_handle(place_x)
self._create_one_place(place)
_LOG.debug("%s" % time.strftime(" stop createmap and\nbegin sort : "
"%a %d %b %Y %H:%M:%S", time.gmtime()))
self.sort = sorted(self.place_list,
key=operator.itemgetter(0)
)
_LOG.debug("%s" % time.strftime(" end sort : "
"%a %d %b %Y %H:%M:%S", time.gmtime()))
self._create_markers()
def bubble_message(self, event, lat, lon, marks):
menu = gtk.Menu()
menu.set_title("places")
message = ""
prevmark = None
for mark in marks:
if message != "":
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit place"))
modify.show()
modify.connect("activate", self.edit_place,
event, lat, lon, prevmark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here,
event, lat, lon, prevmark)
itemoption.append(center)
message = "%s" % mark[0]
prevmark = mark
add_item = gtk.MenuItem(message)
add_item.show()
menu.append(add_item)
itemoption = gtk.Menu()
itemoption.set_title(message)
itemoption.show()
add_item.set_submenu(itemoption)
modify = gtk.MenuItem(_("Edit place"))
modify.show()
modify.connect("activate", self.edit_place, event, lat, lon, prevmark)
itemoption.append(modify)
center = gtk.MenuItem(_("Center on this place"))
center.show()
center.connect("activate", self.center_here, event, lat, lon, prevmark)
itemoption.append(center)
menu.popup(None, None, None, 0, event.time)
return 1
def add_specific_menu(self, menu, event, lat, lon):
"""
Add specific entry to the navigation menu.
"""
add_item = gtk.MenuItem()
add_item.show()
menu.append(add_item)
add_item = gtk.MenuItem(_("Show all places"))
add_item.connect("activate", self.show_all_places, event, lat , lon)
add_item.show()
menu.append(add_item)

File diff suppressed because it is too large Load Diff

View File

@ -45,32 +45,6 @@ except:
#no interfaces present, we do not register these plugins
if not (TOOLKIT == NOWEB):
register(VIEW,
id = 'geoview',
name = _("Geographic View"),
description = _("The view showing events on an interactive internet map "
"(internet connection needed)"),
version = '1.0',
gramps_target_version = '3.3',
status = STABLE,
fname = 'geoview.py',
authors = [u"The Gramps project"],
authors_email = ["http://gramps-project.org"],
category = ("Geography", _("Geography")),
viewclass = 'GeoView',
icons = [
('geo-place-add', _('Add Place')),
('geo-place-link', _('Link Place')),
('geo-fixed-zoom', _('Fixed Zoom')),
('geo-free-zoom', _('Free Zoom')),
('geo-show-place', _('Show Places')),
('geo-show-person', _('Show Person')),
('geo-show-family', _('Show Family')),
('geo-show-event', _('Show Events')),
],
icondir = IMAGE_DIR,
)
register(VIEW,
id = 'htmlview',
name = _("Html View"),