Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. How to dynamically add map objects to QML MAP element? Or how to create customised Map widget?

How to dynamically add map objects to QML MAP element? Or how to create customised Map widget?

Scheduled Pinned Locked Moved QML and Qt Quick
25 Posts 6 Posters 19.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    conny
    wrote on last edited by
    #5

    @
    // map_widget.cpp
    #include <QDebug>
    #include <QGeoServiceProvider>
    #include <QGeoMappingManager>
    #include <QGeoCoordinate>
    #include <QGeoMapCircleObject>
    #include <QGeoMapPixmapObject>
    #include <QGeoMapGroupObject>
    #include <QGraphicsSceneMouseEvent>
    #include <QGeoBoundingBox>
    #include <QtCore>

    #include "map_widget.h"

    // A widget for QML, therefore we need the parameter-less constructor.
    MapWidget::MapWidget() :
    QGraphicsGeoMap(createManager())
    {
    setCenter(QGeoCoordinate(51.05, 13.73));
    setZoomLevel(17);
    }

    MapWidget::~MapWidget()
    {
    }

    // This method is a bit a heck. We actually call it before the object
    // is completely created. We need to do this, because our parent class
    // needs a QGeoMappingManager passed to its constructor.
    QGeoMappingManager* MapWidget::createManager()
    {
    qDebug() << "INFO: Creating mapping manager";
    // We have to access this as static member, because we can't get anything
    // inside this object from the outside. The reason is, that this method
    // is called by the constructor and that we cannot add values to the
    // constructor, because QML always needs a parameter-less constructor.
    QGeoServiceProvider *serviceProvider = new QGeoServiceProvider("osm", params);
    QGeoMappingManager *mappingManager = serviceProvider->mappingManager();
    if (mappingManager == 0) {
    qDebug() << "WARN: Could not load 'osm' plugin. Falling back to 'nokia' plugin.";
    serviceProvider = new QGeoServiceProvider("nokia");
    mappingManager = serviceProvider->mappingManager();
    }

    return mappingManager;
    

    }

    void MapWidget::addPoi(PoiData *poi, bool active)
    {
    QGeoCoordinate coord(poi->getLat(), poi->getLon());

    QPixmap pixmap;
    if (active) {
        pixmap = QPixmap(":qml/Common/img/poi_active.png");
    } else {
        pixmap = QPixmap(":qml/Common/img/poi_inactive.png");
    }
    
    QGeoMapPixmapObject *pixMapObject = new QGeoMapPixmapObject(coord, QPoint(-26,-65), pixmap);
    pixMapObject->setProperty("uuid", poi->getUuid());
    pixMapObject->setObjectName("poiMarker");
    
    QGeoMapGroupObject *poiMarker = new QGeoMapGroupObject();
    poiMarker->setProperty("uuid", poi->getUuid());
    poiMarker->addChildObject(pixMapObject);
    
    if (active) {
        QGeoMapCircleObject *circle = new QGeoMapCircleObject(coord, poi->getRadius());
        circle->setPen(QPen((poiColor)));
        circle->setBrush(QBrush(poiColor));
        circle->setZValue(-1);
        poiMarker->addChildObject(circle);
    }
    
    addMapObject(poiMarker);
    

    }

    void MapWidget::removePoi(PoiData *poi)
    {
    for (int i = 0; i < poiMarkers.length(); ++i) {
    QGeoMapObject *marker = poiMarkers[i];
    if (marker->property("uuid").toString() == poi->getUuid()) {
    removeMapObject(marker);
    return;
    }
    }
    }

    void MapWidget::clearPois()
    {
    for (int i = 0; i < poiMarkers.length(); ++i) {
    QGeoMapObject *obj = poiMarkers[i];
    removeMapObject(obj);
    }
    }

    /*

    • Remember the position. We use this in mouseReleaseEvent
      /
      void MapWidget::mousePressEvent(QGraphicsSceneMouseEvent
      event)
      {
      lastPos = event->pos();
      }

    /*

    • If the mouse was moved by a maximum of 30px between press and release

    • we look at the press coordinates and if there is a POI we emit a signal

    • if there are several POIs, we only emit the signal for the first one.
      /
      void MapWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent
      event)
      {
      QPointF newPos = event->pos();
      QPointF diff = lastPos - newPos;

      if (qAbs(diff.x()) > 30 || qAbs(diff.y()) > 30) {
      return;
      }

      QList<QGeoMapObject*> objects = mapObjectsAtScreenPosition(lastPos);
      if (objects.length() > 0) {
      for (int i = 0; i < objects.length(); i++) {
      QGeoMapObject *obj = objects[i];
      if (obj->objectName() == "poiMarker") {
      QString uuid = obj->property("uuid").toString();
      emit poiClicked(uuid);
      }
      }
      }
      }

    void MapWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
    {
    // Round to int
    QPoint lastPos = event->lastPos().toPoint();
    QPoint pos = event->pos().toPoint();

    int dx = lastPos.x() - pos.x();
    int dy = lastPos.y() - pos.y();
    
    pan(dx, dy);
    setFollowPosition(false);
    

    }
    @

    1 Reply Last reply
    0
    • V Offline
      V Offline
      vcsala
      wrote on last edited by
      #6

      JuanF: please use @ tags around your code snippets to make it more readable (I have edited your posts in this thread)

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JuanF
        wrote on last edited by
        #7

        Hi Conny,

        Thank you very much!

        Your approach does work! I think for developers who need to use more complicated features than what qml location plugin offers, probably a custimised map widget which extends QGraphicsGeoMap is the best option.

        And it is also possible to develope own map widget, which subclasses QGraphicsWidget, by using QGeoMapData and QGeoMappingManager.

        Thanks again!

        Regards,
        Juan

        1 Reply Last reply
        0
        • C Offline
          C Offline
          conny
          wrote on last edited by
          #8

          You're welcome! I'm glad I could help :)

          1 Reply Last reply
          0
          • J Offline
            J Offline
            Jano
            wrote on last edited by
            #9

            Hi Conny and Juan,

            Would you just post som QML example how do you use tat MapWidget in QML. Im new in QML/Qt wold.

            Many Thanks

            1 Reply Last reply
            0
            • C Offline
              C Offline
              conny
              wrote on last edited by
              #10

              Hi Jano,

              if you're new with QML you should start by using the default map item. It has also much improved in QtM 1.2. Have a look here:
              http://doc.qt.nokia.com/qtmobility-1.2/declarative-location-mapviewer-mapviewer-qml.html

              1 Reply Last reply
              0
              • J Offline
                J Offline
                Jano
                wrote on last edited by
                #11

                Hi i tried your example.

                Map is succesfully created and pois are shown.. But im not receiving any mousevents.. :(

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  Jano
                  wrote on last edited by
                  #12

                  Actually, im getting mouse events only on device but no in Simulator. Did u have same issue?

                  Many Thanks!

                  1 Reply Last reply
                  0
                  • C Offline
                    C Offline
                    conny
                    wrote on last edited by
                    #13

                    I've not used the simulator for quite some time and currently still have only an old version installed, so I don't know. All I know is that you need at least QtM 1.2. If you have this and it's still not working I'd say it's a bug and you should report it.

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      Jano
                      wrote on last edited by
                      #14

                      Hi Conny,

                      I resolve issue. I'm gettin mouse events in simulator aswell.

                      Do you maybe know if is possible to add mapObject to the map so that onclick event can be handled?
                      Somehow extend QGeoMapObject?

                      Unfortunatelly method mapObjectsAtScreenPosition(lastPos) does not work on devices. I'm retreiving empty objects lists.

                      see bug: http://bugreports.qt.nokia.com/browse/QTMOBILITY-841?page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel

                      I have latest Qt SDK 1.1.2 and usign Qt Mobility 1.1

                      Many Thanks for your help

                      1 Reply Last reply
                      0
                      • C Offline
                        C Offline
                        conny
                        wrote on last edited by
                        #15

                        Yes you're right. Actually I've reported that bug. Unfortunately I don't know a way to get the mouse events on a devices with QtM < 1.2. I'm also waiting that QtM 1.2 will finally be available for devices.

                        On Maemo5 I've tested it with QtM 1.2 and it's actually working. On Symbian and for Ovi, we still have to wait :(

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          Jano
                          wrote on last edited by
                          #16

                          Conny,

                          Thaks again for your help. I resolved the issue.

                          I'm checking mapObjects boundingBox and check if contains clicked coordinate.

                          Regards

                          1 Reply Last reply
                          0
                          • C Offline
                            C Offline
                            conny
                            wrote on last edited by
                            #17

                            Sounds like a good work-around. Very nice!

                            Thanks for sharing!
                            Conny

                            1 Reply Last reply
                            0
                            • H Offline
                              H Offline
                              harbaum
                              wrote on last edited by
                              #18

                              Nice! I have also decided to give qml a try and of course are running into the same issues. I have started to make a minimal demo app from conny's example and would like to setup a wiki page or similar as i think we should document this a little bit, so others can re-use this.

                              1 Reply Last reply
                              0
                              • J Offline
                                J Offline
                                Jano
                                wrote on last edited by
                                #19

                                harabaum,

                                Please post link here, when u are done with demo :)

                                Regards

                                1 Reply Last reply
                                0
                                • H Offline
                                  H Offline
                                  harbaum
                                  wrote on last edited by
                                  #20

                                  Ok, "here":http://wiki.meego.com/QML/QGraphicsGeoMap is the wiki page. Please contribute your findings and let's try to make this into a small complete guide for this. I e.g. found that the map doesn't scale when the window size changes.

                                  1 Reply Last reply
                                  0
                                  • C Offline
                                    C Offline
                                    conny
                                    wrote on last edited by
                                    #21

                                    Thanks Till,
                                    what problems do you have with scaling? If I anchor the map to the QML root item and then scale the window the map size is increased. What's the result you get?

                                    1 Reply Last reply
                                    0
                                    • H Offline
                                      H Offline
                                      harbaum
                                      wrote on last edited by
                                      #22

                                      The map just doesn't scale with the window. These are my very first minutes with qml, so i may just be missing something. What do you e.g. mean by anchoring? Would you mind changing the appropriate parts in the wiki page?

                                      1 Reply Last reply
                                      0
                                      • C Offline
                                        C Offline
                                        conny
                                        wrote on last edited by
                                        #23

                                        Ah ok, just try this:

                                        @
                                        Rectangle {
                                        id: page
                                        anchors.fill: parent

                                        Map {
                                        anchors.fill: parent
                                        }
                                        }
                                        @

                                        Ok, now you won't see the rectangle anymore, but you get the point.

                                        1 Reply Last reply
                                        0
                                        • C Offline
                                          C Offline
                                          conny
                                          wrote on last edited by
                                          #24

                                          Also you might need the following in main.cpp:
                                          @
                                          view.setResizeMode(QDeclarativeView::SizeRootObjectToView);
                                          @

                                          That will always scale the root QML item to the size of the QDeclarativeView.

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved