aboutsummaryrefslogtreecommitdiffstats
path: root/tagit/tiles
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-01-29 12:01:11 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-01-29 12:01:11 +0100
commitbfb86bdd23c2fb7211636841545b4e003f07b643 (patch)
treecb0ddd9c8a5ecf84a52db9603e3a4009af32c4ef /tagit/tiles
parent0fe45bb93b7a62afa7b8b04145607aca9e57af13 (diff)
downloadtagit-bfb86bdd23c2fb7211636841545b4e003f07b643.tar.gz
tagit-bfb86bdd23c2fb7211636841545b4e003f07b643.tar.bz2
tagit-bfb86bdd23c2fb7211636841545b4e003f07b643.zip
geo tile
Diffstat (limited to 'tagit/tiles')
-rw-r--r--tagit/tiles/__init__.py4
-rw-r--r--tagit/tiles/geo.py140
2 files changed, 142 insertions, 2 deletions
diff --git a/tagit/tiles/__init__.py b/tagit/tiles/__init__.py
index 7817339..40345b6 100644
--- a/tagit/tiles/__init__.py
+++ b/tagit/tiles/__init__.py
@@ -16,7 +16,7 @@ from .browser_tags import BrowserTags
from .buttons import Buttons
from .cursor_tags import CursorTags
#from .entity_histogram import EntityHistogram
-#from .geo import Map
+from .geo import Map
#from .hints import Hints
from .info import Info
#from .libsummary import LibSummary
@@ -44,7 +44,7 @@ class TileBuilder(BuilderBase):
'Buttons': Buttons,
'CursorTags': CursorTags,
# 'EntityHistogram': EntityHistogram,
-# 'Geo': Map,
+ 'Geo': Map,
# 'Hints': Hints,
'Info': Info,
# 'LibSummary': LibSummary,
diff --git a/tagit/tiles/geo.py b/tagit/tiles/geo.py
new file mode 100644
index 0000000..796a1c2
--- /dev/null
+++ b/tagit/tiles/geo.py
@@ -0,0 +1,140 @@
+"""
+
+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('''
+<Map>:
+ # meta
+ title: "Map"
+ tooltip: 'Location of an item'
+ # content
+ map_: map_
+ MapView:
+ id: map_
+ zoom: 9
+
+<MapLabel>:
+ 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 ##