""" Part of the tagit module. A copy of the license is provided with the project. Author: Matthias Baumgartner, 2022 """ # standard imports import os # kivy ipmorts from kivy.lang import Builder from kivy.uix.label import Label import kivy.properties as kp # tagit imports # NOTE: the following line segfaults: # mapview.source.py:128:self.dp_tile_size = min(dp(self.tile_size), self.tile_size * 2) # setting it to a static value (e.g. 256) works. from tagit.external.kivy_garden.mapview import MapView, MapMarkerPopup from tagit.utils import ns from tagit.widgets.browser import BrowserAwareMixin # inner-module imports from .tile import Tile # exports __all__ = ('Map', ) ## code ## Builder.load_string(''' : # meta title: "Map" tooltip: 'Location of an item' # content map_: map_ MapView: id: map_ zoom: 9 : size: self.texture_size size_hint: None, None padding: 5, 5 font_size: '15sp' canvas.before: # background Color: rgba: 0,0,0,0.6 RoundedRectangle: size: self.size pos: self.pos radius: [10] # keep in sync with the line's radius # border Color: rgba: 0,0,0,1 Line: rounded_rectangle: self.x, self.y, self.width, self.height, 10 ''') class MapLabel(Label): pass class Map(Tile, BrowserAwareMixin): """Draw a map which indicates visible items' locations.""" # list of map markers markers = kp.ListProperty() def on_browser(self, sender, browser): """Bind to browser properties.""" # remove old binding if self.browser is not None: self.browser.unbind(cursor=self.update) self.browser.unbind(items=self.update_markers) # add new binding self.browser = browser if self.browser is not None: self.browser.bind(cursor=self.update) self.browser.bind(items=self.update_markers) # initial calls self.update_markers() self.update() def __del__(self): if self.browser is not None: self.browser.unbind(cursor=self.update) self.browser.unbind(items=self.update_markers) self.browser = None def update_markers(self, *args): """Draw markers for all browser items.""" # remove old markers for mark in self.markers: self.map_.remove_marker(mark) self.markers.clear() # get view data data = self.root.browser.unfold(self.root.browser.items).get( ns.bse.filename, ns.bse.latitude, ns.bse.longitude, node=True, ) # draw new markers for ent, vdict in data.items(): if ns.bse.latitude not in vdict: continue if ns.bse.longitude not in vdict: continue # TODO: cluster points, one marker for multiple items lat = vdict[ns.bse.latitude] lon = vdict[ns.bse.longitude] # create popup marker mark = MapMarkerPopup(lat=lat, lon=lon) text = vdict.get(ns.bse.filename, ', '.join(os.path.basename(guid) for guid in ent.guids)) mark.add_widget(MapLabel(text=text)) # add marker self.markers.append(mark) self.map_.add_marker(mark) def update(self, *args): """Focus the map on the cursor.""" if not self.visible: return cursor = self.root.browser.cursor if cursor is not None: coords = cursor.get(ns.bse.latitude, ns.bse.longitude) if set(coords.keys()) == {ns.bse.latitude, ns.bse.longitude}: lat = coords[ns.bse.latitude] lon = coords[ns.bse.longitude] self.map_.center_on(lat, lon) ## EOF ##