display multiple routes on a map using RouteMap QML Qt - qt

I want to display a list of routes on a map using Qt Location properties, I was able to display one route, but I don't know how to display multiple ones. Here's my code:
RouteModel {
id: routeModel
plugin: somePlugin
query: RouteQuery {}
Component.onCompleted: {
query.addWaypoint(QtPositioning.coordinate(26.328045523310905, 50.080033033011546));
query.addWaypoint(QtPositioning.coordinate(26.333615791655415, 50.097984054173025));
routeModel.update();
query.addWaypoint(QtPositioning.coordinate(26.291584, 50.199094));
query.addWaypoint(QtPositioning.coordinate(26.288128, 50.188725));
routeModel.update();
}
onStatusChanged: console.debug("current route model status", status, count, errorString)
}
I wish for each couple of addWayPoints to be a distinct route. How canI achieve that?
I added multiple models with their correspondent mapitemview, still it didn't work.
RouteModel {
id: routeModel
plugin: somePlugin
query: RouteQuery {}
Component.onCompleted: {
query.addWaypoint(QtPositioning.coordinate(26.328045523310905, 50.080033033011546));
query.addWaypoint(QtPositioning.coordinate(26.333615791655415, 50.097984054173025));
routeModel.update();
}
}
RouteModel {
id: rm
plugin: somePlugin
query: RouteQuery {}
Component.onCompleted: {
query.addWaypoint(QtPositioning.coordinate(26.291584, 50.199094));
query.addWaypoint(QtPositioning.coordinate(26.288128, 50.188725));
rm.update();
}
}
RouteModel {
id: rm1
plugin: somePlugin
query: RouteQuery {}
Component.onCompleted: {
query.addWaypoint(QtPositioning.coordinate(26.278496, 50.203740));
query.addWaypoint(QtPositioning.coordinate(26.272351, 50.185939));
rm.update();
}
}
Map {
id: map
anchors.fill: parent
plugin: somePlugin
center: magione
gesture.enabled: true
zoomLevel: 13
MapItemView {
model: routeModel
delegate: MapRoute {
route: routeData
line.color: "blue"
line.width: 5
smooth: true
}
}
MapItemView {
model: rm
delegate: MapRoute {
route: routeData1
line.color: "green"
line.width: 5
smooth: true
}
}
MapItemView {
model: rm2
delegate: MapRoute {
route: routeData2
line.color: "black"
line.width: 5
smooth: true
}
}
}

I was just trying to do the same task, just accomplished IT. As in your first attempt, you should add multiple addWayPoints, but update the model only once at the end. Here is an example of a route visiting the following places A->B->C->A
Component.onCompleted:
{
query.addWaypoint(QtPositioning.coordinate(-25.402340, -49.248682));
query.addWaypoint(QtPositioning.coordinate(-25.392142, -49.202556));
query.addWaypoint(QtPositioning.coordinate(-25.372512, -49.227785));
query.addWaypoint(QtPositioning.coordinate(-25.402340, -49.248682));
routeModel.update();
}
Results in: Multiple routes:
Just wondering now how do I get pinpoints at each route stoppoint.

Showing all routes returned from a query normally works out of the box (assuming the plugin you are using gives you more than one result per route request).
If you want to simultaneously display routes for multiple requests, you need one model/view per request you want to simultaneously display
I finish pointing out that, in your example, you are using the model roles wrong.
There is no such routeData1 or routeData2, but only routeData, and you should use this role every time you try to access the route data from a route model.

Related

Route doesn't show

By following a part of this example
display multiple routes on a map using RouteMap QML Qt
I'm trying to show a route inside a MapView in a QML view of my QT application, by using the following code; but the route don't appear. No errors are appearing in the output console. Did I do something wrong?
Map {
anchors.fill: parent
plugin: mapboxglPlugin
center: QtPositioning.coordinate(60.170448, 24.942046) // Oslo
zoomLevel: 16
id: mapMain
copyrightsVisible: false
RouteModel {
id: rm
plugin: mapboxglPlugin
query: RouteQuery {id: routeQuery }
Component.onCompleted: {
routeQuery.addWaypoint(QtPositioning.coordinate(60.170448, 24.942046));
routeQuery.addWaypoint(QtPositioning.coordinate(62.170448, 23.942046));
update();
}
}
MapItemView {
model: rm
delegate: Component{
MapRoute {
route: routeData
line.color: "green"
line.width: 5
smooth: true
}
}
}
}

How to drag multiple targets on a map?

I wanted to implement a function that users can drag the marker (which is defined as MapQuickItem) on the map and automatically change its path (which is defined as MapPolyline). Currently I can only drag the marker but don't know how to change its path.
If I want to define a DropArea under the Map and call the MapPolyline.removeCoordinate() function to change the path, how to visit the index in the delegate? And I'm not sure if this idea will work.
Here is the code:
Map {
id: map
anchors.fill: parent
plugin: mapPlugin
zoomLevel: 14
activeMapType: supportedMapTypes[7]
/* maker */
MouseArea {
anchors.fill: parent
onClicked: {
var crd = map.toCoordinate(Qt.point(mouseX, mouseY))
console.log(crd)
markerModel.append({ "latitude": crd.latitude, "longitude": crd.longitude})
line.addCoordinate(crd)
}
}
MapItemGroup {
MapPolyline {
id: line
line.width: 3
line.color: "#515151"
}
MapItemView {
add: Transition {}
remove: Transition {}
model: ListModel {
id: markerModel
}
delegate:
MapQuickItem {
id: marker
coordinate: QtPositioning.coordinate(latitude, longitude)
anchorPoint: Qt.point(markerImage.width * 0.5, markerImage.height * 0.5)
sourceItem: Image {
id: markerImage
z: 5
width: 30
height: 30
source: index <= 0 ? "Images/starting point.svg" : "Images/point black.svg"
MouseArea {
anchors.fill: parent
onClicked: {
line.removeCoordinate(index);
markerModel.remove(index);
}
drag.target: marker
}
}
}
/* maker */
}
}
}
I have tried several methods to solve the problem.
This method is not feasible cos the event (drag.onActiveChanged) is triggered only at the moment that the drag event happens.
drag.onActiveChanged: {
if(mouseArea.drag.active) {
line.replaceCoordinate(index, marker.coordinate);
}
}
I tried to define a DropArea under the Map and called the drag.ondragStarted() function to trigger the event, but I didn't figure out how to visit the index in the delegate, then I gave up.
It worked! When I dragged the marker on the map, the path automatically changed! The event (onPositionChanged) is triggered everytime the coordinate of marker changes.
onPositionChanged: {
line.replaceCoordinate(index, marker.coordinate);
}
Thank myself :-)

How to put MouseArea inside buildings boundaries in QML Map

I'm trying to make buildings on map clickable using MouseArea. I tried using GeocodeModel with query "building" which was obviously stupid idea. Then I tried getting mapItems : list of Map Object and printing them on the console, but that: "qml: Map items: []" was the only result. Now I'm thinking if it is even possible without going into implementation side of maybe delegate of Map if such thing exists :P Why there is nothing in mapItems ? Are they in some way private in Map ?
My shortened code:
Window {
visible: true
width: 640
height: 480
Map {
id: map
anchors.fill: parent
plugin: Plugin{
name: "osm"
}
zoomLevel: 15
Component.onCompleted: {
console.log("Map items: ", map.mapItems);
}
}
GeocodeModel{
id: geoModel
plugin: Plugin{
name: "osm"
}
autoUpdate: true
query: "building"
limit: -1
onLocationsChanged: {
map.center = geoModel.get(0).coordinate
console.log(count);
}
}

Get model index from MapItemView

I am trying to build an interactive map application which allow me to add and modify Map Items. I am able to add new map item but I still have problem to modify the model. On the code below, if I have more than one item, the remove function always delete the first item crated not the current item selected. I want to modify the model not only the view of the model, but how can I get the currentIndex of the model ?
ListModel {
id: mapModel
}
Map {
id: map
//...
MapItemView {
model: mapModel
delegate: MapCircle {
radius: 80000
color: 'blue'
center {
latitude: lat
longitude: longi
}
MouseArea {
onClicked: {
mapModel.remove(model.index)
}
}
}
}
MouseArea {
anchors.fill: parent
onClicked: {
var coord = map.toCoordinate(Qt.point(mouse.x,mouse.y))
mapModel.append({lat : coord.latitude, longi: coord.longitude});
}
}
}
Found the answer myself. Just use mapModel.remove(index) instead of mapModel.remove(model.index)

selecting delegates depending on property

I have a listview where I want to use either a defaultDelegate or a customDelegate depending on the value of a property.
So far I've tried using a component to load the different delegates:
Component{
id: delegate
Loader {
sourceComponent: type == 3 ? customDelegate : defaultDelegate
}
}
However, I can't access the properties I have in my model from the two delegates I have. I have the following error:
ReferenceError: name is not defined
Here is the model I use:
ListModel {
id: test
ListElement {
name: "Bill"
team: "554"
type: 2
}
ListElement {
name: "John"
team: "555"
type: 3
}
ListElement {
name: "Sam"
team: "556"
type: 1
}
}
Does anyone Have any idea, what I am doing wrong here?
It is, of course, a context problem. In your code, the name, team and type context properties inserted by the ListView into delegate's context is inaccessible to the components inside your delegates, as the Loader uses the creation context of customDelegate and defaultDelegate as the parent context when instantiating them, and name, team and type do not refer to anything withing that context chain.
One solution is to explicitly set the required information as a property of the Loader (this works because the Loader sets itself as the context object for the component it is loading).
Following a working example:
ListModel {
id: testModel
ListElement {
name: "Bill"
team: "554"
type: 2
}
ListElement {
name: "John"
team: "555"
type: 3
}
ListElement {
name: "Sam"
team: "556"
type: 1
}
}
ListView {
anchors.fill: parent
model: testModel
delegate: myDelegate
}
Component {
id: myDelegate // yourDelegate
Loader {
property string modelName: model.name
property string modelTeam: model.team
property int modelType: model.type
sourceComponent: modelType === 3 ? colonDelegate : semicolonDelegate
}
}
Component {
id: colonDelegate
Text { text: modelName + ": " + modelTeam }
}
Component {
id: semicolonDelegate
Text { text: modelName + "; " + modelTeam }
}
For further reading and improvements I highly recommend you to read this.

Resources