Including geps-025 in trunk for new geography based on osmgpsmap.
svn: r17253
This commit is contained in:
parent
f843bc4da9
commit
74c112f684
7
README
7
README
@ -26,7 +26,12 @@ The following packages are *STRONGLY RECOMMENDED* to be installed:
|
|||||||
GraphViz Enable creation of graphs using GraphViz engine
|
GraphViz Enable creation of graphs using GraphViz engine
|
||||||
http://www.graphviz.org
|
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
|
PyWebKitGtk or python-gtkmozembed: PACKAGERS, Test if on your distribution
|
||||||
webkit and Gramps is stable. If you get crashes, patch
|
webkit and Gramps is stable. If you get crashes, patch
|
||||||
src/plugins/view/htmlrenderer.py and
|
src/plugins/view/htmlrenderer.py and
|
||||||
|
@ -139,6 +139,7 @@ src/plugins/gramplet/Makefile
|
|||||||
src/plugins/graph/Makefile
|
src/plugins/graph/Makefile
|
||||||
src/plugins/import/Makefile
|
src/plugins/import/Makefile
|
||||||
src/plugins/lib/Makefile
|
src/plugins/lib/Makefile
|
||||||
|
src/plugins/lib/maps/Makefile
|
||||||
src/plugins/mapservices/Makefile
|
src/plugins/mapservices/Makefile
|
||||||
src/plugins/quickview/Makefile
|
src/plugins/quickview/Makefile
|
||||||
src/plugins/rel/Makefile
|
src/plugins/rel/Makefile
|
||||||
|
@ -158,12 +158,14 @@ register('export.proxy-order', [
|
|||||||
["reference", 0],
|
["reference", 0],
|
||||||
])
|
])
|
||||||
|
|
||||||
register('geoview.latitude', "0.0")
|
register('geography.center-lon', 0.0)
|
||||||
register('geoview.lock', False)
|
register('geography.lock', False)
|
||||||
register('geoview.longitude', "0.0")
|
register('geography.center-lat', 0.0)
|
||||||
register('geoview.map', "person")
|
register('geography.map', "person")
|
||||||
register('geoview.stylesheet', "")
|
register('geography.map_service', 1)
|
||||||
register('geoview.zoom', 0)
|
register('geography.zoom', 0)
|
||||||
|
register('geography.show_cross', False)
|
||||||
|
register('geography.path', "")
|
||||||
|
|
||||||
register('htmlview.start-url', "http://gramps-project.org")
|
register('htmlview.start-url', "http://gramps-project.org")
|
||||||
register('htmlview.url-handler', False)
|
register('htmlview.url-handler', False)
|
||||||
|
@ -12,6 +12,8 @@ EXTRA_DIST=$(xml_in_files) $(xml_files)
|
|||||||
|
|
||||||
pkgdatadir = $(datadir)/@PACKAGE@/plugins/lib
|
pkgdatadir = $(datadir)/@PACKAGE@/plugins/lib
|
||||||
|
|
||||||
|
SUBDIRS = maps
|
||||||
|
|
||||||
pkgdata_PYTHON = \
|
pkgdata_PYTHON = \
|
||||||
libcairodoc.py\
|
libcairodoc.py\
|
||||||
libformatting.py\
|
libformatting.py\
|
||||||
|
19
src/plugins/lib/maps/Makefile.am
Normal file
19
src/plugins/lib/maps/Makefile.am
Normal 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));
|
27
src/plugins/lib/maps/__init__.py
Normal file
27
src/plugins/lib/maps/__init__.py
Normal 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__ = []
|
108
src/plugins/lib/maps/constants.py
Normal file
108
src/plugins/lib/maps/constants.py
Normal 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,
|
||||||
|
}
|
||||||
|
|
733
src/plugins/lib/maps/geography.py
Normal file
733
src/plugins/lib/maps/geography.py
Normal 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
|
193
src/plugins/lib/maps/grampsmaps.py
Normal file
193
src/plugins/lib/maps/grampsmaps.py
Normal 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(obj)
|
||||||
|
|
||||||
|
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
|
@ -10,8 +10,12 @@ pkgdata_PYTHON = \
|
|||||||
familyview.py \
|
familyview.py \
|
||||||
fanchartview.gpr.py \
|
fanchartview.gpr.py \
|
||||||
fanchartview.py \
|
fanchartview.py \
|
||||||
geoview.py \
|
geoevents.py \
|
||||||
geoview.gpr.py \
|
geoplaces.py \
|
||||||
|
geoperson.py \
|
||||||
|
geofamily.py \
|
||||||
|
geography.gpr.py \
|
||||||
|
htmlrenderer.gpr.py \
|
||||||
grampletview.py \
|
grampletview.py \
|
||||||
htmlrenderer.py \
|
htmlrenderer.py \
|
||||||
mediaview.py \
|
mediaview.py \
|
||||||
|
382
src/plugins/view/geoevents.py
Normal file
382
src/plugins/view/geoevents.py
Normal 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)
|
||||||
|
|
430
src/plugins/view/geofamily.py
Normal file
430
src/plugins/view/geofamily.py
Normal 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
|
||||||
|
|
103
src/plugins/view/geography.gpr.py
Normal file
103
src/plugins/view/geography.gpr.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# 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
|
||||||
|
pass
|
||||||
|
|
||||||
|
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.4',
|
||||||
|
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.4',
|
||||||
|
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.4',
|
||||||
|
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.4',
|
||||||
|
status = STABLE,
|
||||||
|
order = START,
|
||||||
|
fname = 'geofamily.py',
|
||||||
|
authors = [u"Serge Noiraud"],
|
||||||
|
authors_email = [""],
|
||||||
|
category = ("Geography", _("Geography")),
|
||||||
|
viewclass = 'GeoFamily',
|
||||||
|
stock_icon = 'geo-show-family',
|
||||||
|
)
|
||||||
|
|
431
src/plugins/view/geoperson.py
Normal file
431
src/plugins/view/geoperson.py
Normal 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
|
||||||
|
|
327
src/plugins/view/geoplaces.py
Normal file
327
src/plugins/view/geoplaces.py
Normal 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
@ -19,7 +19,7 @@
|
|||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
# $Id$
|
# $Id: htmlrenderer.gpr.py 17129 2011-04-15 18:43:37Z noirauds $
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -45,32 +45,6 @@ except:
|
|||||||
|
|
||||||
#no interfaces present, we do not register these plugins
|
#no interfaces present, we do not register these plugins
|
||||||
if not (TOOLKIT == NOWEB):
|
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.4',
|
|
||||||
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,
|
register(VIEW,
|
||||||
id = 'htmlview',
|
id = 'htmlview',
|
||||||
name = _("Html View"),
|
name = _("Html View"),
|
Loading…
x
Reference in New Issue
Block a user