Places (QML)▲
Sélectionnez
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import
QtQuick 2.5
import
QtQuick.Controls 1.4
import
QtQuick.Layouts 1.2
import
QtPositioning
5.5
import
QtLocation 5.6
import
"items"
ApplicationWindow
{
id
:
appWindow
property
Map map
property
variant parameters
property
variant searchLocation
:
map ? map.center :
QtPositioning.coordinate()
property
variant searchRegion
:
QtPositioning.circle(searchLocation)
property
variant searchRegionItem
property
Plugin favoritesPlugin
function
getPlugins() {
var plugin
=
Qt.createQmlObject
(
'import QtLocation 5.3; Plugin {}'
,
appWindow);
var myArray =
new Array;
for (
var i =
0
;
i &
lt;
plugin
.
availableServiceProviders.
length;
i++
) {
var tempPlugin =
Qt.createQmlObject
(
'import QtLocation 5.3; Plugin {name: "'
+
plugin
.
availableServiceProviders[
i]+
'"}'
,
appWindow)
if (
tempPlugin.supportsPlaces
(
) &
amp;&
amp;
tempPlugin.supportsMapping
(
) )
myArray.push
(
tempPlugin.
name
)
}
myArray.sort
(
)
return myArray;
}
function
initializeProviders(pluginParameters)
{
var parameters =
new Array()
for
(var prop in pluginParameters) {
var parameter =
Qt.createQmlObject
(
'import QtLocation 5.3; PluginParameter{ name: "'
+
prop +
'"; value: "'
+
pluginParameters[
prop]+
'"}'
,
appWindow)
parameters.push
(
parameter)
}
appWindow.parameters =
parameters
var plugins =
getPlugins()
mainMenu.providerMenu.createMenu(plugins)
for
(var i =
0
; i&
lt;plugins.length; i++) {
if (
plugins[
i]
===
"osm"
)
mainMenu.selectProvider
(
plugins[
i]
)
}
}
function
createMap(provider) {
var plugin
;
if (
parameters &
amp;&
amp;
parameters.
length&
gt;
0
)
plugin
=
Qt.createQmlObject
(
'import QtLocation 5.3; Plugin{ name:"'
+
provider +
'"; parameters: appWindow.parameters}'
,
appWindow)
else
plugin
=
Qt.createQmlObject
(
'import QtLocation 5.3; Plugin{ name:"'
+
provider +
'"}'
,
appWindow)
if (
map)
map.destroy
(
);
map =
mapComponent.createObject
(
page);
map.
plugin
=
plugin
;
map.
zoomLevel = (
map.
maximumZoomLevel -
map.
minimumZoomLevel)/
2
categoryModel.
plugin
=
plugin
;
categoryModel.update
(
);
placeSearchModel.
plugin
=
plugin
;
suggestionModel.
plugin
=
plugin
;
}
title
:
qsTr("Places"
)
width
:
360
height
:
640
visible
:
true
menuBar
:
mainMenu
toolBar
:
searchBar
MainMenu {
id
:
mainMenu
onSelectProvider
: {
stackView.pop
(
page)
for (
var i =
0
;
i &
lt;
providerMenu.
items.
length;
i++
) {
providerMenu.
items[
i].
checked =
providerMenu.
items[
i].
text
===
providerName
}
createMap
(
providerName)
if (
map.
error ===
Map.
NoError) {
settingsMenu.createMenu
(
map);
}
else {
settingsMenu.clear
(
);
}
}
onSelectSetting
: {
stackView.pop
({
tem
:
page,
immediate
:
true}
)
switch (
setting) {
case "searchCenter"
:
stackView.push
({
item
:
Qt.resolvedUrl
(
"forms/SearchCenter.qml"
) ,
properties
:
{
"coordinate"
:
map.
center}}
)
stackView.
currentItem.
changeSearchCenter.connect
(
stackView.
changeSearchCenter)
stackView.
currentItem.
closeForm.connect
(
stackView.
closeForm)
break
case "searchBoundingBox"
:
stackView.push
({
item
:
Qt.resolvedUrl
(
"forms/SearchBoundingBox.qml"
) ,
properties
:
{
"searchRegion"
:
searchRegion}}
)
stackView.
currentItem.
changeSearchBoundingBox.connect
(
stackView.
changeSearchBoundingBox)
stackView.
currentItem.
closeForm.connect
(
stackView.
closeForm)
break
case "searchBoundingCircle"
:
stackView.push
({
item
:
Qt.resolvedUrl
(
"forms/SearchBoundingCircle.qml"
) ,
properties
:
{
"searchRegion"
:
searchRegion}}
)
stackView.
currentItem.
changeSearchBoundingCircle.connect
(
stackView.
changeSearchBoundingCircle)
stackView.
currentItem.
closeForm.connect
(
stackView.
closeForm)
break
case "SearchOptions"
:
stackView.push
({
item
:
Qt.resolvedUrl
(
"forms/SearchOptions.qml"
) ,
properties
:
{
"plugin"
:
map.
plugin
,
"model"
:
placeSearchModel}}
)
stackView.
currentItem.
changeSearchSettings.connect
(
stackView.
changeSearchSettings)
stackView.
currentItem.
closeForm.connect
(
stackView.
closeForm)
break
default
:
console.log
(
"Unsupported setting !"
)
}
}
}
SearchBar {
id
:
searchBar
width
:
appWindow.width
searchBarVisbile
:
stackView.depth &
gt; 1
&
amp;&
amp;
stackView.currentItem &
amp;&
amp;
stackView.currentItem.objectName !=
"suggestionView"
? false
:
true
onShowCategories
: {
if (
map &
amp;&
amp;
map.
plugin
) {
stackView.pop
({
tem
:
page,
immediate
:
true}
)
stackView.enterCategory
(
)
}
}
onGoBack
:
stackView.pop()
onSearchTextChanged
: {
if (
searchText.
length &
gt;=
3
&
amp;&
amp;
suggestionModel !=
null) {
suggestionModel.
searchTerm =
searchText;
suggestionModel.update
(
);
}
}
onDoSearch
: {
if (
searchText.
length &
gt;
0
)
placeSearchModel.searchForText
(
searchText);
}
onShowMap
:
stackView.pop(page)
}
StackView
{
id
:
stackView
function
showMessage(title
,message,backPage)
{
push({
item
:
Qt.resolvedUrl("forms/Message.qml"
) ,
properties
: {
"title"
:
title,
"message"
:
message,
"backPage"
:
backPage
}}
)
currentItem.closeForm.connect(closeMessage)
}
function
closeMessage(backPage)
{
pop(backPage)
}
function
closeForm()
{
pop(page)
}
function
enterCategory(index
)
{
push({
item
:
Qt.resolvedUrl("views/CategoryView.qml"
) ,
properties
: {
"categoryModel"
:
categoryModel,
"rootIndex"
:
index
}}
)
currentItem.showSubcategories.connect(stackView.enterCategory)
currentItem.searchCategory.connect(placeSearchModel.searchForCategory)
}
function
showSuggestions()
{
if
(currentItem.objectName !=
"suggestionView"
) {
stackView.pop
(
page)
push
({
item
:
Qt.resolvedUrl
(
"views/SuggestionView.qml"
) ,
properties
:
{
"suggestionModel"
:
suggestionModel }
}
)
currentItem.
objectName =
"suggestionView"
currentItem.
suggestionSelected.connect
(
searchBar.
showSearch)
currentItem.
suggestionSelected.connect
(
placeSearchModel.
searchForText)
}
}
function
showPlaces()
{
if
(currentItem.objectName !=
"searchResultView"
) {
stackView.pop
({
tem
:
page,
immediate
:
true}
)
push
({
item
:
Qt.resolvedUrl
(
"views/SearchResultView.qml"
) ,
properties
:
{
"placeSearchModel"
:
placeSearchModel }
}
)
currentItem.
showPlaceDetails.connect
(
showPlaceDatails)
currentItem.
showMap.connect
(
searchBar.
showMap)
currentItem.
objectName =
"searchResultView"
}
}
function
showPlaceDatails(place, distance)
{
push({
item
:
Qt.resolvedUrl("forms/PlaceDetails.qml"
) ,
properties
: {
"place"
:
place,
"distanceToPlace"
:
distance }
}
)
currentItem.searchForSimilar.connect(searchForSimilar)
currentItem.showReviews.connect(showReviews)
currentItem.showEditorials.connect(showEditorials)
currentItem.showImages.connect(showImages)
}
function
showEditorials(place)
{
push({
item
:
Qt.resolvedUrl("views/EditorialView.qml"
) ,
properties
: {
"place"
:
place }
}
)
currentItem.showEditorial.connect(showEditorial)
}
function
showReviews(place)
{
push({
item
:
Qt.resolvedUrl("views/ReviewView.qml"
) ,
properties
: {
"place"
:
place }
}
)
currentItem.showReview.connect(showReview)
}
function
showImages(place)
{
push({
item
:
Qt.resolvedUrl("views/ImageView.qml"
) ,
properties
: {
"place"
:
place }
}
)
}
function
showEditorial(editorial)
{
push({
item
:
Qt.resolvedUrl("views/EditorialPage.qml"
) ,
properties
: {
"editorial"
:
editorial }
}
)
}
function
showReview(review)
{
push({
item
:
Qt.resolvedUrl("views/ReviewPage.qml"
) ,
properties
: {
"review"
:
review }
}
)
}
function
changeSearchCenter(coordinate)
{
stackView.pop(page)
map.center =
coordinate;
if
(searchRegionItem) {
map.removeMapItem
(
searchRegionItem);
searchRegionItem.destroy
(
);
}
}
function
changeSearchBoundingBox(coordinate,widthDeg,heightDeg)
{
stackView.pop(page)
map.center =
coordinate
searchRegion =
QtPositioning.rectangle(map.center, widthDeg, heightDeg)
if
(searchRegionItem) {
map.removeMapItem
(
searchRegionItem);
searchRegionItem.destroy
(
);
}
searchRegionItem =
Qt.createQmlObject('import QtLocation 5.3; MapRectangle { color: "#46a2da"; border.color: "#190a33"; border.width: 2; opacity: 0.25 }'
, page, "MapRectangle"
);
searchRegionItem.topLeft =
searchRegion.topLeft;
searchRegionItem.bottomRight =
searchRegion.bottomRight;
map.addMapItem(searchRegionItem);
}
function
changeSearchBoundingCircle(coordinate,radius
)
{
stackView.pop(page)
map.center =
coordinate;
searchRegion =
QtPositioning.circle(coordinate, radius
)
if
(searchRegionItem) {
map.removeMapItem
(
searchRegionItem);
searchRegionItem.destroy
(
);
}
searchRegionItem =
Qt.createQmlObject('import QtLocation 5.3; MapCircle { color: "#46a2da"; border.color: "#190a33"; border.width: 2; opacity: 0.25 }'
, page, "MapRectangle"
);
searchRegionItem.center =
searchRegion.center;
searchRegionItem.radius =
searchRegion.radius;
map.addMapItem(searchRegionItem);
}
function
changeSearchSettings(orderByDistance, orderByName, locales)
{
stackView.pop(page)
/*if (isFavoritesEnabled) {
if (favoritesPlugin == null)
favoritesPlugin = Qt.createQmlObject('import QtLocation 5.3; Plugin { name: "places_jsondb" }', page);
favoritesPlugin.parameters = pluginParametersFromMap(pluginParameters);
placeSearchModel.favoritesPlugin = favoritesPlugin;
} else {
placeSearchModel.favoritesPlugin = null;
}*/
placeSearchModel.favoritesPlugin =
null;
placeSearchModel.relevanceHint =
orderByDistance ? PlaceSearchModel.DistanceHint :
orderByName ? PlaceSearchModel.LexicalPlaceNameHint :
PlaceSearchModel.UnspecifiedHint;
map.plugin.locales =
locales.split(Qt.locale().groupSeparator);
}
function
searchForSimilar(place) {
stackView.pop
(
page)
searchBar.showSearch
(
place.
name
)
placeSearchModel.searchForRecommendations
(
place.
placeId);
}
anchors.fill
:
parent
focus
:
true
initialItem
:
Item
{
id
:
page
PlaceSearchModel {
id
:
placeSearchModel
searchArea
:
searchRegion
function
searchForCategory(category) {
searchTerm =
""
;
categories =
category;
recommendationId =
""
;
searchArea =
searchRegion
limit =
-
1
;
update
(
);
}
function
searchForText(text
) {
searchTerm =
text
;
categories =
null;
recommendationId =
""
;
searchArea =
searchRegion
limit =
-
1
;
update
(
);
}
function
searchForRecommendations(placeId) {
searchTerm =
""
;
categories =
null;
recommendationId =
placeId;
searchArea =
null;
limit =
-
1
;
update
(
);
}
onStatusChanged
: {
switch (
status
) {
case PlaceSearchModel.
Ready
:
if (
count &
gt;
0
)
stackView.showPlaces
(
)
else
stackView.showMessage
(
qsTr
(
"Search Place Error"
),
qsTr
(
"Place not found !"
))
break;
case PlaceSearchModel.
Error
:
stackView.showMessage
(
qsTr
(
"Search Place Error"
),
errorString
(
))
break;
}
}
}
PlaceSearchSuggestionModel {
id
:
suggestionModel
searchArea
:
searchRegion
onStatusChanged
: {
if (
status
==
PlaceSearchSuggestionModel.
Ready)
stackView.showSuggestions
(
)
}
}
CategoryModel {
id
:
categoryModel
hierarchical
:
true
}
Component
{
id
:
mapComponent
MapComponent {
width
:
page.width
height
:
page.height
onErrorChanged
: {
if (
map.
error !=
Map.
NoError) {
var title =
qsTr
(
"ProviderError"
);
var message =
map.
errorString +
"<br/><br/><b>"
+
qsTr
(
"Try to select other provider"
) +
"</b>"
;
if (
map.
error ==
Map.
MissingRequiredParameterError)
message +=
"<br/>"
+
qsTr
(
"or see"
) +
"
\'
mapviewer --help
\'
"
+
qsTr
(
"how to pass plugin parameters."
);
stackView.showMessage
(
title,
message);
}
}
MapItemView {
model
:
placeSearchModel
delegate
:
MapQuickItem {
coordinate
:
model.type ===
PlaceSearchModel.PlaceResult ? place.location.coordinate :
QtPositioning.coordinate()
visible
:
model.type ===
PlaceSearchModel.PlaceResult
anchorPoint.x
:
image.width *
0.28
anchorPoint.y
:
image.height
sourceItem
:
Image
{
id
:
image
source
:
"resources/marker.png"
MouseArea
{
anchors.fill
:
parent
onClicked
:
stackView.showPlaceDatails(model.place,model.distance)
}
}
}
}
}
}
}
}
Rectangle
{
color
:
"white"
opacity
:
busyIndicator.running ? 0.8 :
0
anchors.fill
:
parent
Behavior
on
opacity
{
NumberAnimation
{}
}
}
BusyIndicator
{
id
:
busyIndicator
anchors.centerIn
:
parent
running
:
placeSearchModel.status ==
PlaceSearchModel.Loading ||
categoryModel.status ===
CategoryModel.Loading
}
}