static QString boundingBoxToLtrb(const QGeoRectangle &rect)
{
    return QString::number(rect.topLeft().longitude()) + QLatin1Char(',') +
           QString::number(rect.topLeft().latitude()) + QLatin1Char(',') +
           QString::number(rect.bottomRight().longitude()) + QLatin1Char(',') +
           QString::number(rect.bottomRight().latitude());
}
示例#2
0
void tst_QGeoLocation::isEmpty()
{
    QGeoAddress address;
    address.setCity(QStringLiteral("Braunschweig"));
    QVERIFY(!address.isEmpty());

    QGeoRectangle boundingBox;
    boundingBox.setTopLeft(QGeoCoordinate(1, -1));
    boundingBox.setBottomRight(QGeoCoordinate(-1, 1));
    QVERIFY(!boundingBox.isEmpty());

    QGeoLocation location;

    QVERIFY(location.isEmpty());

    // address
    location.setAddress(address);
    QVERIFY(!location.isEmpty());
    location.setAddress(QGeoAddress());
    QVERIFY(location.isEmpty());

    // coordinate
    location.setCoordinate(QGeoCoordinate(1, 2));
    QVERIFY(!location.isEmpty());
    location.setCoordinate(QGeoCoordinate());
    QVERIFY(location.isEmpty());

    // bounding box
    location.setBoundingBox(boundingBox);
    QVERIFY(!location.isEmpty());
    location.setBoundingBox(QGeoRectangle());
    QVERIFY(location.isEmpty());
}
示例#3
0
/*!
    Returns whether the geo rectangle \a rectangle is contained within this
    geo rectangle.
*/
bool QGeoRectangle::contains(const QGeoRectangle &rectangle) const
{
    Q_D(const QGeoRectangle);

    return (d->contains(rectangle.topLeft())
            && d->contains(rectangle.topRight())
            && d->contains(rectangle.bottomLeft())
            && d->contains(rectangle.bottomRight()));
}
void QDeclarativeGeoMap::fitViewportToGeoShape()
{
    double bboxWidth;
    double bboxHeight;
    QGeoCoordinate centerCoordinate;

    switch (m_region.type()) {
    case QGeoShape::RectangleType:
    {
        QGeoRectangle rect = m_region;
        QDoubleVector2D topLeftPoint = m_map->coordinateToItemPosition(rect.topLeft(), false);
        QDoubleVector2D botRightPoint = m_map->coordinateToItemPosition(rect.bottomRight(), false);
        bboxWidth = qAbs(topLeftPoint.x() - botRightPoint.x());
        bboxHeight = qAbs(topLeftPoint.y() - botRightPoint.y());
        centerCoordinate = rect.center();
        break;
    }
    case QGeoShape::CircleType:
    {
        QGeoCircle circle = m_region;
        centerCoordinate = circle.center();
        QGeoCoordinate edge = centerCoordinate.atDistanceAndAzimuth(circle.radius(), 90);
        QDoubleVector2D centerPoint = m_map->coordinateToItemPosition(centerCoordinate, false);
        QDoubleVector2D edgePoint = m_map->coordinateToItemPosition(edge, false);
        bboxWidth = qAbs(centerPoint.x() - edgePoint.x()) * 2;
        bboxHeight = bboxWidth;
        break;
    }
    case QGeoShape::UnknownType:
        //Fallthrough to default
    default:
        return;
    }

    // position camera to the center of bounding box
    setProperty("center", QVariant::fromValue(centerCoordinate));

    //If the shape is empty we just change centerposition, not zoom
    if (bboxHeight == 0 && bboxWidth == 0)
        return;

    // adjust zoom
    double bboxWidthRatio = bboxWidth / (bboxWidth + bboxHeight);
    double mapWidthRatio = width() / (width() + height());
    double zoomRatio;

    if (bboxWidthRatio > mapWidthRatio)
        zoomRatio = bboxWidth / width();
    else
        zoomRatio = bboxHeight / height();

    qreal newZoom = std::log10(zoomRatio) / std::log10(0.5);

    newZoom = std::floor(qMax(minimumZoomLevel(), (m_map->mapController()->zoom() + newZoom)));
    setProperty("zoomLevel", QVariant::fromValue(newZoom));
}
/*
    This property holds the width of this georectangle (in degrees).
*/
void GeoRectangleValueType::setWidth(double width)
{
    QGeoRectangle r = v;

    if (!r.isValid())
        r.setCenter(QGeoCoordinate(0.0, 0.0));

    r.setWidth(width);
    v = r;
}
/*
    This property holds the height of this georectangle (in degrees).
*/
void GeoRectangleValueType::setHeight(double height)
{
    QGeoRectangle r = v;

    if (!r.isValid())
        r.setCenter(QGeoCoordinate(0.0, 0.0));

    r.setHeight(height);
    v = r;
}
/*
    This property holds the center coordinate of this georectangle.
*/
void GeoRectangleValueType::setCenter(const QGeoCoordinate &coordinate)
{
    QGeoRectangle r = v;

    if (r.center() == coordinate)
        return;

    r.setCenter(coordinate);
    v = r;
}
/*
    This property holds the top right coordinate of this georectangle.
*/
void GeoRectangleValueType::setTopRight(QGeoCoordinate &coordinate)
{
    QGeoRectangle r = v;

    if (r.topRight() == coordinate)
        return;

    r.setTopRight(coordinate);
    v = r;
}
/*
    This property holds the bottom right coordinate of this georectangle.
*/
void GeoRectangleValueType::setBottomRight(const QGeoCoordinate &coordinate)
{
    QGeoRectangle r = v;

    if (r.bottomRight() == coordinate)
        return;

    r.setBottomRight(coordinate);
    v = r;
}
QString GeoRectangleValueType::toString() const
{
    if (v.type() != QGeoShape::RectangleType) {
        qWarning("Not a rectangle a %d\n", v.type());
        return QStringLiteral("QGeoRectangle(not a rectangle)");
    }

    QGeoRectangle r = v;
    return QStringLiteral("QGeoRectangle({%1, %2}, {%3, %4})")
        .arg(r.topLeft().latitude())
        .arg(r.topLeft().longitude())
        .arg(r.bottomRight().latitude())
        .arg(r.bottomRight().longitude());
}
示例#11
0
/*!
    Returns whether the geo rectangle \a rectangle intersects this geo rectangle.

    If the top or bottom edges of both geo rectangles are at one of the poles
    the geo rectangles are considered to be intersecting, since the longitude
    is irrelevant when the edges are at the pole.
*/
bool QGeoRectangle::intersects(const QGeoRectangle &rectangle) const
{
    Q_D(const QGeoRectangle);

    double left1 = d->topLeft.longitude();
    double right1 = d->bottomRight.longitude();
    double top1 = d->topLeft.latitude();
    double bottom1 = d->bottomRight.latitude();

    double left2 = rectangle.d_func()->topLeft.longitude();
    double right2 = rectangle.d_func()->bottomRight.longitude();
    double top2 = rectangle.d_func()->topLeft.latitude();
    double bottom2 = rectangle.d_func()->bottomRight.latitude();

    if (top1 < bottom2)
        return false;

    if (bottom1 > top2)
        return false;

    if ((top1 == 90.0) && (top1 == top2))
        return true;

    if ((bottom1 == -90.0) && (bottom1 == bottom2))
        return true;

    if (left1 < right1) {
        if (left2 < right2) {
            if ((left1 > right2) || (right1 < left2))
                return false;
        } else {
            if ((left1 > right2) && (right1 < left2))
                return false;
        }
    } else {
        if (left2 < right2) {
            if ((left2 > right1) && (right2 < left1))
                return false;
        } else {
            // if both wrap then they have to intersect
        }
    }

    return true;
}
QDataStream &operator<<(QDataStream &stream, const QGeoShape &shape)
{
    stream << quint32(shape.type());
    switch (shape.type()) {
    case QGeoShape::UnknownType:
        break;
    case QGeoShape::RectangleType: {
        QGeoRectangle r = shape;
        stream << r.topLeft() << r.bottomRight();
        break;
    }
    case QGeoShape::CircleType: {
        QGeoCircle c = shape;
        stream << c.center() << c.radius();
        break;
    }
    }

    return stream;
}
示例#13
0
void QGeoCodeReplyOsm::networkReplyFinished()
{
    if (!m_reply)
        return;

    if (m_reply->error() != QNetworkReply::NoError)
        return;

    QList<QGeoLocation> locations;
    QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());

    if (document.isObject()) {
        QJsonObject object = document.object();

        QGeoCoordinate coordinate;

        coordinate.setLatitude(object.value(QStringLiteral("lat")).toString().toDouble());
        coordinate.setLongitude(object.value(QStringLiteral("lon")).toString().toDouble());

        QGeoLocation location;
        location.setCoordinate(coordinate);
        location.setAddress(parseAddressObject(object));

        locations.append(location);

        setLocations(locations);
    } else if (document.isArray()) {
        QJsonArray results = document.array();

        for (int i = 0; i < results.count(); ++i) {
            if (!results.at(i).isObject())
                continue;

            QJsonObject object = results.at(i).toObject();

            QGeoCoordinate coordinate;

            coordinate.setLatitude(object.value(QStringLiteral("lat")).toString().toDouble());
            coordinate.setLongitude(object.value(QStringLiteral("lon")).toString().toDouble());

            QGeoRectangle rectangle;

            if (object.contains(QStringLiteral("boundingbox"))) {
                QJsonArray a = object.value(QStringLiteral("boundingbox")).toArray();
                if (a.count() == 4) {
                    rectangle.setTopLeft(QGeoCoordinate(a.at(1).toString().toDouble(),
                                                        a.at(2).toString().toDouble()));
                    rectangle.setBottomRight(QGeoCoordinate(a.at(0).toString().toDouble(),
                                                            a.at(3).toString().toDouble()));
                }
            }

            QGeoLocation location;
            location.setCoordinate(coordinate);
            location.setBoundingBox(rectangle);
            location.setAddress(parseAddressObject(object));
            locations.append(location);
        }

    }

    setLocations(locations);
    setFinished(true);

    m_reply->deleteLater();
    m_reply = 0;
}
示例#14
0
void QGeoCodeReplyQGC::networkReplyFinished()
{
    if (!m_reply)
        return;

    if (m_reply->error() != QNetworkReply::NoError)
        return;

    QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());
    QJsonObject object = document.object();

    if (object.value(QStringLiteral("status")) != QStringLiteral("OK")) {
        QString error = object.value(QStringLiteral("status")).toString();
        qWarning() << m_reply->url() << "returned" << error;
        setError(QGeoCodeReply::CommunicationError, error);
        m_reply->deleteLater();
        m_reply = 0;
        return;
    }

    QList<QGeoLocation> locations;
    QJsonArray results = object.value(QStringLiteral("results")).toArray();
    for (int i=0; i<results.size(); ++i) {
        if (!results[i].isObject())
            continue;

        QJsonObject geocode = results[i].toObject();

        QGeoAddress address;
        if (geocode.contains(QStringLiteral("formatted_address"))) {
            address.setText(geocode.value(QStringLiteral("formatted_address")).toString());
        }


        if (geocode.contains(QStringLiteral("address_components"))) {
            QJsonArray ac = geocode.value(QStringLiteral("address_components")).toArray();

            for (int j=0; j<ac.size(); ++j) {
                if (!ac[j].isObject())
                    continue;

                QJsonObject c = ac[j].toObject();
                if (!c.contains(QStringLiteral("types")))
                    continue;

                QSet<int> types = kMonger.json2QGCGeoCodeType(c[QStringLiteral("types")].toArray());
                QString long_name = c[QStringLiteral("long_name")].toString();
                QString short_name = c[QStringLiteral("short_name")].toString();
                if (types.contains(Country)) {
                    address.setCountry(long_name);
                    address.setCountryCode(short_name);
                } else if (types.contains(AdministrativeAreaLevel1)) {
                    address.setState(long_name);
                } else if (types.contains(AdministrativeAreaLevel2)) {
                    address.setCounty(long_name);
                } else if (types.contains(Locality)) {
                    address.setCity(long_name);
                } else if (types.contains(Sublocality)) {
                    address.setDistrict(long_name);
                } else if (types.contains(PostalCode)) {
                    address.setPostalCode(long_name);
                } else if (types.contains(StreetAddress) || types.contains(Route) || types.contains(Intersection)) {
                    address.setStreet(long_name);
                }
            }
        }

        QGeoCoordinate coordinate;
        QGeoRectangle boundingBox;
        if (geocode.contains(QStringLiteral("geometry"))) {
            QJsonObject geom = geocode.value(QStringLiteral("geometry")).toObject();
            if (geom.contains(QStringLiteral("location"))) {
                QJsonObject location = geom.value(QStringLiteral("location")).toObject();
                coordinate.setLatitude(location.value(QStringLiteral("lat")).toDouble());
                coordinate.setLongitude(location.value(QStringLiteral("lng")).toDouble());
            }
            if (geom.contains(QStringLiteral("bounds"))) {
                QJsonObject bounds = geom.value(QStringLiteral("bounds")).toObject();
                QJsonObject northeast = bounds.value(QStringLiteral("northeast")).toObject();
                QJsonObject southwest = bounds.value(QStringLiteral("southwest")).toObject();
                QGeoCoordinate topRight(northeast.value(QStringLiteral("lat")).toDouble(),
                                        northeast.value(QStringLiteral("lng")).toDouble());
                QGeoCoordinate bottomLeft(southwest.value(QStringLiteral("lat")).toDouble(),
                                          southwest.value(QStringLiteral("lng")).toDouble());
                boundingBox.setTopRight(topRight);
                boundingBox.setBottomLeft(bottomLeft);
            }
        }

        QGeoLocation location;
        location.setAddress(address);
        location.setCoordinate(coordinate);
        location.setBoundingBox(boundingBox);

        locations << location;
    }

    setLocations(locations);
    setFinished(true);

    m_reply->deleteLater();
    m_reply = 0;
}
QPlaceSearchReply *QPlaceManagerEngineOsm::search(const QPlaceSearchRequest &request)
{
    bool unsupported = false;

    // Only public visibility supported
    unsupported |= request.visibilityScope() != QLocation::UnspecifiedVisibility &&
                   request.visibilityScope() != QLocation::PublicVisibility;
    unsupported |= request.searchTerm().isEmpty() && request.categories().isEmpty();

    if (unsupported)
        return QPlaceManagerEngine::search(request);

    QUrlQuery queryItems;

    queryItems.addQueryItem(QStringLiteral("format"), QStringLiteral("jsonv2"));

    //queryItems.addQueryItem(QStringLiteral("accept-language"), QStringLiteral("en"));

    QGeoRectangle boundingBox;
    QGeoShape searchArea = request.searchArea();
    switch (searchArea.type()) {
    case QGeoShape::CircleType: {
        QGeoCircle c(searchArea);
        qreal radius = c.radius();
        if (radius < 0)
            radius = 50000;

        boundingBox = QGeoRectangle(c.center().atDistanceAndAzimuth(radius, -45),
                                    c.center().atDistanceAndAzimuth(radius, 135));
        break;
    }
    case QGeoShape::RectangleType:
        boundingBox = searchArea;
        break;
    default:
        ;
    }

    if (!boundingBox.isEmpty()) {
        queryItems.addQueryItem(QStringLiteral("bounded"), QStringLiteral("1"));
        QString coordinates;
        coordinates = QString::number(boundingBox.topLeft().longitude()) + QLatin1Char(',') +
                      QString::number(boundingBox.topLeft().latitude()) + QLatin1Char(',') +
                      QString::number(boundingBox.bottomRight().longitude()) + QLatin1Char(',') +
                      QString::number(boundingBox.bottomRight().latitude());
        queryItems.addQueryItem(QStringLiteral("viewbox"), coordinates);
    }

    QStringList queryParts;
    if (!request.searchTerm().isEmpty())
        queryParts.append(request.searchTerm());

    foreach (const QPlaceCategory &category, request.categories()) {
        QString id = category.categoryId();
        int index = id.indexOf(QLatin1Char('='));
        if (index != -1)
            id = id.mid(index+1);
        queryParts.append(QLatin1Char('[') + id + QLatin1Char(']'));
    }

    queryItems.addQueryItem(QStringLiteral("q"), queryParts.join(QLatin1Char('+')));

    QVariantMap parameters = request.searchContext().toMap();

    QStringList placeIds = parameters.value(QStringLiteral("ExcludePlaceIds")).toStringList();
    if (!placeIds.isEmpty())
        queryItems.addQueryItem(QStringLiteral("exclude_place_ids"), placeIds.join(QLatin1Char(',')));

    queryItems.addQueryItem(QStringLiteral("addressdetails"), QStringLiteral("1"));

    QUrl requestUrl(m_urlPrefix);
    requestUrl.setQuery(queryItems);

    QNetworkReply *networkReply = m_networkManager->get(QNetworkRequest(requestUrl));

    QPlaceSearchReplyOsm *reply = new QPlaceSearchReplyOsm(request, networkReply, this);
    connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
    connect(reply, SIGNAL(error(QPlaceReply::Error,QString)),
            this, SLOT(replyError(QPlaceReply::Error,QString)));

    return reply;
}
示例#16
0
/*!
    \qmlmethod QtLocation::Map::fitViewportToGeoShape(QGeoShape shape)

    Fits the current viewport to the boundary of the shape. The camera is positioned
    in the center of the shape, and at the largest integral zoom level possible which
    allows the whole shape to be visible on screen

*/
void QDeclarativeGeoMap::fitViewportToGeoShape(const QVariant &variantShape)
{
    if (!map_ || !mappingManagerInitialized_)
        return;

    QGeoShape shape;

    if (variantShape.userType() == qMetaTypeId<QGeoRectangle>())
        shape = variantShape.value<QGeoRectangle>();
    else if (variantShape.userType() == qMetaTypeId<QGeoCircle>())
        shape = variantShape.value<QGeoCircle>();
    else if (variantShape.userType() == qMetaTypeId<QGeoShape>())
        shape = variantShape.value<QGeoShape>();

    if (!shape.isValid())
        return;

    double bboxWidth;
    double bboxHeight;
    QGeoCoordinate centerCoordinate;

    switch (shape.type()) {
    case QGeoShape::RectangleType:
    {
        QGeoRectangle rect = shape;
        QDoubleVector2D topLeftPoint = map_->coordinateToScreenPosition(rect.topLeft(), false);
        QDoubleVector2D botRightPoint = map_->coordinateToScreenPosition(rect.bottomRight(), false);
        bboxWidth = qAbs(topLeftPoint.x() - botRightPoint.x());
        bboxHeight = qAbs(topLeftPoint.y() - botRightPoint.y());
        centerCoordinate = rect.center();
        break;
    }
    case QGeoShape::CircleType:
    {
        QGeoCircle circle = shape;
        centerCoordinate = circle.center();
        QGeoCoordinate edge = centerCoordinate.atDistanceAndAzimuth(circle.radius(), 90);
        QDoubleVector2D centerPoint = map_->coordinateToScreenPosition(centerCoordinate, false);
        QDoubleVector2D edgePoint = map_->coordinateToScreenPosition(edge, false);
        bboxWidth = qAbs(centerPoint.x() - edgePoint.x()) * 2;
        bboxHeight = bboxWidth;
        break;
    }
    case QGeoShape::UnknownType:
        //Fallthrough to default
    default:
        return;
    }

    // position camera to the center of bounding box
    setProperty("center", QVariant::fromValue(centerCoordinate));

    //If the shape is empty we just change centerposition, not zoom
    if (bboxHeight == 0 && bboxWidth == 0)
        return;

    // adjust zoom
    double bboxWidthRatio = bboxWidth / (bboxWidth + bboxHeight);
    double mapWidthRatio = width() / (width() + height());
    double zoomRatio;

    if (bboxWidthRatio > mapWidthRatio)
        zoomRatio = bboxWidth / width();
    else
        zoomRatio = bboxHeight / height();

    qreal newZoom = log10(zoomRatio) / log10(0.5);
    newZoom = floor(qMax(minimumZoomLevel(), (map_->mapController()->zoom() + newZoom)));
    setProperty("zoomLevel", QVariant::fromValue(newZoom));
}
示例#17
0
/*!
    Returns whether this geo rectangle is not equal to \a other.
*/
bool QGeoRectangle::operator!=(const QGeoRectangle &other) const
{
    Q_D(const QGeoRectangle);

    return !(*d == *other.d_func());
}
示例#18
0
void QDeclarativeGeoMap::fitViewportToGeoShape()
{
    int margins  = 10;
    if (!m_map || width() <= margins || height() <= margins)
        return;

    QGeoCoordinate topLeft;
    QGeoCoordinate bottomRight;

    switch (m_region.type()) {
    case QGeoShape::RectangleType:
    {
        QGeoRectangle rect = m_region;
        topLeft = rect.topLeft();
        bottomRight = rect.bottomRight();
        break;
    }
    case QGeoShape::CircleType:
    {
        const double pi = M_PI;
        QGeoCircle circle = m_region;
        QGeoCoordinate centerCoordinate = circle.center();

        // calculate geo bounding box of the circle
        // circle tangential points with meridians and the north pole create
        // spherical triangle, we use spherical law of sines
        // sin(lon_delta_in_rad)/sin(r_in_rad) =
        // sin(alpha_in_rad)/sin(pi/2 - lat_in_rad), where:
        // * lon_delta_in_rad - delta of longitudes of circle center
        //   and tangential points
        // * r_in_rad - angular radius of the circle
        // * lat_in_rad - latitude of circle center
        // * alpha_in_rad - angle between meridian and radius to the circle =>
        //   this is tangential point => sin(alpha) = 1
        // * lat_delta_in_rad - delta of latitudes of circle center and
        //   latitude of points where great circle (going through circle
        //   center) crosses circle and the pole

        double r_in_rad = circle.radius() / EARTH_MEAN_RADIUS; // angular r
        double lat_delta_in_deg = r_in_rad * 180 / pi;
        double lon_delta_in_deg = std::asin(std::sin(r_in_rad) /
               std::cos(centerCoordinate.latitude() * pi / 180)) * 180 / pi;

        topLeft.setLatitude(centerCoordinate.latitude() + lat_delta_in_deg);
        topLeft.setLongitude(centerCoordinate.longitude() - lon_delta_in_deg);
        bottomRight.setLatitude(centerCoordinate.latitude()
                                - lat_delta_in_deg);
        bottomRight.setLongitude(centerCoordinate.longitude()
                                 + lon_delta_in_deg);

        // adjust if circle reaches poles => cross all meridians and
        // fit into Mercator projection bounds
        if (topLeft.latitude() > 90 || bottomRight.latitude() < -90) {
            topLeft.setLatitude(qMin(topLeft.latitude(), 85.05113));
            topLeft.setLongitude(-180.0);
            bottomRight.setLatitude(qMax(bottomRight.latitude(),
                                                 -85.05113));
            bottomRight.setLongitude(180.0);
        }
        break;
    }
    case QGeoShape::UnknownType:
        //Fallthrough to default
    default:
        return;
    }

    // adjust zoom, use reference world to keep things simple
    // otherwise we would need to do the error prone longitudes
    // wrapping
    QDoubleVector2D topLeftPoint =
            m_map->referenceCoordinateToItemPosition(topLeft);
    QDoubleVector2D bottomRightPoint =
            m_map->referenceCoordinateToItemPosition(bottomRight);

    double bboxWidth = bottomRightPoint.x() - topLeftPoint.x();
    double bboxHeight = bottomRightPoint.y() - topLeftPoint.y();

    // find center of the bounding box
    QGeoCoordinate centerCoordinate =
            m_map->referenceItemPositionToCoordinate(
                (topLeftPoint + bottomRightPoint)/2);

    // position camera to the center of bounding box
    setCenter(centerCoordinate);

    // if the shape is empty we just change center position, not zoom
    if (bboxHeight == 0 && bboxWidth == 0)
        return;

    double zoomRatio = qMax(bboxWidth / (width() - margins),
                            bboxHeight / (height() - margins));
    // fixme: use log2 with c++11
    zoomRatio = std::log(zoomRatio) / std::log(2.0);
    double newZoom = qMax((double)minimumZoomLevel(), m_map->mapController()->zoom()
                          - zoomRatio);
    setZoomLevel(newZoom);
    m_validRegion = true;
}
示例#19
0
void QGeoCodeReplyOsm::networkReplyFinished()
{
    if (!m_reply)
        return;

    if (m_reply->error() != QNetworkReply::NoError)
        return;

    QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());

    if (document.isObject()) {
        QJsonObject object = document.object();

        QGeoCoordinate coordinate;

        coordinate.setLatitude(object.value(QStringLiteral("lat")).toString().toDouble());
        coordinate.setLongitude(object.value(QStringLiteral("lon")).toString().toDouble());

        QJsonObject ao = object.value(QStringLiteral("address")).toObject();

        QGeoAddress address;
        address.setText(object.value(QStringLiteral("display_name")).toString());
        address.setCountry(ao.value(QStringLiteral("country")).toString());
        address.setCountryCode(ao.value(QStringLiteral("country_code")).toString());
        address.setState(ao.value(QStringLiteral("state")).toString());
        address.setCity(ao.value(QStringLiteral("city")).toString());
        address.setDistrict(ao.value(QStringLiteral("suburb")).toString());
        address.setPostalCode(ao.value(QStringLiteral("postcode")).toString());
        address.setStreet(ao.value(QStringLiteral("road")).toString());

        QGeoLocation location;
        location.setCoordinate(coordinate);
        location.setAddress(address);

        QList<QGeoLocation> locations;
        locations.append(location);

        setLocations(locations);
        setFinished(true);
    } else if (document.isArray()) {
        QJsonArray results = document.array();

        QList<QGeoLocation> locations;

        for (int i = 0; i < results.count(); ++i) {
            if (!results.at(i).isObject())
                continue;

            QJsonObject object = results.at(i).toObject();

            QGeoCoordinate coordinate;

            coordinate.setLatitude(object.value(QStringLiteral("lat")).toString().toDouble());
            coordinate.setLongitude(object.value(QStringLiteral("lon")).toString().toDouble());

            QGeoRectangle rectangle;

            if (object.contains(QStringLiteral("boundingbox"))) {
                QJsonArray a = object.value(QStringLiteral("boundingbox")).toArray();
                if (a.count() == 4) {
                    rectangle.setTopLeft(QGeoCoordinate(a.at(1).toString().toDouble(),
                                                        a.at(2).toString().toDouble()));
                    rectangle.setBottomRight(QGeoCoordinate(a.at(0).toString().toDouble(),
                                                            a.at(3).toString().toDouble()));
                }
            }

            QJsonObject ao = object.value(QStringLiteral("address")).toObject();

            QGeoAddress address;
            address.setText(object.value(QStringLiteral("display_name")).toString());
            address.setCountry(ao.value(QStringLiteral("country")).toString());
            address.setCountryCode(ao.value(QStringLiteral("country_code")).toString());
            address.setState(ao.value(QStringLiteral("state")).toString());
            address.setCity(ao.value(QStringLiteral("city")).toString());
            address.setDistrict(ao.value(QStringLiteral("suburb")).toString());
            address.setPostalCode(ao.value(QStringLiteral("postcode")).toString());
            address.setStreet(ao.value(QStringLiteral("road")).toString());

            QGeoLocation location;
            location.setCoordinate(coordinate);
            location.setBoundingBox(rectangle);
            location.setAddress(address);
            locations.append(location);
        }

        setLocations(locations);
        setFinished(true);
    }

    m_reply->deleteLater();
    m_reply = 0;
}