/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:FDL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Free Documentation License Usage ** Alternatively, this file may be used under the terms of the GNU Free ** Documentation License version 1.3 as published by the Free Software ** Foundation and appearing in the file included in the packaging of ** this file. Please review the following information to ensure ** the GNU Free Documentation License version 1.3 requirements ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page location-places-qml.html \title QML Places API \section1 Overview The Places API allows users to discover places of interest and view details about them, such as address and contact information. Some places may have additional content associated with them, such as images and reviews. The Places API also facilitates management of places and categories, allowing users to save and remove them. \section1 Introductory Concepts \section2 Plugin A \l Plugin is an abstraction for a backend. One \l Plugin might access places from a REST server while another may access places from a local database. The following instantiates a \l Plugin object by providing a name of "osm". The \l Plugin name identifies which backend to choose from. Plugins may also be provided with a set of \l {PluginParameter} {parameters}, which essentially takes the form of a set of key-value pairs. The \l {PluginParameter} {parameters} that can be specified vary among the different \l Plugin backends. For documentation on the possible \l {PluginParameter} {parameters} and nuances of each \l Plugin, see the \l {Plugin references and parameters}{Plugin References}. \snippet places_list/places_list.qml Initialize Plugin \note The HERE plugin must be supplied with some mandatory parameters as outlined in the \l {Mandatory Parameters} {HERE Plugin} documentation. \section2 Models, Views and Delegates The QML Places API is built around the notion of models, views and delegates. \table \row \li \b Model \li A model holds data items and maintains their structure. The model is also responsible for retrieving the items from a data source. \row \li \b View \li A view is a visual container that displays the data and manages how visual items are shown such as in a list or a grid. The view may also be responsible for navigating the data, for example, scrolling through the visual items during a flicking motion. \row \li \b Delegate \li A delegate defines how individual data elements should appear as visual items in the view. The models expose a set of data roles and the delegate uses them to construct a visual item. The delegate may also define behaviour such as an operation to invoke when a visual item is clicked. \endtable The Common Use Cases section below demonstrates concrete examples of how these concepts fit together. \section1 Common Use Cases \section2 Searching for Places Searching is accomplished via the \l PlaceSearchModel. The \l {PlaceSearchModel::plugin} {plugin} property specifies which backend to perform search operations against. Search parameters may be provided through properties such as the \l {PlaceSearchModel::searchTerm} {searchTerm} and \l {PlaceSearchModel::searchArea} {searchArea}. A search operation can then be started by invoking the \l {PlaceSearchModel::update} {update()} method. For simplicity, the snippet below invokes \l {PlaceSearchModel::update} {update()} once construction of the model as been completed, typically \l {PlaceSearchModel::update} {update()} would be invoked in response to a user action such as a button click. While the search operation is underway the \l {PlaceSearchModel::status} property transitions into the \c Loading state and when successfully completed moves into the \c Ready state. \snippet places_list/places_list.qml PlaceSearchModel \section2 Display Search Results using a ListView A \l ListView can be used to show the search results found by the model. It defines the visual region for where the results are shown, and in the case below fills the entirety of its parent. The \l ListView has built in behavior that enables the region to respond to flicking events and to scroll appropriately. In the snippet below, the search model has been assigned to the ListView's \l {ListView::model} {model} property. When the model is updated with new results, the \l ListView is automatically updated to reflect the model's new data items. A simple delegate has been bound to the \l {ListView}'s \l {ListView::delegate} {delegate} property. The \l PlaceSearchModel exposes a set of \l {PlaceSearchModel Roles} {roles} of which the \e title and \e place roles have been used below, these are of type string and \l Place respectively. Essentially for each data item that should be visible in the view, the view invokes the delegate to create a visual representation of the item. \table \row \li \snippet places_list/places_list.qml Places ListView \li \inlineimage places_list.png \endtable \note For simplicty's sake we have assumed that every search result is of \l {Search Result Types} {type} \c PlaceSearchResult and so always have access to the \e place role, other search result types may not have a \e place role. See the \l {Places List(QML)} {Places List} example for full source code. \section2 Display Search Results using a MapItemView Instead of a \l ListView, the \l PlaceSearchModel can be used in conjunction with a \l MapItemView to display markers on a map. Firstly a \l Map is used to define the visual region occupied by the map, in this case it fills the entirety of its parent. Other properties are specified such as the \l {Map::plugin} {plugin} providing the maps, and the map's \l {Map::center} {center} and \l {Map::zoomLevel} {zoomLevel}. Inside the \l Map, a \l MapItemView is declared, where the \l {MapItemView::model} {model} property has been set to the search model and a \l {MapItemView::delegate} {delegate} consisting of a \l MapQuickItem is used to display a marker image. A marker is shown for every place that was found by the search model. The delegate uses the \e place role to position the marker. \table \row \li \snippet places_map/places_map.qml Places MapItemView \li \inlineimage places_map.png \endtable \note For simplicty's sake we have assumed that every search result is of \l {Search Result Types} {type} \c PlaceSearchResult and so always have access to the \e place role, other search result types may not have a \e place role. See the \l {Places Map(QML)} {Places Map} example for full source code. \section2 Fetching Place Details In order to save bandwidth, sometimes a backend will only return places which are partially populated with details. This can be checked with the Place::detailsFetched property which indicates whether all availalable details have been fetched or not. If not, the Place::getDetails() method can be invoked to fetch the remaining details. \snippet declarative/places.qml Place fetchDetails \section2 Saving and Removing Places Some backends may support saving and removing places. This can be done by calling the Place::save() and Place::remove() methods respectively. Note that in order to save a \l Place, a \l Plugin must be assigned to specify which backend we are saving to. The \l {Place::status} {status} property will transition into the \c Saving state while the save operation is happening and on successful completion will move to the \c Ready state. The following snippet shows how to save and remove a place using javascript. \snippet declarative/places.qml Place createAndSavePlace \codeline \snippet declarative/places.qml Place removePlace \section2 Learn More The above snippets only exhibit a small subset of Places functionality. Refer to the \l {Places Types} shown below for richer content such as \l {ImageModel} {images}, \l {ReviewModel} {reviews} etc, as well as more indepth descriptions and explanations. See also the \l {Places (QML)}{Places (QML)} example for a more comprehensive demonstration on how to use the API. \section1 Places Types \section2 Data Types \annotatedlist qml-QtLocation5-places-data \section2 Models \annotatedlist qml-QtLocation5-places-models */ /*! \page location-places-cpp.html \title Places (C++) \section1 Overview The Places API allows users to discover places/points of interest and view details about them such as address and contact information; some places may even have rich content such as images and reviews. The Places API also facilitates management of places and categories, allowing users to save and remove them. \section1 Place Definition \include place-definition.qdocinc \section1 Common Operations \section2 Initializing a Manager All places functionality is facilitated by a QPlaceManager instance. One must specify a QGeoServiceProvider in order to create the QPlaceManager \snippet places/requesthandler.h Initialize Manager \section2 Discovery/Search In order to perform a search operation we simply create a QPlaceSearchRequest and set the desired search parameters, such as a search term and search center. \snippet places/requesthandler.h Search for places cpp The request is an asynchronous operation so we need a slot to handle the completion of the request. In the handler we check that there are no errors and that our search result type is a place. If so we can then retrieve some of the core details of the place. At the end of the slot, we delete the reply since they are for single use only. \snippet places/requesthandler.h Search for places handler cpp \b {Note:} Depending upon the plugin backend that was chosen, the search results may contain places which have further details that can be fetched on a place by place basis. To fetch these other details see \l {Fetching Place Details}. \section3 Recommendations Recommendations can be retrieved by supplying a place id via QPlaceSearchRequest::setRecommendationId(). Any places similar to the given place are retrieved. \section3 Paging If the plugin supports paging, the limit parameter may be provided to the search request. \snippet places/requesthandler.h Search paging \section2 Fetching Place Details A place that has been returned from a search request may have more details that can be fetched. The following demonstrates how to check if there are further details and if so how to request them. \snippet places/requesthandler.h Details check \dots \dots \snippet places/requesthandler.h Details handler cpp \section2 Fetching Rich Content Rich content such as images and reviews is retrieved through the manager and then if required assigned to a place. \snippet places/requesthandler.h Image request We can handle the content request as shown below. \snippet places/requesthandler.h Image handler It is important to note that the results in the QPlaceContentReply, is a QPlaceContent::Collection which is essentially a QMap. The key \c {int} in this case is the index of the content, and the value is the content itself. Due to the way Content is implemented it is possible to convert a content type as follows \code QPlaceImage image = content; //provided that 'content' has a type QPlace::ImageType \endcode The usage of the QPlaceContent::Collection and the conversion between content and its subtypes means that code for handling the mechanics of paging reviews, images and editorials can be easily shared. \section2 Search Suggestions The retrieval of search term suggestions is very similar to performing a place search. A QPlaceSearchRequest is used just like a place search, the only difference being that the search term is set to a partially completed string. \snippet places/requesthandler.h Suggestion request And when the request is done, we can use the reply to show the suggestions. \snippet places/requesthandler.h Suggestion handler \target Saving a place cpp \section2 Saving a Place The saving of a new place is performed as follows, we create a QPlace instance and populate it with information such as a name, address and coordinate. Once done we can invoke QPlaceManager::savePlace() to begin a save operation. \snippet places/requesthandler.h Save place pt1 \dots \snippet places/requesthandler.h Save place pt2 Once a place is saved the reply contains the new identifier for that place. \snippet places/requesthandler.h Save place handler Note that to save an already \e existing place, the QPlace::placeId() must be filled in with the correct identifier. Otherwise a new place will be created if empty or the wrong place overwritten if the identifier is incorrect. When a place is saved, the QPlaceManager may emit QPlaceManager::placedAdded() or QPlaceManager::placeUpdated() signals. However whether a manager does so or not is provider specific, managers accessing places from a web service will typically not emit these signals while managers accessing places locally stored generally will. \section3 Caveats \input place-caveats.qdocinc \section3 Saving Between Managers When saving places between managers, there are a few things to be aware of. Some fields of a place such as the id, categories and icons are manager specific entities for example the categories in one manager may not be recognized in another. Therefore trying to save a place directly from one manager to another is not possible. The typical approach is to use the QPlaceManager::compatiblePlace() function, it creates a copy of a place, but only copies data that the manager supports. Manager specific data such as the place identifier is not copied over. The new copy is now suitable for saving into the manager. If the manager supports matching by alternative identifiers, an alternative identifier attribute is assigned to the copy (see \l {Matching places between managers}) \snippet places/requesthandler.h Save to different manager \target Removing a place cpp \section2 Removing a Place The removal of a place is performed as follows: \snippet places/requesthandler.h Remove place \dots \dots \snippet places/requesthandler.h Remove place handler When a place is removed, the QPlaceManager may emit the QPlaceManager::placeRemoved() signal. Whether a manager does so is provider specific. Managers accessing places from a web service will typically not emit these signals, while managers accessing places stored locally generally will. \section2 Using Categories Categories are keywords that can describe a place. For example, 'park', 'theater', 'restaurant'. A place could be described by many categories, it could be a park and a music venue and a ferry or bus stop. To use categories they must first be initialized. \snippet places/requesthandler.h Initialize categories \dots \dots \snippet places/requesthandler.h Initialize categories reply After the categories have been initialized we can then use these category functions. \list \li QPlaceManager::childCategories() \li QPlaceManager::category() \li QPlaceManager::parentCategoryId() \li QPlaceManager::childCategoryIds(); \endlist To retrieve the top level categories we use the QPlaceManager::childCategories() function but do not provide a category identifier. \snippet places/requesthandler.h Top level categories If we did provide an identifier then we could retrieve a category's children. \snippet places/requesthandler.h Child categories \section2 Saving a Category The following shows how to save a category \snippet places/requesthandler.h Save category \dots \dots \snippet places/requesthandler.h Save category handler When a category is saved, the QPlaceManager may emit QPlaceManager::categoryAdded() or QPlaceManager::categoryUpdated() signals. However whether a manager does so or not is provider specific, managers accessing places from a web service will typically not emit these signals while managers accessing places locally stored generally will. \section2 Removing a Category Category removal is very similar to removing a place \snippet places/requesthandler.h Remove category \dots \dots \snippet places/requesthandler.h Remove category handler When a category is removed, the QPlaceManager may emit the QPlaceManager::categoryRemoved() signal. Whether a manager does so is provider specific. Managers accessing places from a web service will typically not emit these signals, while managers accessing places stored locally generally will. \section2 Matching Places Between Managers Sometimes you may want to cross reference whether places from one manager match those from another manager. Such a situation may arise where one manager provides read-only access to places (origin manager) while another second r/w manager (destination manager) is used to save selected favorites from the first. During a search of the origin manager we may want to know which ones have been 'favorited' into the destination manager and perhaps display a customized favorite name rather than the original name. The matching mechanism can vary between managers, but is typically accomplished through an alternative identifier. As part of the save process, the place identifier from the origin manager is saved as an alternative identifier attribute in the destination manager (which can have its own place identifier scheme). In the following example, the origin manager is from the 'here' QGeoServiceProider, therefore as part of the saving process an alternative identifier attribute, x_id_here, is set for the place saved into the destination manager (when QPlaceManager::compatiblePlace() is called) \input place-crossref.qdocinc In order to perform the matching, we create a QPlaceMatchRequest and assign it the search results from the origin manager. The QPlaceMatchRequest will be used on the destination manager to return corresponding places. We also specify matching parameters which are key value pairs. As mentioned previously, this can vary depending on the manager but typically the key is QPlaceMatchRequest::AlternativeId to indicate we are matching by alternative id, the value in this case would be x_id_here which specifies which alternative identifier attribute we are using to do the matching. \snippet places/requesthandler.h Match places \dots \dots \snippet places/requesthandler.h Match places handler \section1 Classes in Places \section2 Data Classes \annotatedlist QtLocation-places-data \section2 Request Classes \annotatedlist QtLocation-places-requests \target Places Reply Classes \section2 Reply classes \annotatedlist QtLocation-places-replies \section2 Manager Classes \annotatedlist QtLocation-places-manager */