diff --git a/src/plugins/lib/maps/__init__.py b/src/plugins/lib/maps/__init__.py index ae07589a5..6a4fc97ea 100644 --- a/src/plugins/lib/maps/__init__.py +++ b/src/plugins/lib/maps/__init__.py @@ -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 diff --git a/src/plugins/lib/maps/constants.py b/src/plugins/lib/maps/constants.py index 559d4ee95..d29b9cf1a 100644 --- a/src/plugins/lib/maps/constants.py +++ b/src/plugins/lib/maps/constants.py @@ -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 diff --git a/src/plugins/lib/maps/dummylayer.py b/src/plugins/lib/maps/dummylayer.py new file mode 100644 index 000000000..77052b30c --- /dev/null +++ b/src/plugins/lib/maps/dummylayer.py @@ -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) + diff --git a/src/plugins/lib/maps/dummynogps.py b/src/plugins/lib/maps/dummynogps.py new file mode 100644 index 000000000..87ce3765c --- /dev/null +++ b/src/plugins/lib/maps/dummynogps.py @@ -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) + diff --git a/src/plugins/lib/maps/geography.py b/src/plugins/lib/maps/geography.py index 7a6f31406..155f66044 100644 --- a/src/plugins/lib/maps/geography.py +++ b/src/plugins/lib/maps/geography.py @@ -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('%s' % - _('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) diff --git a/src/plugins/lib/maps/lifewaylayer.py b/src/plugins/lib/maps/lifewaylayer.py new file mode 100644 index 000000000..91a09725d --- /dev/null +++ b/src/plugins/lib/maps/lifewaylayer.py @@ -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) + diff --git a/src/plugins/lib/maps/grampsmaps.py b/src/plugins/lib/maps/osmGps.py similarity index 65% rename from src/plugins/lib/maps/grampsmaps.py rename to src/plugins/lib/maps/osmGps.py index aea2c3d5b..c2b5d24b4 100644 --- a/src/plugins/lib/maps/grampsmaps.py +++ b/src/plugins/lib/maps/osmGps.py @@ -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 diff --git a/src/plugins/lib/maps/placeselection.py b/src/plugins/lib/maps/placeselection.py new file mode 100644 index 000000000..cd635ee0e --- /dev/null +++ b/src/plugins/lib/maps/placeselection.py @@ -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('(.*)') +PLACE_STRING = '%s' + +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('%s' % + _('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) + diff --git a/src/plugins/lib/maps/selectionlayer.py b/src/plugins/lib/maps/selectionlayer.py new file mode 100644 index 000000000..ae8eda70c --- /dev/null +++ b/src/plugins/lib/maps/selectionlayer.py @@ -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) +