Места (C++)
Обзор
API Места позволяет пользователям находить места/точки интереса и просматривать подробности о них, такие как адрес и контактная информация; некоторые места могут содержать богатый контент, такой как изображения и отзывы. API Места также упрощает управление местами и категориями, позволяя пользователям сохранять и удалять их.
Определение места
Место — это точка интереса, это может быть любимый ресторан, парк или чья-то квартира. Объект QPlace представляет место, действуя как контейнер для различной информации об этом месте.
Эту информацию можно разделить на две основные категории:
- Подробности
- Богатый контент
Подробности места состоят из свойств места, таких как имя, местоположение, контактная информация и так далее. Когда место возвращается во время поиска, эти подробности заполняются. Иногда, чтобы сэкономить пропускную способность, есть дополнительная информация о месте, которую можно получить для каждого отдельного места по запросу пользователя, если он заинтересован. Функция QPlace::detailsFetched() может быть запрошена для проверки, были ли получены все доступные подробности, и если нет, то QPlaceManager::getPlaceDetails() может быть использована для их получения. Точно какие подробности заполняются во время поиска, а какие нужно получать индивидуально, может различаться в зависимости от поставщика. Более подробную информацию см. в документации плагина.
Богатый контент места состоит из таких элементов, как изображения, отзывы и статьи. Возможно, может быть много элементов богатого контента, поэтому они обрабатываются отдельно от подробностей места. Их можно получить по страницам с помощью QPlaceManager::getPlaceContent(). При необходимости контент можно назначить месту, чтобы он действовал как удобный контейнер.
Общие операции
Инициализация менеджера
Все функциональные возможности мест обеспечиваются экземпляром QPlaceManager. Для создания QPlaceManager необходимо указать QGeoServiceProvider.
//The "provider name" is used to select a particular provider
QGeoServiceProvider *provider = new QGeoServiceProvider("provider name");
QPlaceManager *manager = provider->placeManager(); Обнаружение/Поиск
Для выполнения операции поиска достаточно создать QPlaceSearchRequest и установить желаемые параметры поиска, такие как поисковый термин и центр поиска.
//instantiate request and set parameters
QPlaceSearchRequest searchRequest;
searchRequest.setSearchTerm("ice cream");
searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78)));
//send off a search request
/*QPlaceSearchReply * */ searchReply = manager->search(searchRequest);
//connect a slot to handle the reply
connect(searchReply, SIGNAL(finished()), this, SLOT(handleSearchReply())); Запрос является асинхронной операцией, поэтому нам нужен слот для обработки завершения запроса. В обработчике мы проверяем отсутствие ошибок и то, что тип результата поиска — это место. Если это так, мы можем получить некоторые основные подробности о месте. В конце слота мы удаляем ответ, так как они предназначены только для однократного использования.
void handleSearchReply() {
if (searchReply->error() == QPlaceReply::NoError) {
foreach (const QPlaceSearchResult &result, searchReply->results()) {
if (result.type() == QPlaceSearchResult::PlaceResult) {
QPlaceResult placeResult = result;
qDebug() << "Name: " << placeResult.place().name();
qDebug() << "Coordinate " << placeResult.place().location().coordinate().toString();
qDebug() << "Street: " << placeResult.place().location().address().street();
qDebug() << "Distance: " << placeResult.distance();
}
}
}
searchReply->deleteLater(); //discard reply
searchReply = 0;
} Примечание: В зависимости от выбранного плагина-бекенда, результаты поиска могут содержать места, для которых есть дополнительные подробности, которые можно получить по отдельности для каждого места. Чтобы получить эти дополнительные подробности, см. Получение подробностей о месте.
Рекомендации
Рекомендации можно получить, предоставив идентификатор места через QPlaceSearchRequest::setRecommendationId(). Получаются все места, похожие на данное место.
Странирование
Если плагин поддерживает странирование, можно предоставить параметр ограничения в запрос поиска.
QPlaceSearchRequest searchRequest; searchRequest.setLimit(15); //specify how many results are to be retrieved.
Получение подробностей о месте
У места, возвращённого запросом поиска, могут быть дополнительные подробности, которые можно получить. Следующее демонстрирует, как проверить, есть ли дополнительные подробности, и если есть, как их запросить.
if (!place.detailsFetched()) {
/*QPlaceDetailsReply * */ detailsReply = manager->getPlaceDetails(place.placeId());
connect(detailsReply, SIGNAL(finished()), this, SLOT(handleDetailsReply()));
}
...
...
void handleDetailsReply() {
QPlace place;
if (detailsReply->error() == QPlaceReply::NoError)
place = detailsReply->place();
detailsReply->deleteLater(); //discard reply
detailsReply = 0;
} Получение богатого контента
Богатый контент, такой как изображения и отзывы, извлекается через менеджер, а затем, при необходимости, назначается месту.
QPlaceContentRequest request; request.setContentType(QPlaceContent::ImageType); request.setPlaceId(place.placeId()); request.setLimit(5); /*QPlaceContentReply * */ contentReply = manager->getPlaceContent(request); connect(contentReply, SIGNAL(finished()), this, SLOT(handleImagesReply()));
Мы можем обработать запрос на контент, как показано ниже.
void handleImagesReply() {
if (contentReply->error() == QPlaceReply::NoError) {
const auto content = contentReply->content();
for (auto iter = content.cbegin(), end = content.cend(); iter != end; ++iter) {
qDebug() << "Index: " << iter.key();
QPlaceImage image = iter.value();
qDebug() << image.url();
qDebug() << image.mimeType();
}
//alternatively if indexes are irrelevant
foreach (const QPlaceImage &image, contentReply->content()) {
qDebug() << image.url();
qDebug() << image.mimeType();
}
//we can assign content to the place that it belongs to.
//the place object serves as a container where we can retrieve
//content that has already been fetched
place.insertContent(contentReply->request().contentType(), contentReply->content());
place.setTotalContentCount(contentReply->request().contentType(), contentReply->totalCount());
}
contentReply->deleteLater();
contentReply = 0;
} Важно отметить, что результаты в QPlaceContentReply — это QPlaceContent::Collection, что по сути является QMap<int, QPlaceContent>. Ключ int в этом случае — индекс контента, а значение — сам контент. Из-за способа реализации контента можно преобразовать тип контента следующим образом
QPlaceImage image = content; //provided that 'content' has a type QPlace::ImageType
Использование QPlaceContent::Collection и преобразование между контентом и его подтипами означает, что код для обработки механики странирования отзывов, изображений и статей можно легко использовать повторно.
Предложения по поиску
Получение предложений по поисковым запросам очень похоже на выполнение поиска мест. QPlaceSearchRequest используется так же, как и для поиска мест, единственное отличие заключается в том, что поисковый термин задаётся как частично завершённая строка.
QPlaceSearchRequest request;
request.setSearchTerm("piz");
request.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78)));
/* QPlaceSearchSuggestion * */suggestionReply = manager->searchSuggestions(request);
connect(suggestionReply, SIGNAL(finished()), this, SLOT(handleSuggestionReply())); И когда запрос завершён, мы можем использовать ответ для отображения предложений.
void handleSuggestionReply() {
if (suggestionReply->error() == QPlaceReply::NoError) {
foreach (const QString &suggestion, suggestionReply->suggestions())
qDebug() << suggestion;
}
suggestionReply->deleteLater(); //discard reply
suggestionReply = 0;
} Сохранение места
Сохранение нового места выполняется следующим образом: создаётся экземпляр QPlace и заполняется информация, такая как имя, адрес и координаты. После этого можно вызвать QPlaceManager::savePlace() для начала операции сохранения.
QPlace place;
place.setName( "Fred's Ice Cream Parlor" );
QGeoLocation location;
location.setCoordinate(QGeoCoordinate(12.34, 56.78));
QGeoAddress address;
address.setStreet("111 Nother Street");
...
location.setAddress(address);
place.setLocation(location);
/* QPlaceIdReply * */savePlaceReply = manager->savePlace(place);
connect(savePlaceReply, SIGNAL(finished()), this, SLOT(handleSavePlaceReply())); После сохранения места ответ содержит новый идентификатор этого места.
void handleSavePlaceReply() {
if (savePlaceReply->error() == QPlaceReply::NoError)
qDebug() << savePlaceReply->id();
savePlaceReply->deleteLater(); //discard reply
savePlaceReply = 0;
} Обратите внимание, что для сохранения уже существующего места, QPlace::placeId() необходимо заполнить правильным идентификатором. В противном случае, если поле пустое, будет создано новое место, или, если идентификатор неверный, будет перезаписано не то место.
При сохранении места QPlaceManager может генерировать сигналы QPlaceManager::placedAdded() или QPlaceManager::placeUpdated(). Однако, генерируется ли менеджер эти сигналы или нет, зависит от поставщика. Менеджеры, обращающиеся к местам через веб-сервис, обычно не генерируют эти сигналы, в то время как менеджеры, обращающиеся к местам, хранящимся локально, обычно их генерируют.
Ограничения
В настоящее время API Места разработан только для сохранения основных подробностей. Сохранение богатого контента, такого как изображения и отзывы, или подробностей, таких как поставщик и рейтинг, не является поддерживаемой областью применения. Обычно менеджер игнорирует эти поля при сохранении и может вывести сообщение об ошибке, если они заполнены.
API Места поддерживает только сохранение следующих основных подробностей:
- имя
- идентификатор места
- местоположение
- контактные данные
- иконка
- категории (подобные тегам имена для описания места)
- сфера видимости
Возможные ситуации, когда поставщики поддерживают только часть из них. Более подробную информацию см. в документации плагина.
Сохранение таких свойств, как рейтинг, расширенные атрибуты, изображения, отзывы, статьи и поставщик, явно не поддерживается API Места.
Сохранение между менеджерами
При сохранении мест между менеджерами нужно учитывать несколько моментов. Некоторые поля места, такие как идентификатор, категории и значки, являются специфическими для менеджера, например, категории в одном менеджере могут быть не распознаны в другом. Поэтому попытка напрямую сохранить место из одного менеджера в другой невозможна.
Типичный подход — использовать функцию QPlaceManager::compatiblePlace(), она создаёт копию места, но копирует только данные, которые поддерживает менеджер. Управляющая информация менеджера, такая как идентификатор места, не копируется. Новая копия теперь подходит для сохранения в менеджере. Если менеджер поддерживает сопоставление по альтернативным идентификаторам, атрибут альтернативного идентификатора назначается копии (см. Сопоставление мест между менеджерами)
//result retrieved from a different manager) QPlace place = manager->compatiblePlace(result.place()); saveReply = manager->savePlace(place);
Удаление места
Удаление места выполняется следующим образом:
/* QPlaceIdReply * */removePlaceReply = manager->removePlace(place.placeId());
connect(removePlaceReply, SIGNAL(finished()), this, SLOT(handleRemovePlaceReply()));
...
...
void handleRemovePlaceReply() {
if (removePlaceReply->error() == QPlaceReply::NoError)
qDebug() << "Removal of place identified by"
<< removePlaceReply->id() << "was successful";
removePlaceReply->deleteLater(); //discard reply
removePlaceReply = 0;
} При удалении места QPlaceManager может генерировать сигнал QPlaceManager::placeRemoved(). Генерируется ли менеджером сигнал, зависит от поставщика. Менеджеры, обращающиеся к местам через веб-сервис, как правило, не генерируют эти сигналы, в то время как менеджеры, обращающиеся к локально хранящимся местам, обычно генерируют.
Использование категорий
Категории — это ключевые слова, которые могут описывать место. Например, «парк», «театр», «ресторан». Место может быть описано многими категориями, это может быть парк, музыкальное заведение и остановка автобуса или парома.
Для использования категорий их сначала нужно инициализировать.
/* QPlaceReply * */initCatReply = manager->initializeCategories();
connect(initCatReply, SIGNAL(finished()), this, SLOT(handleInitCatReply()));
...
...
void handleInitCatReply() {
if (initCatReply->error() == QPlaceReply::NoError)
qDebug() << "Categories initialized";
else
qDebug() << "Failed to initialize categories";
initCatReply->deleteLater();
initCatReply = 0;
} После инициализации категорий можно использовать эти функции категорий.
- QPlaceManager::childCategories()
- QPlaceManager::category()
- QPlaceManager::parentCategoryId()
- QPlaceManager::childCategoryIds();
Для получения категорий верхнего уровня используется функция QPlaceManager::childCategories(), но не предоставляется идентификатор категории.
QList<QPlaceCategory> topLevelCategories = manager->childCategories();
foreach (const QPlaceCategory &category, topLevelCategories)
qDebug() << category.name(); Если мы предоставим идентификатор, то мы можем получить дочерние категории.
QList<QPlaceCategory> childCategories = manager->childCategories(pizza.categoryId());
Сохранение категории
Следующее показывает, как сохранить категорию
QPlaceCategory fastFood;
QPlaceCategory category;
category.setName("pizza");
/*QPlaceIdReply */ saveCategoryReply = manager->saveCategory(category);
connect(saveCategoryReply, SIGNAL(finished()), this, SLOT(handleSaveCategoryReply()));
//we could have saved a category as a child by supplying a parent identifier.
saveCategoryReply = manager->saveCategory(category, fastFood.categoryId());
...
...
void handleSaveCategoryReply() {
if (saveCategoryReply->error() == QPlaceReply::NoError) {
qDebug() << "Saved category id =" << saveCategoryReply->id();
}
saveCategoryReply->deleteLater();
saveCategoryReply = 0;
} При сохранении категории QPlaceManager может генерировать сигналы QPlaceManager::categoryAdded() или QPlaceManager::categoryUpdated(). Однако, генерируется ли менеджер эти сигналы или нет, зависит от поставщика. Менеджеры, обращающиеся к местам через веб-сервис, обычно не генерируют эти сигналы, в то время как менеджеры, обращающиеся к местам, хранящимся локально, обычно их генерируют.
Удаление категории
Удаление категории очень похоже на удаление места
/* QPlaceIdReply * */removeCategoryReply = manager->removeCategory(place.placeId());
connect(removeCategoryReply, SIGNAL(finished()), this, SLOT(handleRemoveCategoryReply()));
...
...
void handleRemoveCategoryReply() {
if (removeCategoryReply->error() == QPlaceReply::NoError)
qDebug() << "Removal of category identified by"
<< removeCategoryReply->id() << "was successful";
removeCategoryReply->deleteLater(); //discard reply
removeCategoryReply = 0;
} При удалении категории QPlaceManager может генерировать сигнал QPlaceManager::categoryRemoved(). Генерируется ли менеджером сигнал, зависит от поставщика. Менеджеры, обращающиеся к местам через веб-сервис, как правило, не генерируют эти сигналы, в то время как менеджеры, обращающиеся к местам, хранящимся локально, обычно генерируют.
Сопоставление мест между менеджерами
Иногда вам может понадобиться проверить, соответствуют ли места от одного менеджера местам от другого менеджера. Такая ситуация может возникнуть, когда один менеджер предоставляет только чтение мест (исходный менеджер), а другой менеджер чтения/записи (менеджер назначения) используется для сохранения избранных мест из первого. При поиске в исходном менеджере мы можем узнать, какие из них были «избраны» в менеджер назначения и, возможно, отобразить настроенное имя избранного вместо исходного.
Механизм сопоставления может различаться между менеджерами, но обычно достигается с помощью альтернативного идентификатора. В рамках процесса сохранения идентификатор места из исходного менеджера сохраняется как атрибут альтернативного идентификатора в целевом менеджере (который может иметь свою собственную схему идентификатора места). В следующем примере исходный менеджер из QGeoServiceProider 'here', поэтому в рамках процесса сохранения атрибут альтернативного идентификатора x_id_here устанавливается для места, сохраненного в целевом менеджере (при вызове QPlaceManager::compatiblePlace()
origin R/O manager(here) destination R/W manager (places_jsondb)
Save
Place id: ae246 ---> Place id: 0001
Attribute type: x_provider Attribute type: x_id_here
Attribute value: here Attribute text value: ae246 Для выполнения сопоставления мы создаем QPlaceMatchRequest и присваиваем ему результаты поиска из исходного менеджера. QPlaceMatchRequest будет использоваться в целевом менеджере для возврата соответствующих мест. Мы также указываем параметры сопоставления, которые являются парами «ключ-значение». Как упоминалось ранее, это может варьироваться в зависимости от менеджера, но обычно ключ — QPlaceMatchRequest::AlternativeId, чтобы указать, что мы выполняем сопоставление по альтернативному идентификатору, значение в данном случае будет x_id_here, которое определяет, какой атрибут альтернативного идентификатора мы используем для сопоставления.
QPlaceMatchRequest request;
request.setResults(results);
QVariantMap parameters;
parameters.insert(QPlaceMatchRequest::AlternativeId, "x_id_here");
request.setParameters(parameters);
matchReply = manager->matchingPlaces(request);
...
...
void matchHandler() {
if (matchReply->error() == QPlaceReply::NoError) {
foreach (const QPlace place, matchReply->places()) {
if (place != QPlace())
qDebug() << "Place is a favorite with name" << place.name();
else
qDebug() << "Place is not a favorite";
}
}
matchReply->deleteLater();
matchReply = 0;
} Классы мест
Классы данных
Представляет адрес QGeoLocation |
|
Представляет основную информацию о местоположении |
|
Представляет набор данных о месте |
|
Представляет общую информацию об атрибуте места |
|
Представляет категорию, к которой можно отнести QPlace |
|
Представляет контактные данные, такие как номер телефона или URL веб-сайта |
|
Служит базовым классом для типов богатого контента |
|
Представляет статью издателя, описывающую место |
|
Представляет значок |
|
Представляет ссылку на изображение |
|
Представляет результат поиска, содержащий предполагаемый поиск |
|
Содержит информацию об оценках места |
|
Представляет результат поиска, содержащий место |
|
Представляет отзыв о месте |
|
Базовый класс для результатов поиска |
|
Представляет поставщика места или контента, связанного с местом |
|
Представляет отдельного пользователя |
Классы запросов
Представляет параметры запроса контента |
|
Используется для поиска мест из одного менеджера, соответствующих местам из другого. Представляет набор параметров запроса |
|
Представляет набор параметров для запроса поиска |
Классы ответов
Управляет операцией извлечения контента, начатой экземпляром QPlaceManager |
|
Управляет операцией получения подробностей о месте, начатой экземпляром QPlaceManager |
|
Управляет операциями, возвращающими идентификатор, такими как операции сохранения и удаления мест и категорий |
|
Управляет операцией сопоставления мест, начатой экземпляром QPlaceManager |
|
Управляет операцией, начатой экземпляром QPlaceManager, и служит базовым классом для более специализированных ответов |
|
Управляет операцией поиска мест, начатой экземпляром QPlaceManager |
|
Управляет операцией предоставления подсказок поиска, начатой экземпляром QPlaceManager |
Классы менеджеров
Интерфейс, позволяющий клиентам получать доступ к местам, хранящимся в определенном бэкенде |
|
Интерфейс для разработчиков плагинов QGeoServiceProvider, желающих предоставить доступ к функциональности мест |
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.15/location-places-cpp.html