Sur cette page

Lieux (QML)

L'exemple « Lieux » montre comment rechercher des lieux et accéder au contenu associé.

Exemple de page « Lieux » comportant un champ de recherche et une carte d'Oslo sur laquelle figure un repère intitulé « The Qt Company »

L'exemple « Lieux » montre comment rechercher des lieux. Il explique notamment comment récupérer des informations complémentaires telles que des avis, des images et du contenu associé.

Exécution de l'exemple

Vous pouvez exécuter l'exemple à partir de :

L'exemple fonctionne avec n'importe quel plugin de services géographiques disponible. Cependant, certains plugins peuvent nécessiter une plugin parameters supplémentaire pour fonctionner correctement. L'argument Plugin parameters peut être passé en ligne de commande à l'aide de l'argument --plugin, qui prend la forme suivante :

--plugin.<parameter name> <parameter value>

Reportez-vous à la documentation de chaque plugin de services géographiques pour plus de détails sur les paramètres pris en charge par chacun d’entre eux. Le plugin utilisé par défaut dans cet exemple est le plugin OpenStreetMap deQt Location , qui ne nécessite aucun paramètre.

Présentation générale

L'exemple « Places » présente une fenêtre d'application affichant une carte. En haut de la fenêtre se trouve un champ de recherche, qui sert à saisir une requête de recherche de lieu. Pour rechercher un lieu, saisissez un terme de recherche dans la zone de texte, puis cliquez sur l’icône en forme de loupe. Pour rechercher un lieu par catégorie, cliquez sur l’icône de catégorie afin d’afficher la liste des catégories disponibles, puis sélectionnez la catégorie souhaitée. La recherche portera sur les lieux situés à proximité de la position actuelle indiquée sur la carte.

Pour certains plugins, le champ de recherche propose des suggestions de termes de recherche dès que trois caractères ou plus sont saisis. Sélectionner l'une de ces suggestions lancera une recherche de lieux à l'aide du texte de recherche sélectionné.

Cliquer sur un résultat de recherche affiche les détails concernant le lieu. Si un lieu dispose d’un contenu enrichi (articles, avis et images), ceux-ci sont accessibles via les boutons de la page de détails. Pour trouver des lieux similaires, cliquez sur le bouton « Trouver des lieux similaires ».

Il est possible de changer de fournisseur de services géolocalisation en accédant au menu « Fournisseur ».

Affichage des catégories

Avant de pouvoir effectuer une recherche par catégorie, il faut récupérer la liste des catégories disponibles. Pour cela, il faut créer une requête de type « CategoryModel ».

CategoryModel {
    id: categoryModel
    hierarchical: true
}

Le type « CategoryModel » fournit un modèle des catégories disponibles. Il peut fournir soit une liste plate, soit un modèle arborescent hiérarchique. Dans cet exemple, nous utilisons un modèle arborescent hiérarchique, en définissant la propriété « hierarchical » sur « true ». La propriété « plugin » est définie lors de l'initialisation de l'exemple.

Nous créons ensuite un ` ListView ` pour afficher le modèle de catégories.

ListView {
    id: root
    property var categoryModel
    property var rootIndex

    signal searchCategory(var category)
    signal showSubcategories(var index)

    snapMode: ListView.SnapToItem

    model: DelegateModel {
        id: delegeteDataModel
        model: root.categoryModel
        rootIndex: root.rootIndex
        delegate: CategoryDelegate {
            width: ListView.view.width
            onSearchCategory: root.searchCategory(category);
            onShowSubcategories: root.showSubcategories(delegeteDataModel.modelIndex(index));
        }
    }
}

Comme nous utilisons un modèle hiérarchique, un ` DelegateModel ` est nécessaire pour fournir des fonctionnalités de navigation. Si nous avions utilisé un modèle de liste plate, la vue aurait pu utiliser directement la propriété ` CategoryModel `.

La propriété `rootIndex` définit l’index racine de l’ DelegateModel. Les catégories sont affichées par le `CategoryDelegate`, qui fournit deux signaux. Le signal `onShowSubcategories` émet le signal `showSubcategories()` avec l’index racine remplacé par l’index actuel, ce qui entraîne l’affichage des sous-catégories de la catégorie sélectionnée. Le gestionnaire onSearchCategory émet le signal searchCategory() avec un paramètre category indiquant quelle catégorie spécifique a été choisie.

Le CategoryDelegate affiche le nom de la catégorie et émet le signal searchCategory() lorsque l'on clique sur l'Label:

Label {
    id: labelItem
    text: category.name
    anchors.left: icon.right
    anchors.right: parent.right
    anchors.verticalCenter: parent.verticalCenter
}

TapHandler {
    id: tapHanlder
    onTapped: {
        if (model.hasModelChildren) {
            root.showSubcategories()
        } else {
            root.searchCategory()
        }
    }
}

Présentation des suggestions de recherche

Le type « PlaceSearchSuggestionModel » sert à récupérer des suggestions de recherche en fonction d'un terme de recherche partiellement saisi.

Une nouvelle recherche de suggestions est déclenchée dès que le terme de recherche saisi est modifié.

SearchBar {
    id: searchBar
    onSearchTextChanged: function (searchText) {
        if (searchText.length >= 3 && suggestionModel != null) {
            suggestionModel.searchTerm = searchText;
            suggestionModel.update();
        }
    }
}

Les suggestions ne sont recherchées que si le terme de recherche comporte au moins trois caractères.

Lorsque le statut de l’ PlaceSearchSuggestionModel ation change, des suggestions de recherche s’affichent.

PlaceSearchSuggestionModel {
    id: suggestionModel
    searchArea: searchRegion

    onStatusChanged: {
        if (status == PlaceSearchSuggestionModel.Ready)
            stackView.showSuggestions()
    }
}

L'objet principal de l'état « SuggestionsShown » est l'ListView, qui affiche les suggestions de recherche.

ListView {
    id: suggestionView
    property var suggestionModel
    signal suggestionSelected(string text)

    model: suggestionModel
    delegate: Item {
        width: ListView.view.width
        height: label.height * 1.5
        Label {
            id: label
            text: suggestion
        }
        MouseArea {
            anchors.fill: parent
            onClicked: suggestionSelected(suggestion)
        }
    }
}

Un objet Label est utilisé comme délégué pour afficher le texte de la suggestion. Un clic sur le terme de recherche suggéré met à jour le terme de recherche et déclenche une recherche de lieu à l’aide de la suggestion de recherche.

Recherche de lieux

Le type PlaceSearchModel est utilisé pour rechercher des lieux.

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 > 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;
        }
    }
}

On commence par définir certaines propriétés du modèle, qui serviront à formuler la requête de recherche. La propriété ` searchArea ` est définie sur l’objet `searchRegion`, qui est une instance de ` geoCircle ` dont le centre est lié à la position actuelle affichée sur l’ Map.

Enfin, nous définissons trois fonctions d’aide : searchForCategory(), searchForText() et searchForRecommendations(), qui définissent les propriétés categories, searchTerm ou recommendationId, puis appellent la méthode update() pour lancer la recherche de lieux. Les résultats de la recherche s’affichent dans un ListView.

ListView {
    id: searchView

    property var placeSearchModel
    signal showPlaceDetails(var place, var distance)
    signal showMap()

    model: placeSearchModel
    delegate: SearchResultDelegate {
        width: ListView.view.width
        onShowPlaceDetails: function (place, distance) { searchView.showPlaceDetails(place, distance) }
        onSearchFor: function (query) { placeSearchModel.searchForText(query) }
    }

    footer: RowLayout {
        width: parent.width

        Button {
            text: qsTr("Previous")
            enabled: placeSearchModel.previousPagesAvailable
            onClicked: placeSearchModel.previousPage()
            Layout.alignment: Qt.AlignHCenter
        }

        Button {
            text: qsTr("Clear")
            onClicked: {
                placeSearchModel.reset()
                showMap()
            }
            Layout.alignment: Qt.AlignHCenter
        }

        Button {
            text: qsTr("Next")
            enabled: placeSearchModel.nextPagesAvailable
            onClicked: placeSearchModel.nextPage()
            Layout.alignment: Qt.AlignHCenter
        }
    }
}

Le délégué utilisé dans ` ListView`, `SearchResultDelegate`, est conçu pour gérer plusieurs types de résultats de recherche via un objet ` Loader `. Pour les résultats de type `PlaceResult`, le délégué est :

Component {
    id: placeComponent
    Item {
        id: placeRoot
        width: root.width
        height: Math.max(icon.height, 3 * placeName.height)

        Rectangle {
            anchors.fill: parent
            color: "#44ffffff"
            visible: mouse.pressed
        }

        Rectangle {
            anchors.fill: parent
            color: "#dbffde"
            visible: model.sponsored !== undefined ? model.sponsored : false

            Label {
                text: qsTr("Sponsored result")
                horizontalAlignment: Text.AlignRight
                anchors.right: parent.right
                anchors.bottom: parent.bottom
                font.pixelSize: 8
                visible: model.sponsored !== undefined ? model.sponsored : false
            }
        }

        GridLayout {
            rows: 2
            columns: 2
            anchors.fill: parent
            anchors.leftMargin: 30
            flow: GridLayout.TopToBottom

            Image {
                // anchors.verticalCenter: parent.verticalCenter
                id:icon
                source: place.favorite ? Qt.resolvedUrl("../resources/star.png") : place.icon.url()
                Layout.rowSpan: 2
            }

            Label {
                id: placeName
                text: place.favorite ? place.favorite.name : place.name
                Layout.fillWidth: true
            }

            Label {
                id: distanceText
                font.italic: true
                text: Helper.formatDistance(distance)
                Layout.fillWidth: true
            }
        }

        Rectangle {
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.margins: 15
            height: 1
            color: "#46a2da"
        }

        MouseArea {
            id: mouse
            anchors.fill: parent
            onClicked: {
                if (model.type === undefined || type === PlaceSearchModel.PlaceResult) {
                    if (!place.detailsFetched)
                        place.getDetails();
                    root.showPlaceDetails(model.place, model.distance);
                }
            }
        }
    }
}

Affichage du contenu d'un lieu

Les lieux peuvent comporter du contenu enrichi supplémentaire, notamment des articles rédactionnels, des avis et des images. Ce contenu enrichi est accessible via un ensemble de modèles. Les modèles de contenu ne sont généralement pas créés directement par le développeur de l'application ; ils sont plutôt obtenus à partir des propriétés editorialModel, reviewModel et imageModel du type Place.

ListView {
    id:view
    property Place place
    signal showEditorial(var editorial)
    model: place.editorialModel
    delegate: EditorialDelegate {
        width: ListView.view.width
        onShowEditorial: view.showEditorial(model)
    }
}

Exemple de projet sur code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.