Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding markers/places to Qt QML Maps?

Tags:

c++

qt

qt5

qml

Good day ! I am designing a Qt-based GUI platform that displays a map and allows users to add markers/pins on top of the map.

I am rendering the map in a QtQuickWidget using the following QML:

Plugin {
    id: mapPlugin
    name: "osm"
}

I want to allow the user to add an interactive pin on the map using a button on a form. The user can press and hold a point on the map which will open the form, where the user can name the place and press OK.

Example of interactive pin

Example of what I want to achieve: https://webmshare.com/play/5EXV8


  1. I have tried using QQmlComponent and QQuickView but I was unsuccessful [http://doc.qt.io/qt-5/qtqml-cppintegration-interactqmlfromcpp.html]

  2. Another way is to add objects within QML itself using MapItems but this is very unintuitive. This is what my map.qml looks like: https://gist.github.com/blackvitriol/7941688d6362162888630a28c79f8cd9

Project Structure: https://imgur.com/a/P8YAS

Can someone tell me how to allow the user to press and hold left click on the map, then add a marker to that point ?

like image 969
Ahmad M. Avatar asked Mar 07 '23 15:03

Ahmad M.


1 Answers

A possible solution is to use MapItemView and create a model that stores the coordinates:

markermodel.h

#ifndef MARKERMODEL_H
#define MARKERMODEL_H

#include <QAbstractListModel>
#include <QGeoCoordinate>

class MarkerModel : public QAbstractListModel
{
    Q_OBJECT

public:
    using QAbstractListModel::QAbstractListModel;
    enum MarkerRoles{positionRole = Qt::UserRole + 1};

    Q_INVOKABLE void addMarker(const QGeoCoordinate &coordinate){
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_coordinates.append(coordinate);
        endInsertRows();
    }

    int rowCount(const QModelIndex &parent = QModelIndex()) const override{
        Q_UNUSED(parent)
        return m_coordinates.count();
    }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
        if (index.row() < 0 || index.row() >= m_coordinates.count())
            return QVariant();
        if(role== MarkerModel::positionRole)
            return QVariant::fromValue(m_coordinates[index.row()]);
        return QVariant();
    }

    QHash<int, QByteArray> roleNames() const{
        QHash<int, QByteArray> roles;
        roles[positionRole] = "position";
        return roles;
    }

private:
    QList<QGeoCoordinate> m_coordinates;
};

#endif // MARKERMODEL_H

main.qml

import QtQuick 2.0
import QtLocation 5.6
import QtPositioning 5.6
import QtQuick.Window 2.0

Rectangle {
    width: Screen.width
    height: Screen.height
    visible: true

    Plugin {
        id: mapPlugin
        name: "osm"
    }

    Map {
        id: mapview
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(59.91, 10.75)
        zoomLevel: 14

        MapItemView{
            model: markerModel
            delegate: mapcomponent
        }
    }

    Component {
        id: mapcomponent
        MapQuickItem {
            id: marker
            anchorPoint.x: image.width/4
            anchorPoint.y: image.height
            coordinate: position

            sourceItem: Image {
                id: image
                source: "http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"
            }
        }
    }

    MouseArea {
        anchors.fill: parent

        onPressAndHold:  {
            var coordinate = mapview.toCoordinate(Qt.point(mouse.x,mouse.y))
            markerModel.addMarker(coordinate)
        }
    }
}

main.cpp

#include "markermodel.h"

#include <QApplication>
#include <QQuickWidget>
#include <QQmlContext>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QQuickWidget w;
    MarkerModel model;
    w.rootContext()->setContextProperty("markerModel", &model);
    w.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
    w.show();

    return a.exec();
}

enter image description here

The complete example can be found in the following link.

like image 176
eyllanesc Avatar answered Mar 14 '23 22:03

eyllanesc