Geography : reorganization, add a life way layer, some cleaning.
svn: r19209
This commit is contained in:
parent
47ffcf9bec
commit
8d4906354d
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Serge Noiraud
|
||||
# Copyright (C) 2010-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2010 Serge Noiraud
|
||||
# Copyright (C) 2010-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -27,7 +27,6 @@
|
||||
# standard python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.ggettext import gettext as _
|
||||
import gen.lib
|
||||
import os
|
||||
import const
|
||||
|
91
src/plugins/lib/maps/dummylayer.py
Normal file
91
src/plugins/lib/maps/dummylayer.py
Normal file
@ -0,0 +1,91 @@
|
||||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
import gobject
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.dummylayer")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# osmGpsMap
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
try:
|
||||
import osmgpsmap
|
||||
except:
|
||||
raise
|
||||
|
||||
class DummyLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the dummy layer
|
||||
"""
|
||||
gobject.GObject.__init__(self)
|
||||
|
||||
def do_draw(self, gpsmap, gdkdrawable):
|
||||
"""
|
||||
Draw the layer
|
||||
"""
|
||||
pass
|
||||
|
||||
def do_render(self, gpsmap):
|
||||
"""
|
||||
Render the layer
|
||||
"""
|
||||
pass
|
||||
|
||||
def do_busy(self):
|
||||
"""
|
||||
The layer is busy
|
||||
"""
|
||||
return False
|
||||
|
||||
def do_button_press(self, gpsmap, gdkeventbutton):
|
||||
"""
|
||||
Someone press a button
|
||||
"""
|
||||
return False
|
||||
|
||||
gobject.type_register(DummyLayer)
|
||||
|
64
src/plugins/lib/maps/dummynogps.py
Normal file
64
src/plugins/lib/maps/dummynogps.py
Normal file
@ -0,0 +1,64 @@
|
||||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
import gobject
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.dummynogps")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# osmGpsMap
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
try:
|
||||
import osmgpsmap
|
||||
except:
|
||||
raise
|
||||
|
||||
class DummyMapNoGpsPoint(osmgpsmap.GpsMap):
|
||||
def do_draw_gps_point(self, drawable):
|
||||
pass
|
||||
|
||||
gobject.type_register(DummyMapNoGpsPoint)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011 Serge Noiraud
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -28,21 +28,10 @@
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.ggettext import sgettext as _
|
||||
from gen.ggettext import ngettext
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import gobject
|
||||
import time
|
||||
import math
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger(".geography")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -65,13 +54,25 @@ import Errors
|
||||
import Bookmarks
|
||||
import const
|
||||
import constfunc
|
||||
from grampsmaps import *
|
||||
import constants
|
||||
import ManagedWindow
|
||||
from config import config
|
||||
from gui.editors import EditPlace, EditEvent, EditFamily, EditPerson
|
||||
from gui.selectors.selectplace import SelectPlace
|
||||
|
||||
import osmgpsmap
|
||||
from . import constants
|
||||
from osmGps import OsmGps
|
||||
from selectionlayer import SelectionLayer
|
||||
from placeselection import PlaceSelection
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.geography")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Functions and variables
|
||||
@ -89,216 +90,19 @@ def _get_sign(value):
|
||||
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
|
||||
|
||||
def match(self, lat, lon, radius):
|
||||
"""
|
||||
coordinates matching.
|
||||
"""
|
||||
r = float(radius)
|
||||
self.places = []
|
||||
|
||||
# place
|
||||
for entry in self.place_list:
|
||||
if (math.hypot(lat-float(entry[3]), lon-float(entry[4])) <= r) == True:
|
||||
dist = math.sqrt((lat - float(entry[3])) ** 2 + (lon - float(entry[4])) ** 2)
|
||||
# Do we already have this place ? avoid duplicates
|
||||
self.get_location(entry[9])
|
||||
if not [self.country, self.state, self.county] in self.places:
|
||||
self.places.append([self.country, self.state, self.county])
|
||||
return self.places
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# PlaceSelection
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class PlaceSelection(ManagedWindow.ManagedWindow, osmGpsMap):
|
||||
def __init__(self, uistate, dbstate, map, layer, places, lat, lon, function, oldvalue=None):
|
||||
"""
|
||||
We show a selection box for possible places in a region of the map.
|
||||
We can select the diameter of the region which is a circle.
|
||||
Depending of this region, we can show the possible choice.
|
||||
We select the value depending of our need which open the EditPlace box.
|
||||
"""
|
||||
try:
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, [], PlaceSelection)
|
||||
except Errors.WindowActiveError:
|
||||
return
|
||||
self.uistate = uistate
|
||||
self.dbstate = dbstate
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
self.osm = map
|
||||
self.radius = 1.0
|
||||
self.circle = None
|
||||
self.oldvalue = oldvalue
|
||||
self.place_list = places
|
||||
self.function = function
|
||||
self.selection_layer = layer
|
||||
self.layer = layer
|
||||
alignment = gtk.Alignment(0,1,0,0)
|
||||
self.set_window(
|
||||
gtk.Dialog(_('Place Selection in a region'),
|
||||
flags=gtk.DIALOG_NO_SEPARATOR,
|
||||
buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
|
||||
None, _('Place Selection in a region'), None)
|
||||
label = gtk.Label(_('Choose the radius of the selection.\n'
|
||||
'On the map you should see a circle or an oval depending on the latitude.'))
|
||||
alignment.add(label)
|
||||
self.window.vbox.pack_start(alignment, expand=False)
|
||||
adj = gtk.Adjustment(1.0, 0.1, 3.0, 0.1, 0, 0) # default value is 1.0, minimum is 0.1 and max is 3.0
|
||||
slider = gtk.HScale(adj)
|
||||
slider.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
|
||||
slider.set_digits(1)
|
||||
slider.set_value_pos(gtk.POS_BOTTOM)
|
||||
slider.connect('value-changed', self.slider_change, self.lat, self.lon)
|
||||
self.window.vbox.pack_start(slider, expand=False)
|
||||
self.vadjust = gtk.Adjustment(page_size=15)
|
||||
self.scroll = gtk.ScrolledWindow(self.vadjust)
|
||||
self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
self.scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
self.plist = gtk.ListStore(str, str, str)
|
||||
self.choices = gtk.TreeView(self.plist)
|
||||
self.scroll.add(self.choices)
|
||||
self.renderer = gtk.CellRendererText()
|
||||
self.tvcol1 = gtk.TreeViewColumn(_('Country'),self.renderer, markup=0)
|
||||
self.tvcol2 = gtk.TreeViewColumn(_('State'),self.renderer, markup=1)
|
||||
self.tvcol3 = gtk.TreeViewColumn(_('County'),self.renderer, markup=2)
|
||||
self.tvcol1.set_sort_column_id(0)
|
||||
self.tvcol2.set_sort_column_id(1)
|
||||
self.tvcol3.set_sort_column_id(2)
|
||||
self.choices.append_column(self.tvcol1)
|
||||
self.choices.append_column(self.tvcol2)
|
||||
self.choices.append_column(self.tvcol3)
|
||||
self.window.vbox.pack_start(self.scroll, expand=True)
|
||||
self.label2 = gtk.Label()
|
||||
self.label2.set_markup('<span background="green" foreground="black">%s</span>' %
|
||||
_('The green values in the row correspond to the current place values.'))
|
||||
alignment = gtk.Alignment(0,1,0,0)
|
||||
alignment.add(self.label2)
|
||||
self.window.vbox.pack_start(alignment, expand=False)
|
||||
self.window.set_default_size(400, 300)
|
||||
self.choices.connect('row-activated', self.selection, function)
|
||||
self.window.connect('response', self.close)
|
||||
self.window.show_all()
|
||||
self.show()
|
||||
self.label2.hide()
|
||||
self.slider_change(None,lat,lon)
|
||||
|
||||
def close(self, *obj):
|
||||
self.hide_the_region()
|
||||
ManagedWindow.ManagedWindow.close(self, *obj)
|
||||
|
||||
def slider_change(self, obj, lat, lon):
|
||||
"""
|
||||
Display on the map a circle in which we select all the places inside this region.
|
||||
"""
|
||||
self.radius = obj.get_value() if obj else 1.0
|
||||
self.show_the_region(self.radius)
|
||||
match(self, lat, lon, self.radius)
|
||||
self.plist.clear()
|
||||
if self.oldvalue != None:
|
||||
# The old values are always in the first row.
|
||||
# In this case, we change the color of the row.
|
||||
# display the associated message
|
||||
self.label2.show()
|
||||
a,b,c = self.oldvalue
|
||||
self.plist.append((PLACE_STRING % a,
|
||||
PLACE_STRING % b,
|
||||
PLACE_STRING % c)
|
||||
)
|
||||
for place in self.places:
|
||||
self.plist.append(place)
|
||||
# here, we could add value from geography names services ...
|
||||
|
||||
# if we found no place, we must create a default place.
|
||||
self.plist.append((_("New place with empty fields"),"","..."))
|
||||
|
||||
def hide_the_region(self):
|
||||
"""
|
||||
Hide the layer which contains the circle
|
||||
"""
|
||||
layer = self.get_selection_layer()
|
||||
if layer:
|
||||
self.remove_layer(layer)
|
||||
|
||||
def show_the_region(self, r):
|
||||
"""
|
||||
Show a circle in which we select the places.
|
||||
"""
|
||||
# circle (r)
|
||||
self.hide_the_region()
|
||||
self.selection_layer = self.add_selection_layer()
|
||||
self.selection_layer.add_circle(r, self.lat, self.lon)
|
||||
|
||||
def get_location(self, place):
|
||||
"""
|
||||
get location values
|
||||
"""
|
||||
place = self.dbstate.db.get_place_from_gramps_id(place)
|
||||
loc = place.get_main_location()
|
||||
data = loc.get_text_data_list()
|
||||
# new background or font color on gtk fields ?
|
||||
self.country = data[6]
|
||||
self.state = data[5]
|
||||
self.county = data[4]
|
||||
return(self.country, self.state, self.county)
|
||||
|
||||
def selection(self, obj, index, column, function):
|
||||
"""
|
||||
get location values and call the real function : add_place, edit_place
|
||||
"""
|
||||
if self.plist[index][2] == "...":
|
||||
# case with blank values ( New place with empty fields )
|
||||
self.function( "", "", "", self.lat, self.lon)
|
||||
elif self.plist[index][0][1:5] == "span":
|
||||
# case with old values ( keep the old values of the place )
|
||||
name = PLACE_REGEXP.search(self.plist[index][0],0)
|
||||
country = name.group(1)
|
||||
name = PLACE_REGEXP.search(self.plist[index][1],0)
|
||||
state = name.group(1)
|
||||
name = PLACE_REGEXP.search(self.plist[index][2],0)
|
||||
county = name.group(1)
|
||||
self.function( country, county, state, self.lat, self.lon)
|
||||
else:
|
||||
# Set the new values of the country, county and state fields.
|
||||
self.function( self.plist[index][0], self.plist[index][2],
|
||||
self.plist[index][1], self.lat, self.lon)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GeoGraphyView
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
class GeoGraphyView(OsmGps, NavigationView):
|
||||
"""
|
||||
View for pedigree tree.
|
||||
Displays the ancestors of a selected individual.
|
||||
"""
|
||||
#settings in the config file
|
||||
CONFIGSETTINGS = (
|
||||
('geography.path', GEOGRAPHY_PATH),
|
||||
('geography.path', constants.GEOGRAPHY_PATH),
|
||||
|
||||
('geography.zoom', 10),
|
||||
('geography.zoom_when_center', 12),
|
||||
@ -307,11 +111,6 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
('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),
|
||||
)
|
||||
|
||||
@ -329,7 +128,7 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
self.lock = config.get("geography.lock")
|
||||
if config.get('geography.path') == "" :
|
||||
config.set('geography.path', GEOGRAPHY_PATH )
|
||||
osmGpsMap.__init__(self)
|
||||
OsmGps.__init__(self)
|
||||
|
||||
self.format_helper = FormattingHelper(self.dbstate)
|
||||
self.centerlat = self.centerlon = 0.0
|
||||
@ -353,16 +152,18 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
else:
|
||||
default_image = self.geo_altmap
|
||||
self.geo_othermap = {}
|
||||
for id in ( gen.lib.EventType.BIRTH,
|
||||
for ident 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(
|
||||
self.geo_othermap[ident] = gtk.gdk.pixbuf_new_from_file_at_size(
|
||||
os.path.join(const.ROOT_DIR, "images", "22x22",
|
||||
(constants.ICONS.get(int(id), default_image) + '.png' )),
|
||||
(constants.ICONS.get(int(ident), default_image) + '.png' )),
|
||||
22, 22)
|
||||
|
||||
def change_page(self):
|
||||
"""Called when the page changes."""
|
||||
"""
|
||||
Called when the page changes.
|
||||
"""
|
||||
NavigationView.change_page(self)
|
||||
self.uistate.clear_filter_results()
|
||||
self.end_selection = None
|
||||
@ -374,7 +175,7 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
NavigationView.on_delete(self)
|
||||
self._config.save()
|
||||
|
||||
def change_db(self, db):
|
||||
def change_db(self, dbse):
|
||||
"""
|
||||
Callback associated with DbState. Whenever the database
|
||||
changes, this task is called. In this case, we rebuild the
|
||||
@ -422,7 +223,9 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
def build_nav_menu(self, obj, event, lat, lon):
|
||||
"""Builds the menu for actions on the map."""
|
||||
"""
|
||||
Builds the menu for actions on the map.
|
||||
"""
|
||||
menu = gtk.Menu()
|
||||
menu.set_title(_('Map Menu'))
|
||||
|
||||
@ -499,7 +302,8 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
"""
|
||||
Center the map at the new position then save it.
|
||||
"""
|
||||
self.osm.set_center_and_zoom(lat, lon, config.get("geography.zoom_when_center"))
|
||||
self.osm.set_center_and_zoom(lat, lon,
|
||||
config.get("geography.zoom_when_center"))
|
||||
self.save_center(lat, lon)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@ -563,11 +367,17 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
raise NotImplementedError
|
||||
|
||||
def add_selection_layer(self):
|
||||
"""
|
||||
add the selection layer
|
||||
"""
|
||||
selection_layer = SelectionLayer()
|
||||
self.osm.layer_add(selection_layer)
|
||||
return selection_layer
|
||||
|
||||
def remove_layer(self, layer):
|
||||
"""
|
||||
Remove the specified layer
|
||||
"""
|
||||
self.osm.remove_layer(layer)
|
||||
|
||||
def add_marker(self, menu, event, lat, lon, event_type, differtype):
|
||||
@ -716,7 +526,8 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
s_bbox_lon1 = bbox[1] + 10.0
|
||||
s_bbox_lat2 = bbox[2] + 10.0
|
||||
s_bbox_lon2 = bbox[3] + 10.0
|
||||
result = ( s_bbox_lat1 > s_lat > s_bbox_lat2 ) and ( s_bbox_lon1 < s_lon < s_bbox_lon2 )
|
||||
result = ( s_bbox_lat1 > s_lat > s_bbox_lat2 ) and \
|
||||
( s_bbox_lon1 < s_lon < s_bbox_lon2 )
|
||||
return result
|
||||
|
||||
def _autozoom_in(self, lvl, p1lat, p1lon, p2lat, p2lon):
|
||||
@ -728,9 +539,11 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
and lvl < 18 ):
|
||||
lvl += 1
|
||||
self.osm.set_zoom(lvl)
|
||||
gobject.timeout_add(50, self._autozoom_in, lvl, p1lat, p1lon, p2lat, p2lon)
|
||||
gobject.timeout_add(50, self._autozoom_in, lvl,
|
||||
p1lat, p1lon, p2lat, p2lon)
|
||||
else:
|
||||
gobject.timeout_add(50, self._autozoom_out, lvl, p1lat, p1lon, p2lat, p2lon)
|
||||
gobject.timeout_add(50, self._autozoom_out, lvl,
|
||||
p1lat, p1lon, p2lat, p2lon)
|
||||
|
||||
def _autozoom_out(self, lvl, p1lat, p1lon, p2lat, p2lon):
|
||||
"""
|
||||
@ -741,7 +554,8 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
and lvl > 1 ):
|
||||
lvl -= 1
|
||||
self.osm.set_zoom(lvl)
|
||||
gobject.timeout_add(50, self._autozoom_out, lvl, p1lat, p1lon, p2lat, p2lon)
|
||||
gobject.timeout_add(50, self._autozoom_out, lvl,
|
||||
p1lat, p1lon, p2lat, p2lon)
|
||||
else:
|
||||
layer = self.get_selection_layer()
|
||||
if layer:
|
||||
@ -767,7 +581,8 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
p2lat = self.end_selection.rlat
|
||||
p2lon = self.end_selection.rlon
|
||||
# We zoom in until at least one marker missing.
|
||||
gobject.timeout_add(50, self._autozoom_in, level_start, p1lat, p1lon, p2lat, p2lon)
|
||||
gobject.timeout_add(50, self._autozoom_in, level_start,
|
||||
p1lat, p1lon, p2lat, p2lon)
|
||||
|
||||
def _set_center_and_zoom(self):
|
||||
"""
|
||||
@ -829,7 +644,7 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
self._autozoom()
|
||||
self.end_selection = None
|
||||
self.save_center(self.latit, self.longt)
|
||||
config.set("geography.zoom",self.osm.props.zoom)
|
||||
config.set("geography.zoom", self.osm.props.zoom)
|
||||
|
||||
def _get_father_and_mother_name(self, event):
|
||||
"""
|
||||
@ -958,16 +773,23 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
place = selector.run()
|
||||
if place:
|
||||
loc = place.get_main_location()
|
||||
oldv = (loc.get_country(), loc.get_state(), loc.get_county()) if loc else None
|
||||
oldv = (loc.get_country(), loc.get_state(),
|
||||
loc.get_county()) if loc else None
|
||||
places_handle = self.dbstate.db.iter_place_handles()
|
||||
for place_hdl in places_handle:
|
||||
plce = self.dbstate.db.get_place_from_handle(place_hdl)
|
||||
if plce.get_title() == place.get_title():
|
||||
self.mark = [None,None,None,None,None,None,None,
|
||||
None,None,plce.gramps_id,None,None]
|
||||
self.select_fct = PlaceSelection(self.uistate, self.dbstate, self.osm,
|
||||
self.selection_layer, self.place_list,
|
||||
lat, lon, self.__edit_place, oldv)
|
||||
self.mark = [None, None, None, None, None, None, None,
|
||||
None, None, plce.gramps_id, None, None]
|
||||
self.select_fct = PlaceSelection(self.uistate,
|
||||
self.dbstate,
|
||||
self.osm,
|
||||
self.selection_layer,
|
||||
self.place_list,
|
||||
lat,
|
||||
lon,
|
||||
self.__edit_place,
|
||||
oldv)
|
||||
|
||||
def __add_place(self, pcountry, pcounty, pstate, plat, plon):
|
||||
"""
|
||||
@ -1081,8 +903,9 @@ class GeoGraphyView(osmGpsMap, NavigationView):
|
||||
Function that builds the widget in the configuration dialog
|
||||
for the map options.
|
||||
"""
|
||||
self._config.set('geography.path',config.get('geography.path'))
|
||||
self._config.set('geography.zoom_when_center',config.get('geography.zoom_when_center'))
|
||||
self._config.set('geography.path', config.get('geography.path'))
|
||||
self._config.set('geography.zoom_when_center',
|
||||
config.get('geography.zoom_when_center'))
|
||||
table = gtk.Table(1, 1)
|
||||
table.set_border_width(12)
|
||||
table.set_col_spacings(6)
|
||||
|
158
src/plugins/lib/maps/lifewaylayer.py
Normal file
158
src/plugins/lib/maps/lifewaylayer.py
Normal file
@ -0,0 +1,158 @@
|
||||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
import gobject
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.lifeway")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import cairo
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# osmGpsMap
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
try:
|
||||
import osmgpsmap
|
||||
except:
|
||||
raise
|
||||
|
||||
class LifeWayLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
|
||||
"""
|
||||
This is the layer used to display tracks or the life way for one or several
|
||||
individuals.
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the layer
|
||||
"""
|
||||
gobject.GObject.__init__(self)
|
||||
self.lifeways = []
|
||||
self.lifeways_comment = []
|
||||
self.comments = []
|
||||
|
||||
def clear_ways(self):
|
||||
"""
|
||||
reset the layer attributes.
|
||||
"""
|
||||
self.lifeways = []
|
||||
self.lifeways_comment = []
|
||||
self.comments = []
|
||||
|
||||
def add_way(self, points, color):
|
||||
"""
|
||||
Add a track or life way.
|
||||
"""
|
||||
self.lifeways.append((points, color))
|
||||
|
||||
def add_text(self, points, text):
|
||||
"""
|
||||
Add a text to the track or life way.
|
||||
"""
|
||||
self.lifeways_comment.append((points, text))
|
||||
|
||||
def do_draw(self, gpsmap, drawable):
|
||||
"""
|
||||
Draw all tracks or life ways.
|
||||
"""
|
||||
for lifeway in self.lifeways:
|
||||
ctx = drawable.cairo_create()
|
||||
ctx.set_line_width(3.0)
|
||||
map_points = []
|
||||
for point in lifeway[0]:
|
||||
conv_pt = osmgpsmap.point_new_degrees(point[0], point[1])
|
||||
coord_x, coord_y = gpsmap.convert_geographic_to_screen(conv_pt)
|
||||
map_points.append((coord_x, coord_y))
|
||||
color = gtk.gdk.color_parse(lifeway[1])
|
||||
ctx.set_source_rgb(color.red / 65535,
|
||||
color.green / 65535,
|
||||
color.blue / 65535)
|
||||
first = True
|
||||
for idx_pt in range(0, len(map_points)):
|
||||
if first:
|
||||
first = False
|
||||
ctx.move_to(map_points[idx_pt][0], map_points[idx_pt][1])
|
||||
else:
|
||||
ctx.line_to(map_points[idx_pt][0], map_points[idx_pt][1])
|
||||
ctx.stroke()
|
||||
|
||||
for comment in self.lifeways_comment:
|
||||
ctx = drawable.cairo_create()
|
||||
ctx.set_line_width(3.0)
|
||||
ctx.select_font_face("Purisa",
|
||||
cairo.FONT_SLANT_NORMAL,
|
||||
cairo.FONT_WEIGHT_NORMAL)
|
||||
ctx.set_font_size(13)
|
||||
points = comment[0]
|
||||
conv_pt = osmgpsmap.point_new_degrees(points[0][0], points[0][1])
|
||||
coord_x, coord_y = gpsmap.convert_geographic_to_screen(conv_pt)
|
||||
ctx.move_to(coord_x, coord_y)
|
||||
ctx.show_text(comment[1])
|
||||
|
||||
def do_render(self, gpsmap):
|
||||
"""
|
||||
render the layer
|
||||
"""
|
||||
pass
|
||||
|
||||
def do_busy(self):
|
||||
"""
|
||||
set the layer busy
|
||||
"""
|
||||
return False
|
||||
|
||||
def do_button_press(self, gpsmap, gdkeventbutton):
|
||||
"""
|
||||
When we press a button.
|
||||
"""
|
||||
return False
|
||||
|
||||
gobject.type_register(LifeWayLayer)
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011 Serge Noiraud
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -20,14 +20,13 @@
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id$
|
||||
# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import sys
|
||||
import os
|
||||
import gobject
|
||||
|
||||
@ -37,7 +36,7 @@ import gobject
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.osmgpsmap")
|
||||
_LOG = logging.getLogger("maps.osmgps")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@ -53,21 +52,17 @@ import gtk
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
import constants
|
||||
from dummylayer import DummyLayer
|
||||
from dummynogps import DummyMapNoGpsPoint
|
||||
from selectionlayer import SelectionLayer
|
||||
from lifewaylayer import LifeWayLayer
|
||||
from gen.ggettext import sgettext as _
|
||||
from gen.ggettext import ngettext
|
||||
from config import config
|
||||
from QuestionDialog import ErrorDialog
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
GEOGRAPHY_PATH = os.path.join(const.HOME_DIR, "maps")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# osmGpsMap
|
||||
# OsmGps
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -76,89 +71,28 @@ try:
|
||||
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 SelectionLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
|
||||
def __init__(self):
|
||||
gobject.GObject.__init__(self)
|
||||
self.circles = []
|
||||
self.rectangles = []
|
||||
|
||||
def add_circle(self, r, lat, lon):
|
||||
self.circles.append((r, lat, lon))
|
||||
|
||||
def add_rectangle(self, p1, p2):
|
||||
self.rectangles.append((p1, p2))
|
||||
|
||||
def do_draw(self, gpsmap, drawable):
|
||||
gc = drawable.new_gc()
|
||||
for circle in self.circles:
|
||||
top_left = osmgpsmap.point_new_degrees(circle[1] + circle[0],
|
||||
circle[2] - circle[0])
|
||||
bottom_right = osmgpsmap.point_new_degrees(circle[1] - circle[0],
|
||||
circle[2] + circle[0])
|
||||
x, y = gpsmap.convert_geographic_to_screen(top_left)
|
||||
x2, y2 = gpsmap.convert_geographic_to_screen(bottom_right)
|
||||
drawable.draw_arc(gc, False, x, y, x2 - x, y2 - y, 0, 360*64)
|
||||
for rectangle in self.rectangles:
|
||||
top_left, bottom_right = rectangle
|
||||
x, y = gpsmap.convert_geographic_to_screen(top_left)
|
||||
x2, y2 = gpsmap.convert_geographic_to_screen(bottom_right)
|
||||
# be sure when can select a region in all case.
|
||||
if ( x < x2 ):
|
||||
if ( y < y2 ):
|
||||
drawable.draw_rectangle(gc, False, x, y, x2 - x, y2 - y)
|
||||
else:
|
||||
drawable.draw_rectangle(gc, False, x, y2, x2 - x, y - y2)
|
||||
else:
|
||||
if ( y < y2 ):
|
||||
drawable.draw_rectangle(gc, False, x2, y, x - x2, y2 - y)
|
||||
else:
|
||||
drawable.draw_rectangle(gc, False, x2, y2, x - x2, y - y2)
|
||||
|
||||
def do_render(self, gpsmap):
|
||||
pass
|
||||
|
||||
def do_busy(self):
|
||||
return False
|
||||
|
||||
def do_button_press(self, gpsmap, gdkeventbutton):
|
||||
return False
|
||||
gobject.type_register(SelectionLayer)
|
||||
|
||||
class osmGpsMap():
|
||||
class OsmGps():
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the map
|
||||
"""
|
||||
self.vbox = None
|
||||
self.cross_map = None
|
||||
self.osm = None
|
||||
self.show_tooltips = True
|
||||
self.zone_selection = False
|
||||
self.selection_layer = None
|
||||
self.lifeway_layer = None
|
||||
self.context_id = 0
|
||||
self.begin_selection = None
|
||||
self.end_selection = None
|
||||
self.current_map = None
|
||||
self.places_found = None
|
||||
|
||||
def build_widget(self):
|
||||
"""
|
||||
create the vbox
|
||||
"""
|
||||
self.vbox = gtk.VBox(False, 0)
|
||||
cache_path = config.get('geography.path')
|
||||
if not os.path.isdir(cache_path):
|
||||
@ -169,16 +103,20 @@ class osmGpsMap():
|
||||
cache_path )
|
||||
return self.vbox
|
||||
|
||||
self.change_map(None,config.get("geography.map_service"))
|
||||
self.change_map(None, config.get("geography.map_service"))
|
||||
return self.vbox
|
||||
|
||||
def change_map(self, obj, map_type):
|
||||
"""
|
||||
Change the current map
|
||||
"""
|
||||
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(config.get('geography.path'), constants.tiles_path[map_type])
|
||||
tiles_path = os.path.join(config.get('geography.path'),
|
||||
constants.tiles_path[map_type])
|
||||
if not os.path.isdir(tiles_path):
|
||||
try:
|
||||
os.makedirs(tiles_path, 0755) # create dir like mkdir -p
|
||||
@ -197,6 +135,7 @@ class osmGpsMap():
|
||||
self.osm.layer_add(current_map)
|
||||
self.osm.layer_add(DummyLayer())
|
||||
self.selection_layer = self.add_selection_layer()
|
||||
self.lifeway_layer = self.add_lifeway_layer()
|
||||
self.cross_map = osmgpsmap.GpsMapOsd( show_crosshair=False)
|
||||
self.set_crosshair(config.get("geography.show_cross"))
|
||||
self.osm.set_center_and_zoom(config.get("geography.center-lat"),
|
||||
@ -209,48 +148,74 @@ class osmGpsMap():
|
||||
self.osm.connect('changed', self.zoom_changed)
|
||||
self.osm.show()
|
||||
self.vbox.pack_start(self.osm)
|
||||
if obj is not None:
|
||||
self._createmap(None)
|
||||
|
||||
def add_selection_layer(self):
|
||||
"""
|
||||
add the selection layer
|
||||
"""
|
||||
selection_layer = SelectionLayer()
|
||||
self.osm.layer_add(selection_layer)
|
||||
return selection_layer
|
||||
|
||||
def get_selection_layer(self):
|
||||
"""
|
||||
get the selection layer
|
||||
"""
|
||||
return self.selection_layer
|
||||
|
||||
def add_lifeway_layer(self):
|
||||
"""
|
||||
add the track or life ways layer
|
||||
"""
|
||||
lifeway_layer = LifeWayLayer()
|
||||
self.osm.layer_add(lifeway_layer)
|
||||
return lifeway_layer
|
||||
|
||||
def get_lifeway_layer(self):
|
||||
"""
|
||||
get the track or life ways layer
|
||||
"""
|
||||
return self.lifeway_layer
|
||||
|
||||
def remove_layer(self, layer):
|
||||
"""
|
||||
remove the specified layer
|
||||
"""
|
||||
self.osm.layer_remove(layer)
|
||||
|
||||
def zoom_changed(self, zoom):
|
||||
config.set("geography.zoom",self.osm.props.zoom)
|
||||
"""
|
||||
save the zoom and the position
|
||||
"""
|
||||
config.set("geography.zoom", self.osm.props.zoom)
|
||||
self.save_center(self.osm.props.latitude, self.osm.props.longitude)
|
||||
|
||||
def motion_event(self, osmmap, event):
|
||||
"""
|
||||
Show the place name if found on the status bar
|
||||
Moving during selection
|
||||
"""
|
||||
current = osmgpsmap.point_new_degrees(0.0,0.0)
|
||||
current = osmgpsmap.point_new_degrees(0.0, 0.0)
|
||||
osmmap.convert_screen_to_geographic(int(event.x), int(event.y), current)
|
||||
lat, lon = current.get_degrees()
|
||||
if self.zone_selection:
|
||||
# We draw a rectangle to show the selected region.
|
||||
layer = self.get_selection_layer()
|
||||
if layer:
|
||||
self.osm.layer_remove(layer)
|
||||
self.selection_layer = self.add_selection_layer()
|
||||
if self.end_selection == None:
|
||||
self.selection_layer.add_rectangle(self.begin_selection, current)
|
||||
else:
|
||||
self.selection_layer.add_rectangle(self.begin_selection, self.end_selection)
|
||||
# We draw a rectangle to show the selected region.
|
||||
layer = self.get_selection_layer()
|
||||
if layer:
|
||||
self.osm.layer_remove(layer)
|
||||
self.selection_layer = self.add_selection_layer()
|
||||
if self.end_selection == None:
|
||||
self.selection_layer.add_rectangle(self.begin_selection,
|
||||
current)
|
||||
else:
|
||||
self.selection_layer.add_rectangle(self.begin_selection,
|
||||
self.end_selection)
|
||||
else:
|
||||
places = self.is_there_a_place_here(lat, lon)
|
||||
mess = ""
|
||||
for p in places:
|
||||
for plc in places:
|
||||
if mess != "":
|
||||
mess += " || "
|
||||
mess += p[0]
|
||||
mess += plc[0]
|
||||
self.uistate.status.pop(self.context_id)
|
||||
self.context_id = self.uistate.status.push(1, mess)
|
||||
|
||||
@ -260,8 +225,8 @@ class osmGpsMap():
|
||||
"""
|
||||
_LOG.debug("save_center : %s,%s" % (lat, lon) )
|
||||
if ( -90.0 < lat < +90.0 ) and ( -180.0 < lon < +180.0 ):
|
||||
config.set("geography.center-lat",lat)
|
||||
config.set("geography.center-lon",lon)
|
||||
config.set("geography.center-lat", lat)
|
||||
config.set("geography.center-lon", lon)
|
||||
else:
|
||||
_LOG.debug("save_center : new coordinates : %s,%s" % (lat, lon) )
|
||||
_LOG.debug("save_center : old coordinates : %s,%s" % (lat, lon) )
|
||||
@ -271,13 +236,22 @@ class osmGpsMap():
|
||||
config.get("geography.zoom") )
|
||||
|
||||
def activate_selection_zoom(self, osm, event):
|
||||
"""
|
||||
Zoom when in zone selection
|
||||
"""
|
||||
if self.end_selection is not None:
|
||||
self._autozoom()
|
||||
return True
|
||||
|
||||
def map_clicked(self, osm, event):
|
||||
lat,lon = self.osm.get_event_location(event).get_degrees()
|
||||
current = osmgpsmap.point_new_degrees(0.0,0.0)
|
||||
"""
|
||||
Someone click on the map. Look at if we have a marker.
|
||||
mouse button 1 : zone selection or marker selection
|
||||
mouse button 2 : begin zone selection
|
||||
mouse button 3 : call the menu
|
||||
"""
|
||||
lat, lon = self.osm.get_event_location(event).get_degrees()
|
||||
current = osmgpsmap.point_new_degrees(0.0, 0.0)
|
||||
osm.convert_screen_to_geographic(int(event.x), int(event.y), current)
|
||||
lat, lon = current.get_degrees()
|
||||
if event.button == 1:
|
||||
@ -286,24 +260,23 @@ class osmGpsMap():
|
||||
self.end_selection = None
|
||||
else:
|
||||
# do we click on a marker ?
|
||||
marker = self.is_there_a_marker_here(event, lat, lon)
|
||||
self.is_there_a_marker_here(event, lat, lon)
|
||||
elif event.button == 2 and event.type == gtk.gdk.BUTTON_PRESS:
|
||||
self.begin_selection = current
|
||||
self.end_selection = None
|
||||
self.zone_selection = True
|
||||
self.begin_selection = current
|
||||
self.end_selection = None
|
||||
self.zone_selection = True
|
||||
elif event.button == 2 and event.type == gtk.gdk.BUTTON_RELEASE:
|
||||
self.end_selection = current
|
||||
self.zone_selection = False
|
||||
self.end_selection = current
|
||||
self.zone_selection = False
|
||||
elif event.button == 3:
|
||||
self.build_nav_menu(osm, event, lat, lon )
|
||||
else:
|
||||
self.save_center(lat,lon)
|
||||
self.save_center(lat, lon)
|
||||
|
||||
def is_there_a_place_here(self, lat, lon):
|
||||
"""
|
||||
Is there a place at this position ?
|
||||
"""
|
||||
found = False
|
||||
mark_selected = []
|
||||
oldplace = ""
|
||||
for mark in self.places_found:
|
||||
@ -312,11 +285,12 @@ class osmGpsMap():
|
||||
if mark[0] != oldplace:
|
||||
oldplace = mark[0]
|
||||
precision = {
|
||||
1 : '%3.0f', 2 : '%3.1f', 3 : '%3.1f', 4 : '%3.1f',
|
||||
5 : '%3.2f', 6 : '%3.2f', 7 : '%3.2f', 8 : '%3.3f',
|
||||
9 : '%3.3f', 10 : '%3.3f', 11 : '%3.3f', 12 : '%3.3f',
|
||||
13 : '%3.3f', 14 : '%3.4f', 15 : '%3.4f', 16 : '%3.4f',
|
||||
17 : '%3.4f', 18 : '%3.4f'
|
||||
1 : '%3.0f', 2 : '%3.1f', 3 : '%3.1f',
|
||||
4 : '%3.1f', 5 : '%3.2f', 6 : '%3.2f',
|
||||
7 : '%3.2f', 8 : '%3.3f', 9 : '%3.3f',
|
||||
10 : '%3.3f', 11 : '%3.3f', 12 : '%3.3f',
|
||||
13 : '%3.3f', 14 : '%3.4f', 15 : '%3.4f',
|
||||
16 : '%3.4f', 17 : '%3.4f', 18 : '%3.4f'
|
||||
}.get(config.get("geography.zoom"), '%3.1f')
|
||||
shift = {
|
||||
1 : 5.0, 2 : 5.0, 3 : 3.0,
|
||||
@ -339,13 +313,21 @@ class osmGpsMap():
|
||||
lonok = True
|
||||
if latok and lonok:
|
||||
mark_selected.append(mark)
|
||||
found = True
|
||||
return mark_selected
|
||||
|
||||
def is_there_a_marker_here(self, lat, lon):
|
||||
def build_nav_menu(self, osm, event, lat, lon):
|
||||
"""
|
||||
Must be implemented in the caller class
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def set_crosshair(self,active):
|
||||
def is_there_a_marker_here(self, event, lat, lon):
|
||||
"""
|
||||
Must be implemented in the caller class
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def set_crosshair(self, active):
|
||||
"""
|
||||
Show or hide the crosshair ?
|
||||
"""
|
||||
@ -357,4 +339,3 @@ class osmGpsMap():
|
||||
self.osm.zoom_out()
|
||||
else:
|
||||
self.osm.layer_remove(self.cross_map)
|
||||
pass
|
256
src/plugins/lib/maps/placeselection.py
Normal file
256
src/plugins/lib/maps/placeselection.py
Normal file
@ -0,0 +1,256 @@
|
||||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: geography.py 18338 2011-10-16 20:21:22Z paul-franklin $
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.ggettext import sgettext as _
|
||||
import re
|
||||
import gobject
|
||||
import math
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.placeselection")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GTK/Gnome modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import Errors
|
||||
import ManagedWindow
|
||||
from osmGps import OsmGps
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Functions and variables
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
PLACE_REGEXP = re.compile('<span background="green">(.*)</span>')
|
||||
PLACE_STRING = '<span background="green">%s</span>'
|
||||
|
||||
def match(self, lat, lon, radius):
|
||||
"""
|
||||
coordinates matching.
|
||||
"""
|
||||
rds = float(radius)
|
||||
self.places = []
|
||||
|
||||
# place
|
||||
for entry in self.place_list:
|
||||
if (math.hypot(lat-float(entry[3]),
|
||||
lon-float(entry[4])) <= rds) == True:
|
||||
# Do we already have this place ? avoid duplicates
|
||||
self.get_location(entry[9])
|
||||
if not [self.country, self.state, self.county] in self.places:
|
||||
self.places.append([self.country, self.state, self.county])
|
||||
return self.places
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# PlaceSelection
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class PlaceSelection(ManagedWindow.ManagedWindow, OsmGps):
|
||||
"""
|
||||
We show a selection box for possible places in a region of the map.
|
||||
We can select the diameter of the region which is a circle.
|
||||
Depending of this region, we can show the possible choice.
|
||||
We select the value depending of our need which open the EditPlace box.
|
||||
"""
|
||||
def __init__(self, uistate, dbstate, maps, layer, places, lat, lon,
|
||||
function, oldvalue=None):
|
||||
"""
|
||||
Place Selection initialization
|
||||
"""
|
||||
try:
|
||||
ManagedWindow.ManagedWindow.__init__(self, uistate, [],
|
||||
PlaceSelection)
|
||||
except Errors.WindowActiveError:
|
||||
return
|
||||
self.uistate = uistate
|
||||
self.dbstate = dbstate
|
||||
self.lat = lat
|
||||
self.lon = lon
|
||||
self.osm = maps
|
||||
self.country = None
|
||||
self.state = None
|
||||
self.county = None
|
||||
self.radius = 1.0
|
||||
self.circle = None
|
||||
self.oldvalue = oldvalue
|
||||
self.place_list = places
|
||||
self.function = function
|
||||
self.selection_layer = layer
|
||||
self.layer = layer
|
||||
alignment = gtk.Alignment(0, 1, 0, 0)
|
||||
self.set_window(
|
||||
gtk.Dialog(_('Place Selection in a region'),
|
||||
flags=gtk.DIALOG_NO_SEPARATOR,
|
||||
buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
|
||||
None, _('Place Selection in a region'), None)
|
||||
label = gtk.Label(_('Choose the radius of the selection.\n'
|
||||
'On the map you should see a circle or an'
|
||||
' oval depending on the latitude.'))
|
||||
alignment.add(label)
|
||||
self.window.vbox.pack_start(alignment, expand=False)
|
||||
adj = gtk.Adjustment(1.0, 0.1, 3.0, 0.1, 0, 0)
|
||||
# default value is 1.0, minimum is 0.1 and max is 3.0
|
||||
slider = gtk.HScale(adj)
|
||||
slider.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
|
||||
slider.set_digits(1)
|
||||
slider.set_value_pos(gtk.POS_BOTTOM)
|
||||
slider.connect('value-changed', self.slider_change, self.lat, self.lon)
|
||||
self.window.vbox.pack_start(slider, expand=False)
|
||||
self.vadjust = gtk.Adjustment(page_size=15)
|
||||
self.scroll = gtk.ScrolledWindow(self.vadjust)
|
||||
self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
self.scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
self.plist = gtk.ListStore(str, str, str)
|
||||
self.choices = gtk.TreeView(self.plist)
|
||||
self.scroll.add(self.choices)
|
||||
self.renderer = gtk.CellRendererText()
|
||||
self.tvcol1 = gtk.TreeViewColumn(_('Country'), self.renderer, markup=0)
|
||||
self.tvcol2 = gtk.TreeViewColumn(_('State'), self.renderer, markup=1)
|
||||
self.tvcol3 = gtk.TreeViewColumn(_('County'), self.renderer, markup=2)
|
||||
self.tvcol1.set_sort_column_id(0)
|
||||
self.tvcol2.set_sort_column_id(1)
|
||||
self.tvcol3.set_sort_column_id(2)
|
||||
self.choices.append_column(self.tvcol1)
|
||||
self.choices.append_column(self.tvcol2)
|
||||
self.choices.append_column(self.tvcol3)
|
||||
self.window.vbox.pack_start(self.scroll, expand=True)
|
||||
self.label2 = gtk.Label()
|
||||
self.label2.set_markup('<span background="green" foreground="black"'
|
||||
'>%s</span>' %
|
||||
_('The green values in the row correspond '
|
||||
'to the current place values.'))
|
||||
alignment = gtk.Alignment(0, 1, 0, 0)
|
||||
alignment.add(self.label2)
|
||||
self.window.vbox.pack_start(alignment, expand=False)
|
||||
self.window.set_default_size(400, 300)
|
||||
self.choices.connect('row-activated', self.selection, function)
|
||||
self.window.connect('response', self.close)
|
||||
self.window.show_all()
|
||||
self.show()
|
||||
self.label2.hide()
|
||||
self.slider_change(None, lat, lon)
|
||||
|
||||
def close(self, *obj):
|
||||
"""
|
||||
Close the selection place editor
|
||||
"""
|
||||
self.hide_the_region()
|
||||
ManagedWindow.ManagedWindow.close(self, *obj)
|
||||
|
||||
def slider_change(self, obj, lat, lon):
|
||||
"""
|
||||
Display on the map a circle in which we select all the places inside this region.
|
||||
"""
|
||||
self.radius = obj.get_value() if obj else 1.0
|
||||
self.show_the_region(self.radius)
|
||||
match(self, lat, lon, self.radius)
|
||||
self.plist.clear()
|
||||
if self.oldvalue != None:
|
||||
# The old values are always in the first row.
|
||||
# In this case, we change the color of the row.
|
||||
# display the associated message
|
||||
self.label2.show()
|
||||
field1, field2, field3 = self.oldvalue
|
||||
self.plist.append((PLACE_STRING % field1,
|
||||
PLACE_STRING % field2,
|
||||
PLACE_STRING % field3)
|
||||
)
|
||||
for place in self.places:
|
||||
self.plist.append(place)
|
||||
# here, we could add value from geography names services ...
|
||||
|
||||
# if we found no place, we must create a default place.
|
||||
self.plist.append((_("New place with empty fields"), "", "..."))
|
||||
|
||||
def hide_the_region(self):
|
||||
"""
|
||||
Hide the layer which contains the circle
|
||||
"""
|
||||
layer = self.get_selection_layer()
|
||||
if layer:
|
||||
self.remove_layer(layer)
|
||||
|
||||
def show_the_region(self, rds):
|
||||
"""
|
||||
Show a circle in which we select the places.
|
||||
"""
|
||||
# circle (rds)
|
||||
self.hide_the_region()
|
||||
self.selection_layer = self.add_selection_layer()
|
||||
self.selection_layer.add_circle(rds, self.lat, self.lon)
|
||||
|
||||
def get_location(self, place):
|
||||
"""
|
||||
get location values
|
||||
"""
|
||||
place = self.dbstate.db.get_place_from_gramps_id(place)
|
||||
loc = place.get_main_location()
|
||||
data = loc.get_text_data_list()
|
||||
# new background or font color on gtk fields ?
|
||||
self.country = data[6]
|
||||
self.state = data[5]
|
||||
self.county = data[4]
|
||||
return(self.country, self.state, self.county)
|
||||
|
||||
def selection(self, obj, index, column, function):
|
||||
"""
|
||||
get location values and call the real function : add_place, edit_place
|
||||
"""
|
||||
if self.plist[index][2] == "...":
|
||||
# case with blank values ( New place with empty fields )
|
||||
self.function( "", "", "", self.lat, self.lon)
|
||||
elif self.plist[index][0][1:5] == "span":
|
||||
# case with old values ( keep the old values of the place )
|
||||
name = PLACE_REGEXP.search(self.plist[index][0], 0)
|
||||
country = name.group(1)
|
||||
name = PLACE_REGEXP.search(self.plist[index][1], 0)
|
||||
state = name.group(1)
|
||||
name = PLACE_REGEXP.search(self.plist[index][2], 0)
|
||||
county = name.group(1)
|
||||
self.function( country, county, state, self.lat, self.lon)
|
||||
else:
|
||||
# Set the new values of the country, county and state fields.
|
||||
self.function( self.plist[index][0], self.plist[index][2],
|
||||
self.plist[index][1], self.lat, self.lon)
|
||||
|
133
src/plugins/lib/maps/selectionlayer.py
Normal file
133
src/plugins/lib/maps/selectionlayer.py
Normal file
@ -0,0 +1,133 @@
|
||||
# -*- python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# Copyright (C) 2011-2012 Serge Noiraud
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
# $Id: grampsmaps.py 18399 2011-11-02 17:15:20Z noirauds $
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import os
|
||||
import gobject
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Set up logging
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
import logging
|
||||
_LOG = logging.getLogger("maps.selectionlayer")
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps Modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import const
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# osmGpsMap
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
try:
|
||||
import osmgpsmap
|
||||
except:
|
||||
raise
|
||||
|
||||
class SelectionLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize thz selection layer
|
||||
"""
|
||||
gobject.GObject.__init__(self)
|
||||
self.circles = []
|
||||
self.rectangles = []
|
||||
|
||||
def add_circle(self, rds, lat, lon):
|
||||
"""
|
||||
Add a circle
|
||||
"""
|
||||
self.circles.append((rds, lat, lon))
|
||||
|
||||
def add_rectangle(self, cp1, cp2):
|
||||
"""
|
||||
Add a rectangle
|
||||
"""
|
||||
self.rectangles.append((cp1, cp2))
|
||||
|
||||
def do_draw(self, gpsmap, drawable):
|
||||
"""
|
||||
draw the circles and the rectangles
|
||||
"""
|
||||
ggc = drawable.new_gc()
|
||||
for circle in self.circles:
|
||||
top_left = osmgpsmap.point_new_degrees(circle[1] + circle[0],
|
||||
circle[2] - circle[0])
|
||||
bottom_right = osmgpsmap.point_new_degrees(circle[1] - circle[0],
|
||||
circle[2] + circle[0])
|
||||
crd_x, crd_y = gpsmap.convert_geographic_to_screen(top_left)
|
||||
crd_x2, crd_y2 = gpsmap.convert_geographic_to_screen(bottom_right)
|
||||
drawable.draw_arc(ggc, False, crd_x, crd_y, crd_x2 - crd_x,
|
||||
crd_y2 - crd_y, 0, 360*64)
|
||||
for rectangle in self.rectangles:
|
||||
top_left, bottom_right = rectangle
|
||||
crd_x, crd_y = gpsmap.convert_geographic_to_screen(top_left)
|
||||
crd_x2, crd_y2 = gpsmap.convert_geographic_to_screen(bottom_right)
|
||||
# be sure when can select a region in all case.
|
||||
if ( crd_x < crd_x2 ):
|
||||
if ( crd_y < crd_y2 ):
|
||||
drawable.draw_rectangle(ggc, False, crd_x, crd_y,
|
||||
crd_x2 - crd_x, crd_y2 - crd_y)
|
||||
else:
|
||||
drawable.draw_rectangle(ggc, False, crd_x, crd_y2,
|
||||
crd_x2 - crd_x, crd_y - crd_y2)
|
||||
else:
|
||||
if ( crd_y < crd_y2 ):
|
||||
drawable.draw_rectangle(ggc, False, crd_x2, crd_y,
|
||||
crd_x - crd_x2, crd_y2 - crd_y)
|
||||
else:
|
||||
drawable.draw_rectangle(ggc, False, crd_x2, crd_y2,
|
||||
crd_x - crd_x2, crd_y - crd_y2)
|
||||
|
||||
def do_render(self, gpsmap):
|
||||
"""
|
||||
render the layer
|
||||
"""
|
||||
pass
|
||||
|
||||
def do_busy(self):
|
||||
"""
|
||||
set the map busy
|
||||
"""
|
||||
return False
|
||||
|
||||
def do_button_press(self, gpsmap, gdkeventbutton):
|
||||
"""
|
||||
Someone press a button
|
||||
"""
|
||||
return False
|
||||
|
||||
gobject.type_register(SelectionLayer)
|
||||
|
Loading…
x
Reference in New Issue
Block a user