/
main_map.py
221 lines (191 loc) · 7.45 KB
/
main_map.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
__title__ = "main_map"
__description__ = """Holds the mapview and mapcontainer classes"""
from kivy.garden.mapview import MapView
from kivy.garden.mapview import MapMarker
from kivymd.uix.boxlayout import MDBoxLayout
from kivy.properties import StringProperty
from kivy.metrics import dp
from kivymd.toast import toast
from kivy.logger import Logger
from kivy.properties import ObjectProperty
from global_props import is_android
from global_props import Globals
from global_props import load_Settings
from global_props import save_settings
if is_android:
from location import get_system_location
from debug import Debug
from dialogs import Dialogs
def getlatlng(location_manager):
"""
getlatlng(object)
if on android platform gets last known location
if on Windows Linux or iOS then dummy coordinates returned
could use plyer for kivy if migrate over
to cross platforms
"""
latlng = None
if is_android:
location = get_system_location(location_manager)
if location:
latlng = (location.getLatitude(), location.getLongitude())
else:
# use the debugging location
latlng = (Debug.latitude, Debug.longitude)
return latlng
class MapContainer(MDBoxLayout):
"""
Container class holds the mapview and
handles button events
"""
# Mpaview object
app = ObjectProperty(None)
mockmapview = ObjectProperty(None)
lat_text = StringProperty("-12.98989")
lon_text = StringProperty("52.87878")
def on_log(self, *args):
self.app.root.current = "log"
def on_search_button(self, *args):
self.app.root.current = "search"
def on_save_coords(self):
if not self.mockmapview.is_target_shown:
toast("No Target to save. Press on the map to place a Target")
else:
Dialogs.show_save_dialog()
def on_load_coords(self):
Dialogs.show_load_location_dialog()
def on_loc_button_released(self):
"""
Get Location position is pressed
"""
try:
latlng = getlatlng(Globals.location_manager)
if latlng:
self.mockmapview.update_current_locmarker(latlng[0], latlng[1], True)
else:
toast("Could not find your location. Try turning Location on in settings")
except Exception as err:
if "ACCESS_FINE_LOCATION" in err.__str__():
Dialogs.show_location_denied()
return
else:
Logger.info(err.__str__())
def on_start_mock(self):
"""
Start button is pressed
"""
# get the target marker coordinates
latitude, longitude = self.mockmapview.get_last_target_coords()
if latitude and longitude:
# if target marker exists then set the mock location
if is_android:
# tell mock location thread to set new coordinates
Globals.mock_thread.send_message("start", latitude, longitude)
else:
# set global debugging coordinates
Debug.latitude = latitude
Debug.longitude = longitude
self.mockmapview.update_current_locmarker(Debug.latitude, Debug.longitude, False)
else:
# Let user know nothing was selected
Dialogs.show_alert("No Target found", "Press on the map to select target location and then press the start button")
def on_stop_mock(self):
"""
Stop button is pressed
"""
if is_android:
Globals.mock_thread.send_message("stop")
else:
# Set a random location on Windows or Linux
Debug.randomize_latlng()
self.mockmapview.update_current_locmarker(Debug.latitude, Debug.longitude, False)
self.mockmapview.remove_target_marker()
class MockMapView(MapView):
DEFAULT_ZOOM_IN = 8
# reference to the mapview button toolbar
# need this to check if touch up event was triggered inside
# the toolbar if so then we ignore adding a target marker
toolbar = ObjectProperty(None)
app = ObjectProperty(None)
def __init__(self, **kwargs):
self._target_marker = None
self._current_loc_marker = None
self.is_target_shown = False
super().__init__(**kwargs)
def on_touch_up(self, touch):
"""
Map pressed get coordinates and update target marker position
"""
# make sure was inside the mapview bounds before updating target marker
if self.collide_point(touch.x, touch.y) == True and self.toolbar.collide_point(touch.x, touch.y) == False:
lat, lng = self.get_latlon_at(touch.x, touch.y - dp(23), None)
self.update_target_marker(lat, lng)
super().on_touch_up(touch)
def update_target_center(self, lat, lng):
self.update_target_marker(lat, lng)
self.center_on(lat, lng)
def get_target_coords(self):
"""
returns the target markers latitude and lontitude coords
"""
return (self._target_marker.lat, self._target_marker.lon)
def update_target_marker(self, lat, lng):
"""
update_target_locmarker(float, float)
updates the target location marker
lat - Latitude coordinates
lng - Longitude coords
"""
if self._target_marker:
self.remove_marker(self._target_marker)
self._target_marker = MapMarker(source="target.png", lat=lat, lon=lng)
self.add_marker(self._target_marker)
# add coords to root windows textfields
self.app.root.lat_text = str(lat)
self.app.root.lon_text = str(lng)
self.is_target_shown = True
def update_current_locmarker(self, lat, lng, zoom):
"""
update_current_locmarker(float, float, bool)
updates the current location marker
lat - Latitude coordinates
lng - Longitude coords
zoom - Zoom into marker if True else ignore Zoom
"""
self.center_on(lat, lng)
if zoom:
self.zoom = MockMapView.DEFAULT_ZOOM_IN
if self._current_loc_marker:
self.remove_marker(self._current_loc_marker)
self._current_loc_marker = MapMarker(source="current_marker.png", lat=lat, lon=lng)
self.add_marker(self._current_loc_marker)
#Logger.info(f"UPDATE_CURRENT_MARKER: lat={lat}, lng={lng}, zoom={zoom}")
def get_last_target_coords(self):
"""
returns last targets latitude and lonitude coordinates. None is no target selected
"""
if self._target_marker:
lat, lng = (self._target_marker.lat, self._target_marker.lon)
else:
lat, lng = (None, None)
#Logger.info(f"GET_LAST_TARGET_COORDS: lat{lat}, lng={lng}")
return (lat, lng)
def remove_target_marker(self):
if self._target_marker:
self.remove_marker(self._target_marker)
self.is_target_shown = False
def on_zoom_button(self, zoom_value):
"""
on_zoom(int)
zoom_value is the zoom value to change
zooms on target marker if no target marker then zoom
to center of map
"""
if self._target_marker:
self.center_on(self._target_marker.lat, self._target_marker.lon)
self.zoom = zoom_value
else:
self.zoom = zoom_value
settings = load_Settings()
settings["last_zoom_level"] = self.zoom
save_settings(settings)