# -*- python -*- # -*- coding: utf-8 -*- # # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2011 Serge Noiraud # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id$ #------------------------------------------------------------------------- # # Python modules # #------------------------------------------------------------------------- from gen.ggettext import sgettext as _ from gen.ggettext import ngettext import sys import os import re import gobject import time import math #------------------------------------------------------------------------ # # Set up logging # #------------------------------------------------------------------------ import logging _LOG = logging.getLogger(".geography") #------------------------------------------------------------------------- # # GTK/Gnome modules # #------------------------------------------------------------------------- import gtk #------------------------------------------------------------------------- # # Gramps Modules # #------------------------------------------------------------------------- import gen.lib import Utils from gen.display.name import displayer as _nd from gui.views.navigationview import NavigationView from libformatting import FormattingHelper 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 #------------------------------------------------------------------------- # # Functions and variables # #------------------------------------------------------------------------- PLACE_REGEXP = re.compile('(.*)') PLACE_STRING = '%s' def _get_sign(value): """ return 1 if we have a negative number, 0 in other case """ if value < 0.0: return 1 else: return 0 def _get_zoom_lat(value): """ return the zoom value for latitude depending on the distance. """ zoomlat = 1 for i, distance in enumerate([80.0, 40.0, 20.0, 10.0, 3.0, 2.0, 1.0, 0.5, 0.2, 0.1]): if value < distance: zoomlat = i+1 return zoomlat + 3 def _get_zoom_long(value): """ return the zoom value for longitude depending on the distance. """ zoomlong = 1 for i, distance in enumerate([120.0, 60.0, 30.0, 15.0, 7.0, 4.0, 2.0, 1.0, .5, .2, .1]): if value < distance: zoomlong = i+1 return zoomlong + 3 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 = None 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): """ View for pedigree tree. Displays the ancestors of a selected individual. """ #settings in the config file CONFIGSETTINGS = ( ('geography.path', GEOGRAPHY_PATH), ('geography.zoom', 10), ('geography.zoom_when_center', 12), ('geography.show_cross', True), ('geography.lock', False), ('geography.center-lat', 0.0), ('geography.center-lon', 0.0), #('geography.gps_mode', GPS_DISABLED), #('geography.gps_update_rate', float(1.0)), #('geography.max_gps_zoom', 16), #('geography.gps_increment', GPS_INCREMENT), ('geography.map_service', constants.OPENSTREETMAP), ) def __init__(self, title, pdata, dbstate, uistate, get_bookmarks, bm_type, nav_group): NavigationView.__init__(self, title, pdata, dbstate, uistate, get_bookmarks, bm_type, nav_group) self.dbstate = dbstate self.dbstate.connect('database-changed', self.change_db) self.default_text = "Enter location here!" self.centerlon = config.get("geography.center-lon") self.centerlat = config.get("geography.center-lat") self.zoom = config.get("geography.zoom") self.lock = config.get("geography.lock") if config.get('geography.path') == "" : config.set('geography.path', GEOGRAPHY_PATH ) osmGpsMap.__init__(self) self.format_helper = FormattingHelper(self.dbstate) self.centerlat = self.centerlon = 0.0 self.cross_map = None self.current_map = None self.without = 0 self.place_list = [] self.places_found = [] self.select_fct = None self.geo_mainmap = gtk.gdk.pixbuf_new_from_file_at_size( os.path.join(const.ROOT_DIR, "images", "22x22", ('gramps-geo-mainmap' + '.png' )), 22, 22) self.geo_altmap = gtk.gdk.pixbuf_new_from_file_at_size( os.path.join(const.ROOT_DIR, "images", "22x22", ('gramps-geo-altmap' + '.png' )), 22, 22) if ( config.get('geography.map_service') in ( constants.OPENSTREETMAP, constants.OPENSTREETMAP_RENDERER )): default_image = self.geo_mainmap else: default_image = self.geo_altmap self.geo_othermap = {} for id in ( gen.lib.EventType.BIRTH, gen.lib.EventType.DEATH, gen.lib.EventType.MARRIAGE ): self.geo_othermap[id] = gtk.gdk.pixbuf_new_from_file_at_size( os.path.join(const.ROOT_DIR, "images", "22x22", (constants.ICONS.get(int(id), default_image) + '.png' )), 22, 22) def change_page(self): """Called when the page changes.""" NavigationView.change_page(self) self.uistate.clear_filter_results() def on_delete(self): """ Save all modified environment """ NavigationView.on_delete(self) self._config.save() def change_db(self, db): """ Callback associated with DbState. Whenever the database changes, this task is called. In this case, we rebuild the columns, and connect signals to the connected database. Tree is no need to store the database, since we will get the value from self.state.db """ self.bookmarks.update_bookmarks(self.dbstate.db.get_bookmarks()) if self.active: self.bookmarks.redraw() def can_configure(self): """ See :class:`~gui.views.pageview.PageView :return: bool """ return True def config_connect(self): """ Overwriten from :class:`~gui.views.pageview.PageView method This method will be called after the ini file is initialized, use it to monitor changes in the ini file """ self._config.connect("geography.path", self.set_path) self._config.connect("geography.zoom_when_center", self.set_zoom_when_center) def set_path(self, client, cnxn_id, entry, data): """ All geography views must have the same path for maps """ config.set("geography.path", entry) def set_zoom_when_center(self, client, cnxn_id, entry, data): """ All geography views must have the same zoom_when_center for maps """ config.set("geography.zoom_when_center", int(entry)) #------------------------------------------------------------------------- # # Map Menu # #------------------------------------------------------------------------- def build_nav_menu(self, obj, event, lat, lon): """Builds the menu for actions on the map.""" menu = gtk.Menu() menu.set_title(_('Map Menu')) if config.get("geography.show_cross"): title = _('Remove cross hair') else: title = _('Add cross hair') add_item = gtk.MenuItem(title) add_item.connect("activate", self.config_crosshair, event, lat , lon) add_item.show() menu.append(add_item) if config.get("geography.lock"): title = _('Unlock zoom and position') else: title = _('Lock zoom and position') add_item = gtk.MenuItem(title) add_item.connect("activate", self.config_zoom_and_position, event, lat , lon) add_item.show() menu.append(add_item) add_item = gtk.MenuItem(_("Add place")) add_item.connect("activate", self.add_place, event, lat , lon) add_item.show() menu.append(add_item) add_item = gtk.MenuItem(_("Link place")) add_item.connect("activate", self.link_place, event, lat , lon) add_item.show() menu.append(add_item) add_item = gtk.MenuItem(_("Center here")) add_item.connect("activate", self.set_center, event, lat , lon) add_item.show() menu.append(add_item) # Add specific module menu self.add_specific_menu(menu, event, lat, lon) # Add a separator line add_item = gtk.MenuItem(None) add_item.show() menu.append(add_item) map_name = constants.map_title[config.get("geography.map_service")] title = _("Replace '%(map)s' by =>") % { 'map' : map_name } add_item = gtk.MenuItem(title) add_item.show() menu.append(add_item) changemap = gtk.Menu() changemap.set_title(title) changemap.show() add_item.set_submenu(changemap) # show in the map menu all available providers for map in constants.map_type: changemapitem = gtk.MenuItem(constants.map_title[map]) changemapitem.show() changemapitem.connect("activate", self.change_map, map) changemap.append(changemapitem) menu.popup(None, None, None, 0, event.time) return 1 def add_specific_menu(self, menu, event, lat, lon): """ Add specific entry to the navigation menu. Must be done in the associated menu. """ raise NotImplementedError def set_center(self, menu, event, lat, lon): """ Center the map at the new position then save it. """ self.osm.set_center_and_zoom(lat, lon, config.get("geography.zoom_when_center")) self.save_center(lat, lon) #------------------------------------------------------------------------- # # Markers management # #------------------------------------------------------------------------- def is_there_a_marker_here(self, event, lat, lon): """ Is there a marker at this position ? """ found = False mark_selected = [] self.uistate.set_busy_cursor(1) for mark in self.sort: # as we are not precise with our hand, reduce the precision # depending on the zoom. precision = { 1 : '%3.0f', 2 : '%3.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, 4 : 1.0, 5 : 0.5, 6 : 0.3, 7 : 0.15, 8 : 0.06, 9 : 0.03, 10 : 0.015, 11 : 0.005, 12 : 0.003, 13 : 0.001, 14 : 0.0005, 15 : 0.0003, 16 : 0.0001, 17 : 0.0001, 18 : 0.0001 }.get(config.get("geography.zoom"), 5.0) latp = precision % lat lonp = precision % lon mlatp = precision % float(mark[3]) mlonp = precision % float(mark[4]) latok = lonok = False _LOG.debug(" compare latitude : %s with %s (precision = %s)" " place='%s'" % (float(mark[3]), lat, precision, mark[0])) _LOG.debug("compare longitude : %s with %s (precision = %s)" " zoom=%d" % (float(mark[4]), lon, precision, config.get("geography.zoom"))) if (float(mlatp) >= (float(latp) - shift) ) and \ (float(mlatp) <= (float(latp) + shift) ): latok = True if (float(mlonp) >= (float(lonp) - shift) ) and \ (float(mlonp) <= (float(lonp) + shift) ): lonok = True if latok and lonok: mark_selected.append(mark) found = True if found: self.bubble_message(event, lat, lon, mark_selected) self.uistate.set_busy_cursor(0) def bubble_message(self, event, lat, lon, mark): """ Display the bubble message. depends on the view. """ raise NotImplementedError def add_selection_layer(self): selection_layer = SelectionLayer() self.osm.layer_add(selection_layer) return selection_layer def remove_layer(self, layer): self.osm.remove_layer(layer) def add_marker(self, menu, event, lat, lon, event_type, differtype): """ Add a new marker """ mapservice = config.get('geography.map_service') if ( mapservice in ( constants.OPENSTREETMAP, constants.OPENSTREETMAP_RENDERER )): default_image = self.geo_mainmap else: default_image = self.geo_altmap value = default_image if event_type is not None: value = self.geo_othermap.get(int(event_type), default_image) if differtype: # in case multiple evts value = default_image # we use default icon. marker = self.osm.image_add_with_alignment(float(lat), float(lon), value, 0.2, 1.0) def remove_all_gps(self): """ Remove all gps points on the map """ self.osm.gps_clear() def remove_all_tracks(self): """ Remove all tracks on the map """ self.osm.track_remove_all() def remove_all_markers(self): """ Remove all markers on the map """ self.osm.image_remove_all() def _present_in_places_list(self, index, string): """ Search a string in place_list depending index """ found = any(p[index] == string for p in self.place_list) return found def _append_to_places_list(self, place, evttype, name, lat, longit, descr, year, icontype, gramps_id, place_id, event_id, family_id ): """ Create a list of places with coordinates. """ found = any(p[0] == place for p in self.place_list) if not found: self.nbplaces += 1 if len(self.place_list) == 0: self.places_found = [] self.places_found.append([place, lat, longit]) self.place_list.append([place, name, evttype, lat, longit, descr, year, icontype, gramps_id, place_id, event_id, family_id ]) self.nbmarkers += 1 tfa = float(lat) tfb = float(longit) if year is not None: tfc = int(year) if tfc != 0: if tfc < self.minyear: self.minyear = tfc if tfc > self.maxyear: self.maxyear = tfc tfa += 0.00000001 if tfa >= 0 else -0.00000001 tfb += 0.00000001 if tfb >= 0 else -0.00000001 if self.minlat == 0.0 or tfa < self.minlat: self.minlat = tfa if self.maxlat == 0.0 or tfa > self.maxlat: self.maxlat = tfa if self.minlon == 0.0 or tfb < self.minlon: self.minlon = tfb if self.maxlon == 0.0 or tfb > self.maxlon: self.maxlon = tfb def _append_to_places_without_coord(self, gid, place): """ Create a list of places without coordinates. """ if not [gid, place] in self.place_without_coordinates: self.place_without_coordinates.append([gid, place]) self.without += 1 def _create_markers(self): """ Create all markers for the specified person. """ self.remove_all_markers() self.remove_all_gps() self.remove_all_tracks() if ( self.current_map is not None and self.current_map != config.get("geography.map_service") ): self.change_map(self.osm, config.get("geography.map_service")) last = "" current = "" differtype = False savetype = None lat = 0.0 lon = 0.0 icon = None self.uistate.set_busy_cursor(True) _LOG.debug("%s" % time.strftime("start create_marker : " "%a %d %b %Y %H:%M:%S", time.gmtime())) for mark in self.sort: current = ([mark[3], mark[4]]) if last == "": last = current lat = mark[3] lon = mark[4] icon = mark[7] differtype = False continue if last != current: self.add_marker(None, None, lat, lon, icon, differtype) differtype = False last = current lat = mark[3] lon = mark[4] icon = mark[7] else: # This marker already exists. add info. if icon != mark[7]: differtype = True if ( lat != 0.0 and lon != 0.0 ): self.add_marker(None, None, lat, lon, icon, differtype) self._set_center_and_zoom() _LOG.debug("%s" % time.strftime(" stop create_marker : " "%a %d %b %Y %H:%M:%S", time.gmtime())) self.uistate.set_busy_cursor(False) def _set_center_and_zoom(self): """ Calculate the zoom. The best should be an auto zoom to have all markers on the screen. need some works here. we start at zoom 1 until zoom y ( for this a preference ) If all markers are present, continue to zoom. If some markers are missing : return to the zoom - 1 The following is too complex. In some case, all markers are not present. """ # Select the center of the map and the zoom signminlon = _get_sign(self.minlon) signminlat = _get_sign(self.minlat) signmaxlon = _get_sign(self.maxlon) signmaxlat = _get_sign(self.maxlat) # auto zoom ? if signminlon == signmaxlon: maxlong = abs(abs(self.minlon) - abs(self.maxlon)) else: maxlong = abs(abs(self.minlon) + abs(self.maxlon)) if signminlat == signmaxlat: maxlat = abs(abs(self.minlat) - abs(self.maxlat)) else: maxlat = abs(abs(self.minlat) + abs(self.maxlat)) # Calculate the zoom. all places must be displayed on the map. zoomlat = _get_zoom_lat(maxlat) zoomlong = _get_zoom_long(maxlong) self.new_zoom = zoomlat if zoomlat < zoomlong else zoomlong self.new_zoom -= 1 if self.new_zoom < 2: self.new_zoom = 2 # We center the map on a point at the center of all markers self.centerlat = maxlat/2 self.centerlon = maxlong/2 latit = longt = 0.0 for mark in self.sort: if ( signminlat == signmaxlat ): if signminlat == 1: latit = self.minlat+self.centerlat else: latit = self.maxlat-self.centerlat elif self.maxlat > self.centerlat: latit = self.maxlat-self.centerlat else: latit = self.minlat+self.centerlat if ( signminlon == signmaxlon ): if signminlon == 1: longt = self.minlon+self.centerlon else: longt = self.maxlon-self.centerlon elif self.maxlon > self.centerlon: longt = self.maxlon-self.centerlon else: longt = self.minlon+self.centerlon # all maps: 0.0 for longitude and latitude means no location. if latit == longt == 0.0: latit = longt = 0.00000001 self.mustcenter = False self.latit = latit self.longt = longt if not (latit == longt == 0.0): self.mustcenter = True if config.get("geography.lock"): self.osm.set_center_and_zoom(config.get("geography.center-lat"), config.get("geography.center-lon"), config.get("geography.zoom") ) else: self.osm.set_center_and_zoom(self.latit, self.longt, self.new_zoom) self.save_center(self.latit, self.longt) config.set("geography.zoom",self.new_zoom) def _get_father_and_mother_name(self, event): """ Return the father and mother name of a family event """ dbstate = self.dbstate family_list = [ dbstate.db.get_family_from_handle(ref_handle) for (ref_type, ref_handle) in dbstate.db.find_backlink_handles(event.handle) if ref_type == 'Family' ] fnam = mnam = _("Unknown") if family_list: for family in family_list: handle = family.get_father_handle() father = dbstate.db.get_person_from_handle(handle) handle = family.get_mother_handle() mother = dbstate.db.get_person_from_handle(handle) fnam = _nd.display(father) if father else _("Unknown") mnam = _nd.display(mother) if mother else _("Unknown") return ( fnam, mnam ) #------------------------------------------------------------------------- # # Specific functionalities # #------------------------------------------------------------------------- def center_here(self, menu, event, lat, lon, mark): """ Center the map at the marker position """ self.set_center(menu, event, float(mark[3]), float(mark[4])) def add_place_bubble_message(self, event, lat, lon, marks, menu, message, mark): """ Create the place menu of a marker """ add_item = gtk.MenuItem() add_item.show() menu.append(add_item) add_item = gtk.MenuItem(message) add_item.show() menu.append(add_item) itemoption = gtk.Menu() itemoption.set_title(message) itemoption.show() add_item.set_submenu(itemoption) modify = gtk.MenuItem(_("Edit Place")) modify.show() modify.connect("activate", self.edit_place, event, lat, lon, mark) itemoption.append(modify) center = gtk.MenuItem(_("Center on this place")) center.show() center.connect("activate", self.center_here, event, lat, lon, mark) itemoption.append(center) add_item = gtk.MenuItem() add_item.show() menu.append(add_item) def edit_place(self, menu, event, lat, lon, mark): """ Edit the selected place at the marker position """ self.mark = mark place = self.dbstate.db.get_place_from_gramps_id(self.mark[9]) loc = place.get_main_location() self.select_fct = PlaceSelection(self.uistate, self.dbstate, self.osm, self.selection_layer, self.place_list, lat, lon, self.__edit_place, (loc.get_country(), loc.get_state(), loc.get_county()) ) def edit_person(self, menu, event, lat, lon, mark): """ Edit the selected person at the marker position """ _LOG.debug("edit_person : %s" % mark[8]) # need to add code here to edit the person. person = self.dbstate.db.get_person_from_gramps_id(mark[8]) try: EditPerson(self.dbstate, self.uistate, [], person) except Errors.WindowActiveError: pass def edit_family(self, menu, event, lat, lon, mark): """ Edit the selected family at the marker position """ _LOG.debug("edit_family : %s" % mark[11]) # need to add code here to edit the family. family = self.dbstate.db.get_family_from_gramps_id(mark[11]) try: EditFamily(self.dbstate, self.uistate, [], family) except Errors.WindowActiveError: pass def edit_event(self, menu, event, lat, lon, mark): """ Edit the selected event at the marker position """ _LOG.debug("edit_event : %s" % mark[10]) # need to add code here to edit the event. event = self.dbstate.db.get_event_from_gramps_id(mark[10]) try: EditEvent(self.dbstate, self.uistate, [], event) except Errors.WindowActiveError: pass def add_place(self, menu, event, lat, lon): """ Add a new place using longitude and latitude of location centered on the map """ self.select_fct = PlaceSelection(self.uistate, self.dbstate, self.osm, self.selection_layer, self.place_list, lat, lon, self.__add_place) def link_place(self, menu, event, lat, lon): """ Link an existing place using longitude and latitude of location centered on the map """ selector = SelectPlace(self.dbstate, self.uistate, []) place = selector.run() if place: loc = place.get_main_location() 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) def __add_place(self, pcountry, pcounty, pstate, plat, plon): """ Add a new place using longitude and latitude of location centered on the map """ self.select_fct.close() new_place = gen.lib.Place() new_place.set_latitude(str(plat)) new_place.set_longitude(str(plon)) loc = new_place.get_main_location() loc.set_country(pcountry) loc.set_county(pcounty) loc.set_state(pstate) new_place.set_main_location(loc) try: EditPlace(self.dbstate, self.uistate, [], new_place) self.add_marker(None, None, plat, plon, None, True) except Errors.WindowActiveError: pass def __edit_place(self, pcountry, pcounty, pstate, plat, plon): """ Edit the selected place at the marker position """ # need to add code here to edit the event. self.select_fct.close() place = self.dbstate.db.get_place_from_gramps_id(self.mark[9]) place.set_latitude(str(plat)) place.set_longitude(str(plon)) loc = place.get_main_location() loc.set_country(pcountry) loc.set_county(pcounty) loc.set_state(pstate) place.set_main_location(loc) try: EditPlace(self.dbstate, self.uistate, [], place) except Errors.WindowActiveError: pass def __link_place(self, pcountry, pcounty, pstate, plat, plon): """ Link an existing place using longitude and latitude of location centered on the map """ selector = SelectPlace(self.dbstate, self.uistate, []) place = selector.run() if place: self.select_fct.close() place.set_latitude(str(plat)) place.set_longitude(str(plon)) loc = place.get_main_location() loc.set_country(pcountry) loc.set_county(pcounty) loc.set_state(pstate) place.set_main_location(loc) try: EditPlace(self.dbstate, self.uistate, [], place) self.add_marker(None, None, plat, plon, None, True) except Errors.WindowActiveError: pass #------------------------------------------------------------------------- # # Geography preferences # #------------------------------------------------------------------------- def _get_configure_page_funcs(self): """ The function which is used to create the configuration window. """ return [self.map_options, self.specific_options] def config_zoom_and_position(self, client, cnxn_id, entry, data): """ Do we need to lock the zoom and position ? """ if config.get("geography.lock"): config.set("geography.lock", False) self._set_center_and_zoom() else: config.set("geography.lock", True) self.lock = config.get("geography.lock") pass def config_crosshair(self, client, cnxn_id, entry, data): """ We asked to change the crosshair. """ if config.get("geography.show_cross"): config.set("geography.show_cross", False) else: config.set("geography.show_cross", True) self.set_crosshair(config.get("geography.show_cross")) pass def specific_options(self, configdialog): """ Add specific entry to the preference menu. Must be done in the associated view. """ table = gtk.Table(2, 2) table.set_border_width(12) table.set_col_spacings(6) table.set_row_spacings(6) configdialog.add_text(table, _('Nothing for this view.'), 1) return _('Specific parameters'), table def map_options(self, configdialog): """ 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')) table = gtk.Table(1, 1) table.set_border_width(12) table.set_col_spacings(6) table.set_row_spacings(6) configdialog.add_text(table, _('Where to save the tiles for offline mode.'), 1) configdialog.add_entry(table, '', 2, 'geography.path') configdialog.add_text(table, _('If you have no more space in your file system\n' 'You can remove all tiles placed in the above path.\n' 'Be careful! If you have no internet, you\'ll get no map.'), 3) configdialog.add_slider(table, _('Zoom used when centering'), 4, 'geography.zoom_when_center', (2, 16)) # there is no button. I need to found a solution for this. # it can be very dangerous ! if someone put / in geography.path ... # perhaps we need some contrĂ´l on this path : # should begin with : /home, /opt, /map, ... #configdialog.add_button(table, '', 4, 'geography.clean') return _('The map'), table