Skip to content

Commit

Permalink
Cleanup the search module
Browse files Browse the repository at this point in the history
Cleanup the old search code previously used by the GTK GUI - the modern
QML GUI uses the online services module directly. As a result search module
is now effectively empty - we will either reuse it for some advanced search
features in the future or possibly even remove it.
  • Loading branch information
M4rtinK committed Nov 9, 2021
1 parent 876e022 commit d5ad192
Showing 1 changed file with 3 additions and 329 deletions.
332 changes: 3 additions & 329 deletions modules/mod_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------
from core.point import Point
from modules.base_module import RanaModule
from core import geo
import re

from collections import OrderedDict as odict

Expand All @@ -33,16 +30,12 @@ class Search(RanaModule):

def __init__(self, *args, **kwargs):
RanaModule.__init__(self, *args, **kwargs)
self.localSearchResults = None # GLS results from onlineServices
self.scroll = 0
self.local_search_results = None # GLS results from onlineServices
self.list = None # processed results: (distance from pos, result, absolute index)
self.maxIndex = 0 # based on the number of items in the list
self.where = 'position'
self.filters = {}
# names of marker groups used for search results
self._relatedMarkerGroups = ["addressResults", "wikipediaResults"]

def loadFilters(self):
def load_filters(self):
"""fill the filter directory
the different categories are all represented by ordered dictionaries"""
filters = {}
Expand Down Expand Up @@ -142,323 +135,4 @@ def loadFilters(self):
a["swimming_pool"] = {"name": "Swimming pool", "search": "swimming pool"}
filters['Tourism'] = a

self.filters = filters

def handleMessage(self, message, messageType, args):
# without this if, we would search also for the commands that move the listable menu
# lets hope no one needs to search for reset, up or down :)

if message == 'clearSearch':
self.localSearchResults = None
self.list = None
# also remove all search related marker groups
markers = self.m.get("markers")
if markers:
for group in self._relatedMarkerGroups:
markers.removeGroup(group)
self.notify("all search results cleared", 2000)
#TODO: also clear address & Wikipedia search results
elif message == 'storePOI':
store = self.m.get('storePOI', None)
if store is None:
return
resultNr = self.get('searchResultsItemNr', None)
if resultNr is None:
return
resultTuple = filter(lambda x: x[2] == int(resultNr), self.list).pop()
result = resultTuple[1]
store.storeLocalSearchResult(result)

elif message == 'setWhere': # set the search region
if messageType == 'ms' and args:
self.where = args

elif message == 'localSearch':
if messageType == 'ml' and args:
query = None
location = None
online = self.m.get('onlineServices', None)
if not online:
self.log.error("online services module not present")
return
lsType = args[0]
sensor = 'false'
if lsType == "coords": # search around coordinates
# format: type;lat,lon;query
# parse coordinates
lat = float(args[1])
lon = float(args[2])
location = Point(lat, lon)
query = args[3]
elif lsType == "location":
# search around a location (address, coordinates, etc. ),
# modRana just forwards the location to the search engine
location = args[1]
query = args[2]
elif lsType == "position": # search around current position
query = args[1]
sensor = 'true'
fix = self.get('fix', 0)
pos = self.get('pos', None)
if fix > 1 and pos:
lat, lon = pos
location = Point(lat, lon)
else:
self.log.info("position unknown - trying to get GPS lock")
# location = None will trigger GPS fix attempt (provided GPS is enabled in Options)
location = None
elif lsType == "view": #search around current map center
query = args[1]
proj = self.m.get('projection', None)
if proj:
centreLL = proj.getScreenCentreLL()
if centreLL:
(lat, lon) = centreLL
location = Point(lat, lon)
else:
self.log.warning("screen center coordinates unknown")
return

if query:
online.localSearchAsync(query, self._handleLocalSearchResultsCB,
around=location, sensor=sensor)

elif message == "search":
if messageType == "ml" and args:
sType = args[0]
if sType == "address":
self.log.info("address search")
query = args[1]
online = self.m.get('onlineServices', None)
if online:
# geocode the text input asynchronously
online.geocodeAsync(query, self._address2llCB)
else:
self.log.error("online services module missing")
elif sType == "wikipedia":
self.log.info("Wikipedia search")
query = args[1]
online = self.m.get('onlineServices', None)
if online:
# search Wikipedia asynchronously
online.wikipediaSearchAsync(query, self._handleWikipediaResultsCB)
else:
self.log.error("online services module missing")

# DEPRECIATED ?, use the localSearch method
# TODO: depreciate this
elif message == 'searchThis': # search for a term in the message string
if messageType == 'ms' and args:
searchTerm = args
lat = None
lon = None
online = self.m.get('onlineServices', None)
if online is None:
self.log.error("online services module not present")
return

if self.where == 'position':
self.log.info("near position")
pos = self.get('pos', None)
sensor = 'true'
if pos is None:
self.log.error("our position is not known")
return
else:
(lat, lon) = pos
elif self.where == 'view':
self.log.info("near view")
proj = self.m.get('projection', None)
sensor = 'false'
if proj:
centreLL = proj.getScreenCentreLL()
if centreLL:
(lat, lon) = centreLL
else:
self.log.error("screen center coordinates unknown")
return
if lat and lon:
location = Point(lat, lon)
online.localSearchAsync(searchTerm, self._handleLocalSearchResultsCB,
around=location, sensor=sensor)

# try:
# searchList = []
# filters = self.filters
# for topLevel in filters: # iterate over the filter categories
# for key in filters[topLevel]: # iterate over the search keywords
# if filters[topLevel][key] == searchTerm: # is this the search word for the current amenity ?
# searchList.append(key) # add the matching search word to the list
# term = searchList[0] # we have a list, because an amenity can have theoretically more "providers"
#
# except:
# self.log.error("search: key not present in the filter dictionary, using the key as search term")
# term = searchTerm

# initiate asynchronous search, that is running in a separate thread

# if local['responseStatus'] != 200:
# self.log.error("search: google returned %d return code" % local['responseStatus'])
# self.log.error(("search: local search returned %d results") % len(local['responseData']['results']))
# self.localSearchResults = local

elif message == "customQuery":
# start text input for custom query
entry = self.m.get('textEntry', None)
if entry:
entryText = ""
entry.entryBox(self, 'customQuery', 'Enter your search query', entryText,
persistentKey="lastCustomLocalSearchQuery")

elif message == "searchAddress":
# start text input for an address
entry = self.m.get('textEntry', None)
if entry:
entry.entryBox(self, 'address', description='Enter an address or location description',
persistentKey="lastAddressSearchInput")

elif message == "searchWikipedia":
# start text input for an address
entry = self.m.get('textEntry', None)
if entry:
entry.entryBox(self, 'wikipedia', description='Wikipedia search query',
persistentKey="lastWikipediaSearchInput")

elif message == "routeToActiveResult":
# get a route from current position to active search result
# * center on the current position
# -> we want to actually got to there :)
activeResultTuple = self.getActiveResultTupple()
activeResult = activeResultTuple[1]
lat, lon = activeResult.getLL()
# clear any old route and route to the result
self.sendMessage('route:clearRoute|md:route:route:type=pos2ll;toLat=%f;toLon=%f;show=start' % (lat, lon))

def getActiveResultTupple(self):
resultNumber = int(self.get('searchResultsItemNr', 0))
return self.getResult(resultNumber)

def getResult(self, resultNumber, resultList=None):
if resultList is None:
resultList = self.updateDistance()
return filter(lambda x: x[2] == resultNumber, resultList).pop() # get the result for the ABSOLUTE key

def describeItem(self, index, category, itemList):
# longName = name = item.getTracklogName()
# self.log.debug(filter(lambda x: x.getTracklogName() == longName, loadedTracklogs))
# self.log.debug(loadedTracklogs.index(item))
action = "set:menu:search#searchResultsItem"
action += "|set:searchResultsItemNr:%d" % itemList[index][
2] # here we use the ABSOLUTE index, not the relative one
# action += "|set:menu:"
# name = item.getTracklogName().split('/').pop()

# action += "|set:searchResultShowLatLon:%s,%s" % (lat,lon)

point = itemList[index][1]
# Pango does not like & so we need to replace it with &amp
name = re.sub('&', '&amp;', point.name)

units = self.m.get('units', None)
distanceString = units.km2CurrentUnitString(itemList[index][0], dp=2) # use correct units

description = "%s" % distanceString

return (
name,
description,
action)

def showText(self, cr, text, x, y, widthLimit=None, fontsize=40):
if text:
cr.set_font_size(fontsize)
stats = cr.text_extents(text)
(textWidth, textHeight) = stats[2:4]

if widthLimit and textWidth > widthLimit:
cr.set_font_size(fontsize * widthLimit / textWidth)
stats = cr.text_extents(text)
(textWidth, textHeight) = stats[2:4]

cr.move_to(x, y + textHeight)
cr.show_text(text)

def updateDistance(self):
if self.localSearchResults:
position = self.get("pos", None) # our lat lon coordinates
resultList = []
index = 0
for point in self.localSearchResults: # we iterate over the local search results
if position is not None:
(lat1, lon1) = position
(lat2, lon2) = point.getLL()
distance = geo.distance(lat1, lon1, lat2, lon2)
resultTuple = (distance, point, index)
resultList.append(resultTuple) # we pack each result into a tuple with ist distance from us
else:
resultTuple = (
0, point, index) # in this case, we dont know our position, so we say the distance is 0
resultList.append(resultTuple)
index += 1
self.list = resultList
return resultList
else:
self.log.error("error -> distance update on empty results")

def _address2llCB(self, points):
if points:
self.log.info("geocoding done - something found")
markers = self.m.get('markers', None)
name = 'addressResults'
if markers:
g = markers.addGroup(name, points, menu=True)
menu = g.getMenuInstance()
if len(points) == 1: # if only one result is found, center on it righ away
point = points[0]
self._jumpToPoint(point)
else:
self.sendMessage('set:menu:menu#list#%s' % name)
menu.setOnceBackAction('set:menu:searchWhat')
else: # just jump to the first result
point = points[0]
self._jumpToPoint(point)
else:
self.log.info("geocoding done - nothing found")
self.sendMessage('ml:notification:m:No results found for this address.;5')


def _handleLocalSearchResultsCB(self, results):
self.log.info("local search result received")
# only show the results list if there are some results
if results:
self.localSearchResults = results
self.set('menu', 'search#searchResults')

def _handleWikipediaResultsCB(self, results):
"""Handle results from the asynchronous Wikipedia search"""
if results:
self.log.info("wikipedia search done - something found")
name = 'wikipediaResults'
markers = self.m.get('markers', None)
if markers:
g = markers.addGroup(name, results, menu=True)
menu = g.getMenuInstance()
if len(results) == 1: # if only one result is found, center on it righ away
point = results[0]
self._jumpToPoint(point)
else:
self.sendMessage('set:menu:menu#list#%s' % name)
menu.setOnceBackAction('set:menu:searchWhat')
else: # just jump to the first result
point = results[0]
self._jumpToPoint(point)
else:
self.log.info("wikipedia search done - nothing found")
self.sendMessage('ml:notification:m:No results found for this query.;5')

def _jumpToPoint(self, point):
mw = self.m.get('mapView', None)
if mw:
mw.jump2point(point)


self.filters = filters

0 comments on commit d5ad192

Please sign in to comment.