Search Example¶
In this guide you will learn how to use AddressSearchService
to perform an assisted address search.
See the Text Search guide on how to search for anything on the map with a free-form text query.
See the Reverse Geocoding guide on how to use reverse geocoding search to find the positions of points of interest (POIs) near a programmatically or interactively/visually specified position on the map.
Address Search¶
First, get an API key token, see the Getting Started guide.
Qt should be installed to continue.The Maps SDK for Qt should be installed, see the Setup Maps SDK for Qt guide.
Overview¶
AddressSearch
demonstrates how to use the AddressSearchService
item to perform an assisted address search.
This means that the search is interactive, guiding you step by step through all the address levels, starting with the country and ending with the street, or even the house number.
In the text field, start typing the name of a country. Countries which contain the specified substring in their name are listed as you type. Click on one of the countries, Germany in this case, to go to the next level - cities.
Select a city from the list on the right by clicking on it, or start typing in the text field to filter the list, showing only those cities which contain the specified substring in their name.
Select a street from the list on the right by clicking on it, or start typing in the text field to filter the list, showing only those streets which contain the specified substring in their name.
How it works
In Qt, go to the File menu and select Open File or Project…
then browse to the AddressSearch example folder and open AddressSearch.pro
You may want to have a look at Setting your API Key to see how to open and configure a project and set your API Key.
In main.qml, we need to import the GeneralMagic QML plugin. Next, we need to make sure we allow online access, and that we are using the latest data.
1import QtQuick.Window 2.12
2import GeneralMagic 2.0
3
4Window
5{
6 visible: true
7 width: 640
8 height: 480
9 title: qsTr("Address Search Example")
10 Component.onCompleted:
11 {
12 ServicesManager.settings.token = __my_secret_token;
13 ServicesManager.settings.allowInternetConnection = true;
14
15 ServicesManager.contentUpdater(ContentItem.Type.RoadMap).autoApplyWhenReady = true;
16 ServicesManager.contentUpdater(ContentItem.Type.RoadMap).update();
17 }
The __my_secret_token property in the above QML code is set in C++ like this.
1// C++ code
2QQmlApplicationEngine engine;
3//...
4//! [Set API Key token safely]
5// go to https://developer.magiclane.com to get your token
6engine.rootContext()->setContextProperty("__my_secret_token", "YOUR_TOKEN");
7//! [Set API Key token safely]
8
9engine.load(url);
In this example, in main.cpp, replace YOUR_TOKEN with your actual Magic Lane Maps API Key.
We need to declare a AddressSearchService model to perform a search. In this example we are using levels property to keep track of all previous address levels.
1AddressSearchService
2{
3 id: addressSearch
4 property LandmarkList levels: LandmarkList
5 {
6 Landmark
7 {
8 name: "All Countries"
9 }
10 }
11 detailToSearch: nextAddressDetailLevel(parentLandmark)[0]
12 filter: filterTextField.text
13 preferences.maximumMatches: detailToSearch == AddressSearchService.Country ? 150 : 50;
14 preferences.automaticLevelSkip: true
15
16 function searchNow()
17 {
18 searchTimer.stop();
19 search();
20 }
21}
After that, we use an interactive text field to filter the next address detail.
1TextField
2{
3 id: filterTextField
4 Layout.fillWidth: true
5 placeholderText:
6 {
7 switch(addressSearch.detailToSearch)
8 {
9 case 0:
10 return ""
11 case 1:
12 return "Country"
13 case 2:
14 return "State"
15 case 3:
16 return "County"
17 case 4:
18 return "District"
19 case 5:
20 return "City"
21 case 6:
22 return "Settlement"
23 case 7:
24 return "Post Code"
25 case 8:
26 return "Street"
27 case 9:
28 return "Section"
29 case 10:
30 return "Lane"
31 case 11:
32 return "Alley"
33 case 12:
34 return "Number"
35 case 13:
36 return "Crossing"
37 }
38 }
39 enabled: addressSearch.detailToSearch != 0
40 onTextEdited: searchTimer.restart()
41 onEditingFinished: addressSearch.searchNow()
42}
On the left ListView, we show all the previous levels that we stepped through.
1ListView
2{
3 Layout.fillHeight: true
4 Layout.fillWidth: true
5 clip: true
6 model: addressSearch.levels.children
7 delegate: Text
8 {
9 text: (index == 0 ? "" : "-> ") + name
10 color:"white"
11 wrapMode: Text.WrapAnywhere
12 anchors.left: parent.left
13 anchors.leftMargin: index * 10
14 MouseArea
15 {
16 anchors.fill: parent
17 onClicked:
18 {
19 addressSearch.parentLandmark = index === 0 ? null : addressSearch.levels.children[index];
20 filterTextField.text = "";
21 addressSearch.search();
22 if (index > 0)
23 {
24 mapView.centerOnCoordinates(addressSearch.parentLandmark.coordinates,
25 mapView.maxZoomLevel - mapView.maxZoomLevel / (Math.pow(index, 2) + 1));
26 }
27 if (index + 1 < addressSearch.levels.size())
28 addressSearch.levels.remove(index + 1, addressSearch.levels.size() - index - 1);
29 }
30 }
31 }
32}
On the right ListView, we show up to 150 countries, or up to 50 detail items (county, city, etc.).
1ListView
2{
3 Layout.fillHeight: true
4 Layout.fillWidth: true
5 model: addressSearch
6 delegate: Text
7 {
8 text: landmark.name
9 color:"white"
10 wrapMode: Text.WrapAnywhere
11 MouseArea
12 {
13 anchors.fill: parent
14 onClicked:
15 {
16 addressSearch.parentLandmark = addressSearch.get(index);
17 addressSearch.levels.append(addressSearch.parentLandmark);
18 filterTextField.text = "";
19 mapView.centerOnCoordinates(addressSearch.parentLandmark.coordinates,
20 mapView.maxZoomLevel - mapView.maxZoomLevel
21 / (Math.pow(addressSearch.levels.size() - 1 , 2) + 1));
22 addressSearch.search();
23 }
24 }
25 }
26}