Qt-based BB10 API Examples Documentation

Contents

Map View Example

Files:

Description

The Map View example displays a city map overlayed with three sliders that allow you to control altitude, tilt and heading. On top of this it demonstrates its main feature, which is the ability to drop push pins on chosen locations

Overview

In this example we'll learn how to use the MapView class of the BB10 framework to change altitude, tilt and heading in combination with the rotation sensor, as well as dropping push pins using MapData.

The UI

The UI of this sample application consists of a page with a MapView, several actions such as "Drop Pin", "Remove Pins", and some geographical location choices.

    ActionItem {
        title: qsTr("Drop Pin")
        imageSource: "asset:///images/pin.png"
        ActionBar.placement: ActionBarPlacement.OnBar
        onTriggered: {
            _mapViewTest.addPinAtCurrentMapCenter();
        }
    },
    ActionItem {
        title: qsTr("Remove Pins")
        imageSource: "asset:///images/clearpin.png"
        ActionBar.placement: ActionBarPlacement.OnBar
        onTriggered: {
            _mapViewTest.clearPins();
        }
    },
    ActionItem {
        title: qsTr("Center URL")
        imageSource: "asset:///images/url.png"
        ActionBar.placement: ActionBarPlacement.InOverflow
        onTriggered: {
            status.setText(mapview.url());
        }
    },
    ActionItem {
        title: qsTr("Waterloo")
        imageSource: "asset:///images/pin.png"
        ActionBar.placement: ActionBarPlacement.InOverflow
        onTriggered: {
            mapview.latitude = 43.468245;
            mapview.longitude = -80.519603;
        }
    },
    ActionItem {
        title: qsTr("Manhattan")
        imageSource: "asset:///images/pin.png"
        ActionBar.placement: ActionBarPlacement.InOverflow
        onTriggered: {
            mapview.latitude = 40.791556;
            mapview.longitude = -73.967394;
        }
    }

These actions provide ways to manipulate the map view by dropping pins, clearing them or going to a specific location such as Manhattan. These manipulations are done through longitude, latitude to drop them in the user focused area.

    MapView {
        id: mapview
        objectName: "mapViewObj"
        altitude: 3000
        latitude: 43.449488
        longitude: -80.406777
        preferredWidth: 768
        preferredHeight: 1280
        onAltitudeChanged: {
            alt.setText(qsTr("Alt: %1").arg(newAlt));
        }
        onHeadingChanged: {
            heading.setText(qsTr("Heading: %1\u00B0").arg(newHeading));
        }
        onLatitudeChanged: {
            lat.setText(qsTr("Lat: %1").arg(newLat));
        }
        onLongitudeChanged: {
            lon.setText(qsTr("Lon: %1").arg(newLon));
        }
        onTiltChanged: {
            tilt.setText(qsTr("Tilt: %1\u00B0").arg(newTilt));
        }
        onMapLongPressed: {
            status.setText(qsTr("map long pressed"));
        }

        onFollowedIdChanged: {
            status.setText(qsTr("followed id changed to %1").arg(idOfFollowed));
        }
        onFocusedIdChanged: {
            status.setText(qsTr("focused id changed to %1").arg(idWithFocus));
        }
        onCaptionButtonClicked: {
            status.setText(qsTr("button clicked %1").arg(focusedId));
        }
        onCaptionLabelTapped: {
            status.setText(qsTr("label clicked %1").arg(focusedId));
        }
        onLocationTapped: {
            status.setText(qsTr("location tapped %1").arg(id));
        }
        onLocationLongPressed: {
            status.setText(qsTr("location long pressed %1").arg(id));
        }
    }

The MapView element is set to the Waterloo, Ontario latitude,longitude location by default. The MapView events, such as latitude, longitude and heading changes update the appropriate labels to display their new values.

    Container {
        layout: StackLayout {
            orientation: LayoutOrientation.LeftToRight
        }
        horizontalAlignment: HorizontalAlignment.Center

Displays the status of the MapView element, such as current atlitude, tilt or latitude, longitude updates and some user actions.

    Container {
        leftPadding: 20
        rightPadding: 20
        bottomPadding: 20
        topPadding: 20
        horizontalAlignment: HorizontalAlignment.Right
        verticalAlignment: VerticalAlignment.Bottom
        overlapTouchPolicy: OverlapTouchPolicy.Allow

        ImageView {
            id: compassImage
            imageSource: "asset:///images/compass.png"
            horizontalAlignment: HorizontalAlignment.Center
            attachedObjects: [
                ImplicitAnimationController {
                    // Disable animations to avoid jumps between 0 and 360 degree
                    enabled: false
                }
            ]
        }
        ToggleButton {
            id: sensorToggle
            horizontalAlignment: HorizontalAlignment.Center
            checked: true
            onCheckedChanged: {
                if (checked) {
                    mapview.setFollowedId("device-location-id");
                } else {
                    mapview.setFollowedId("");
                }
            }
            onCreationCompleted: {
                mapview.setFollowedId("device-location-id");
            }
        }
    }
    Compass {
        property double azimuth: 0
        active: sensorToggle.checked
        axesOrientationMode: Compass.UserOrientation
        alwaysOn: false
        onReadingChanged: { // Called when a new compass reading is available
            mapview.setHeading(reading.azimuth);
            compassImage.rotationZ = 360 - reading.azimuth;
        }
    },

The Container that encapslates a compass image and ToggleButton. This allows us to show the compass positioning and the current map latitude/longitude of your gps location.

    RotationSensor {
        id: rotation
        property real x: 0
        active: sensorToggle.checked
        alwaysOn: false
        skipDuplicates: true
        onReadingChanged: {
            x = reading.x - 30
            if (x <= 40 && x > 0) {
                mapview.setTilt(x);
            }
        }
    },

The RotationSensor is used to determine the map tilt based on your handhelds rotation around the x-axis/y-axis.

        PositionSource {
            id: positionSource
            updateInterval: 1000
            active: sensorToggle.checked
            onPositionChanged: {
                _mapViewTest.updateDeviceLocation(positionSource.position.coordinate.latitude, positionSource.position.coordinate.longitude);
            }
        }

The PositionSource is used to update the graphical map pin that represents your current location when your position is changing.

MapViewDemo

This class deals with the adding and updating of location data for the MapData graphical elements.

    MapViewDemo::MapViewDemo(bb::cascades::Application *app)
        : QObject(app)
    {
        // create scene document from main.qml asset
        // set parent to created document to ensure it exists for the whole application lifetime
        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
        qml->setContextProperty("_mapViewTest", this);

        // create root object for the UI
        AbstractPane *root = qml->createRootObject<AbstractPane>();

        QObject* mapViewAsQObject = root->findChild<QObject*>(QString("mapViewObj"));
        if (mapViewAsQObject) {
            mapView = qobject_cast<bb::cascades::maps::MapView*>(mapViewAsQObject);
            mapView->setCaptionGoButtonVisible(true);
            if (mapView) {
                // creating a data provider just for the device location object. that way, when the clear function is call, this object is not removed.
                DataProvider* deviceLocDataProv = new DataProvider("device-location-data-provider");
                mapView->mapData()->addProvider(deviceLocDataProv);

                // create a geolocation just for the device's location
                deviceLocation = new GeoLocation("device-location-id");
                deviceLocation->setName("Current Device Location");
                deviceLocation->setDescription("<html><a href=\"http://www.blackberry.com\">Hyperlinks</a> are super useful in bubbles.</html>");

                // for that location, replace the standard default pin with the provided bulls eye asset
                Marker bullseye = Marker(UIToolkitSupport::absolutePathFromUrl(
                                    QUrl("asset:///images/me.png")), QSize(60, 60),
                                    QPoint(29, 29), QPoint(29, 1));
                deviceLocation->setMarker(bullseye);

                deviceLocDataProv->add(deviceLocation);
            }
        }

        // set created root object as a scene
        app->setScene(root);
    }

Inside the constructor of the class we create a seperate DataProvider to contain our current location. The reason for this is to seperate the provider containing our location from the default one that contains other location elements we decide to add on the map, so that it may be easier to clear these markers without clearing our location. We also create the Marker which will represent the graphical current position on the map, which is added to the this DataProvider.

    void MapViewDemo::addPinAtCurrentMapCenter() {
        if (mapView) {
            GeoLocation* newDrop = new GeoLocation();
            newDrop->setLatitude(mapView->latitude());
            newDrop->setLongitude(mapView->longitude());
            QString desc = QString("Coordinates: %1, %2").arg(mapView->latitude(),
                                    0, 'f', 3).arg(mapView->longitude(), 0, 'f', 3);
            newDrop->setName("Dropped Pin");
            newDrop->setDescription(desc);

            // use the marker in the assets, as opposed to the default marker
            Marker flag;
            flag.setIconUri(UIToolkitSupport::absolutePathFromUrl(
                            QUrl("asset:///images/on_map_pin.png")));
            flag.setIconSize(QSize(60, 60));
            flag.setLocationCoordinate(QPoint(20, 59));
            flag.setCaptionTailCoordinate(QPoint(20, 1));
            newDrop->setMarker(flag);

            mapView->mapData()->add(newDrop);
        }
    }

The addPinAtCurrentMapCenter method creates GeoLocation instances, with set latitude/longitude values, and corresponding graphical Marker's to graphically represent the current map center. By adding this to the default MapData, they show up on in our MapView.

    void MapViewDemo::clearPins() {
        if (mapView) {
            // this will remove all pins, except the "device location" pin, as it's in a different data provider
            mapView->mapData()->defaultProvider()->clear();
        }
    }

The clearPins() method illustrates how to remove all the Marker's associated with a perticular DataProvider. You can group your Marker's with different DataProvider's to be able to manipulate subsets of Marker's depending on functionality.