/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qdeclarativegeomap_p.h"
#include "qdeclarativegeomapquickitem_p.h"
#include "qdeclarativegeomapcopyrightsnotice_p.h"
#include "qdeclarativegeoserviceprovider_p.h"
#include "qdeclarativegeomaptype_p.h"
#include "qgeomappingmanager_p.h"
#include "qgeocameracapabilities_p.h"
#include "qgeomap_p.h"
#include "qdeclarativegeomapparameter_p.h"
#include "qgeomapobject_p.h"
#include <QtPositioning/QGeoCircle>
#include <QtPositioning/QGeoRectangle>
#include <QtPositioning/QGeoPath>
#include <QtPositioning/QGeoPolygon>
#include <QtQuick/QQuickWindow>
#include <QtQuick/QSGRectangleNode>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickitem_p.h>
#include <cmath>

#ifndef M_PI
#define M_PI 3.141592653589793238463
#endif


QT_BEGIN_NAMESPACE

static qreal sanitizeBearing(qreal bearing)
{
    bearing = std::fmod(bearing, qreal(360.0));
    if (bearing < 0.0)
        bearing += 360.0;

    return bearing;
}

/*!
    \qmltype Map
    \instantiates QDeclarativeGeoMap
    \inqmlmodule QtLocation
    \ingroup qml-QtLocation5-maps
    \since QtLocation 5.0

    \brief The Map type displays a map.

    The Map type is used to display a map or image of the Earth, with
    the capability to also display interactive objects tied to the map's
    surface.

    There are a variety of different ways to visualize the Earth's surface
    in a 2-dimensional manner, but all of them involve some kind of projection:
    a mathematical relationship between the 3D coordinates (latitude, longitude
    and altitude) and 2D coordinates (X and Y in pixels) on the screen.

    Different sources of map data can use different projections, and from the
    point of view of the Map type, we treat these as one replaceable unit:
    the Map plugin. A Map plugin consists of a data source, as well as all other
    details needed to display its data on-screen.

    The current Map plugin in use is contained in the \l plugin property of
    the Map item. In order to display any image in a Map item, you will need
    to set this property. See the \l Plugin type for a description of how
    to retrieve an appropriate plugin for use.

    The geographic region displayed in the Map item is referred to as its
    viewport, and this is defined by the properties \l center, and
    \l zoomLevel. The \l center property contains a \l {coordinate}
    specifying the center of the viewport, while \l zoomLevel controls the scale of the
    map. See each of these properties for further details about their values.

    When the map is displayed, each possible geographic coordinate that is
    visible will map to some pixel X and Y coordinate on the screen. To perform
    conversions between these two, Map provides the \l toCoordinate and
    \l fromCoordinate functions, which are of general utility.

    \section2 Map Objects

    Map related objects can be declared within the body of a Map object in Qt Quick and will
    automatically appear on the Map. To add an object programmatically, first be
    sure it is created with the Map as its parent (for example in an argument to
    Component::createObject).
    Then call the \l addMapItem method on the Map, if the type of this object is one of
    \l MapCircle, \l MapRectangle, \l MapPolyline, \l MapPolygon, \l MapRoute or \l MapQuickItem.
    A corresponding \l removeMapItem method also exists to do the opposite and
    remove any of the above types of map objects from the Map.

    Moving Map objects around, resizing them or changing their shape normally
    does not involve any special interaction with Map itself -- changing these
    properties in a map object will automatically update the display.

    \section2 Interaction

    The Map type includes support for pinch and flick gestures to control
    zooming and panning. These are enabled by default, and available at any
    time by using the \l gesture object. The actual GestureArea is constructed
    specially at startup and cannot be replaced or destroyed. Its properties
    can be altered, however, to control its behavior.

    \section2 Performance

    Maps are rendered using OpenGL (ES) and the Qt Scene Graph stack, and as
    a result perform quite well where GL accelerated hardware is available.

    For "online" Map plugins, network bandwidth and latency can be major
    contributors to the user's perception of performance. Extensive caching is
    performed to mitigate this, but such mitigation is not always perfect. For
    "offline" plugins, the time spent retrieving the stored geographic data
    and rendering the basic map features can often play a dominant role. Some
    offline plugins may use hardware acceleration themselves to (partially)
    avert this.

    In general, large and complex Map items such as polygons and polylines with
    large numbers of vertices can have an adverse effect on UI performance.
    Further, more detailed notes on this are in the documentation for each
    map item type.

    \section2 Example Usage

    The following snippet shows a simple Map and the necessary Plugin type
    to use it. The map is centered over Oslo, Norway, with zoom level 14.

    \quotefromfile minimal_map/main.qml
    \skipto import
    \printuntil }
    \printline }
    \skipto Map
    \printuntil }
    \printline }

    \image minimal_map.png
*/

/*!
    \qmlsignal QtLocation::Map::copyrightLinkActivated(string link)

    This signal is emitted when the user clicks on a \a link in the copyright notice. The
    application should open the link in a browser or display its contents to the user.
*/

QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent)
        : QQuickItem(parent),
        m_plugin(0),
        m_mappingManager(0),
        m_activeMapType(0),
        m_gestureArea(new QQuickGeoMapGestureArea(this)),
        m_map(0),
        m_error(QGeoServiceProvider::NoError),
        m_color(QColor::fromRgbF(0.9, 0.9, 0.9)),
        m_componentCompleted(false),
        m_pendingFitViewport(false),
        m_copyrightsVisible(true),
        m_maximumViewportLatitude(0.0),
        m_initialized(false),
        m_userMinimumZoomLevel(qQNaN()),
        m_userMaximumZoomLevel(qQNaN()),
        m_userMinimumTilt(qQNaN()),
        m_userMaximumTilt(qQNaN()),
        m_userMinimumFieldOfView(qQNaN()),
        m_userMaximumFieldOfView(qQNaN())
{
    setAcceptHoverEvents(false);
    setAcceptedMouseButtons(Qt::LeftButton);
    setFlags(QQuickItem::ItemHasContents | QQuickItem::ItemClipsChildrenToShape);
    setFiltersChildMouseEvents(true); // needed for childMouseEventFilter to work.

    m_activeMapType = new QDeclarativeGeoMapType(QGeoMapType(QGeoMapType::NoMap,
                                                             tr("No Map"),
                                                             tr("No Map"),
                                                             false, false,
                                                             0,
                                                             QByteArrayLiteral(""),
                                                             QGeoCameraCapabilities()), this);
    m_cameraData.setCenter(QGeoCoordinate(51.5073,-0.1277)); //London city center
    m_cameraData.setZoomLevel(8.0);

    m_cameraCapabilities.setTileSize(256);
    m_cameraCapabilities.setSupportsBearing(true);
    m_cameraCapabilities.setSupportsTilting(true);
    m_cameraCapabilities.setMinimumZoomLevel(0);
    m_cameraCapabilities.setMaximumZoomLevel(30);
    m_cameraCapabilities.setMinimumTilt(0);
    m_cameraCapabilities.setMaximumTilt(89.5);
    m_cameraCapabilities.setMinimumFieldOfView(1);
    m_cameraCapabilities.setMaximumFieldOfView(179);

    m_minimumTilt = m_cameraCapabilities.minimumTilt();
    m_maximumTilt = m_cameraCapabilities.maximumTilt();
    m_minimumFieldOfView = m_cameraCapabilities.minimumFieldOfView();
    m_maximumFieldOfView = m_cameraCapabilities.maximumFieldOfView();
}

QDeclarativeGeoMap::~QDeclarativeGeoMap()
{
    // Removing map parameters and map items from m_map
    if (m_map) {
        m_map->clearParameters();
        m_map->clearMapItems();
    }

    // Remove the items from the map, making them deletable.
    // Go in the same order as in removeMapChild: views, groups, then items
    if (!m_mapViews.isEmpty()) {
        const auto mapViews = m_mapViews;
        for (QDeclarativeGeoMapItemView *v : mapViews) { // so that removeMapItemView_real can safely modify m_mapViews;
            if (!v)
                continue;

            QQuickItem *parent = v->parentItem();
            QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(parent);
            if (group)
                continue; // Ignore non-top-level MIVs. They will be recursively processed.
                          // Identify them as being parented by a MapItemGroup.

            removeMapItemView_real(v);
        }
    }

    if (!m_mapItemGroups.isEmpty()) {
        const auto mapGroups = m_mapItemGroups;
        for (QDeclarativeGeoMapItemGroup *g : mapGroups) {
            if (!g)
                continue;

            QQuickItem *parent =g->parentItem();
            QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(parent);
            if (group)
                continue; // Ignore non-top-level Groups. They will be recursively processed.
                          // Identify them as being parented by a MapItemGroup.

            removeMapItemGroup_real(g);
        }
    }

    // remove any remaining map items associations
    const auto mapItems = m_mapItems;
    for (auto mi: mapItems)
        removeMapItem_real(mi.data());

    if (m_copyrights.data())
        delete m_copyrights.data();
    m_copyrights.clear();

    for (auto obj: qAsConst(m_pendingMapObjects))
        obj->setMap(nullptr); // worst case: going to be setMap(nullptr)'d twice

    delete m_map; // map objects get reset here
}

static QDeclarativeGeoMapType *findMapType(const QList<QDeclarativeGeoMapType *> &types, const QGeoMapType &type)
{
    for (int i = 0; i < types.size(); ++i)
        if (types[i]->mapType() == type)
            return types[i];
    return nullptr;
}

void QDeclarativeGeoMap::onSupportedMapTypesChanged()
{
    QList<QDeclarativeGeoMapType *> supportedMapTypes;
    QList<QGeoMapType> types = m_mappingManager->supportedMapTypes();
    for (int i = 0; i < types.size(); ++i) {
        // types that are present and get removed will be deleted at QObject destruction
        QDeclarativeGeoMapType *type = findMapType(m_supportedMapTypes, types[i]);
        if (!type)
            type = new QDeclarativeGeoMapType(types[i], this);
        supportedMapTypes.append(type);
    }
    m_supportedMapTypes.swap(supportedMapTypes);
    if (m_supportedMapTypes.isEmpty()) {
        m_map->setActiveMapType(QGeoMapType()); // no supported map types: setting an invalid one
    } else {
        bool hasMapType = false;
        foreach (QDeclarativeGeoMapType *declarativeType, m_supportedMapTypes) {
            if (declarativeType->mapType() == m_map->activeMapType())
                hasMapType = true;
        }
        if (!hasMapType) {
            QDeclarativeGeoMapType *type = m_supportedMapTypes.at(0);
            m_activeMapType = type;
            m_map->setActiveMapType(type->mapType());
        }
    }

    emit supportedMapTypesChanged();
}

void QDeclarativeGeoMap::setError(QGeoServiceProvider::Error error, const QString &errorString)
{
    if (m_error == error && m_errorString == errorString)
        return;
    m_error = error;
    m_errorString = errorString;
    emit errorChanged();
}

/*!
    \internal
    Called when the mapping manager is initialized AND the declarative element has a valid size > 0
*/
void QDeclarativeGeoMap::initialize()
{
    // try to keep change signals in the end
    bool visibleAreaHasChanged = false;

    QGeoCoordinate center = m_cameraData.center();

    if (!qIsFinite(m_userMinimumZoomLevel))
        setMinimumZoomLevel(m_map->minimumZoom(), false);
    else
        setMinimumZoomLevel(qMax<qreal>(m_map->minimumZoom(), m_userMinimumZoomLevel), false);

    double bearing = m_cameraData.bearing();
    double tilt = m_cameraData.tilt();
    double fov = m_cameraData.fieldOfView(); // Must be 45.0
    QGeoCameraData cameraData = m_cameraData;

    if (!m_cameraCapabilities.supportsBearing() && bearing != 0.0)
        cameraData.setBearing(0);

    if (!m_cameraCapabilities.supportsTilting() && tilt != 0.0)
        cameraData.setTilt(0);

    m_map->setVisibleArea(m_visibleArea);
    if (m_map->visibleArea() != m_visibleArea)
        visibleAreaHasChanged = true;

    cameraData.setFieldOfView(qBound(m_cameraCapabilities.minimumFieldOfView(),
                                       fov,
                                       m_cameraCapabilities.maximumFieldOfView()));

    // set latitude boundary check
    m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(cameraData);
    m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(cameraData);

    center.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
    cameraData.setCenter(center);

    connect(m_map.data(), &QGeoMap::cameraDataChanged,
            this,  &QDeclarativeGeoMap::onCameraDataChanged);
    m_map->setCameraData(cameraData); // This normally triggers property changed signals.
                                      // BUT not in this case, since m_cameraData is already == cameraData.
                                      // So, emit visibleRegionChanged() separately, as
                                      // the effective visible region becomes available only now.

    for (auto obj : qAsConst(m_pendingMapObjects))
        obj->setMap(m_map);

    m_initialized = true;

    if (visibleAreaHasChanged)
        emit visibleAreaChanged();
    connect(m_map.data(), &QGeoMap::visibleAreaChanged, this, &QDeclarativeGeoMap::visibleAreaChanged);

    emit mapReadyChanged(true);
    emit visibleRegionChanged();

    if (m_copyrights) // To not update during initialize()
         update();
}

/*!
    \internal
*/
void QDeclarativeGeoMap::pluginReady()
{
    QGeoServiceProvider *provider = m_plugin->sharedGeoServiceProvider();
    m_mappingManager = provider->mappingManager();

    if (provider->mappingError() != QGeoServiceProvider::NoError) {
        setError(provider->mappingError(), provider->mappingErrorString());
        return;
    }

    if (!m_mappingManager) {
        //TODO Should really be EngineNotSetError (see QML GeoCodeModel)
        setError(QGeoServiceProvider::NotSupportedError, tr("Plugin does not support mapping."));
        return;
    }

    if (!m_mappingManager->isInitialized())
        connect(m_mappingManager, SIGNAL(initialized()), this, SLOT(mappingManagerInitialized()));
    else
        mappingManagerInitialized();

    // make sure this is only called once
    disconnect(this, SLOT(pluginReady()));
}

/*!
    \internal
*/
void QDeclarativeGeoMap::componentComplete()
{
    m_componentCompleted = true;
    populateParameters();
    populateMap();
    QQuickItem::componentComplete();
}

/*!
    \qmlproperty MapGestureArea QtLocation::Map::gesture

    Contains the MapGestureArea created with the Map. This covers pan, flick and pinch gestures.
    Use \c{gesture.enabled: true} to enable basic gestures, or see \l{MapGestureArea} for
    further details.
*/

QQuickGeoMapGestureArea *QDeclarativeGeoMap::gesture()
{
    return m_gestureArea;
}

/*!
    \internal

    This may happen before mappingManagerInitialized()
*/
void QDeclarativeGeoMap::populateMap()
{
    QSet<QObject *> kids(children().cbegin(), children().cend());
    const QList<QQuickItem *> quickKids = childItems();
    for (QQuickItem *ite: quickKids)
        kids.insert(ite);

    for (QObject *k : qAsConst(kids)) {
        addMapChild(k);
    }
}

void QDeclarativeGeoMap::populateParameters()
{
    QObjectList kids = children();
    QList<QQuickItem *> quickKids = childItems();
    for (int i = 0; i < quickKids.count(); ++i)
        kids.append(quickKids.at(i));
    for (int i = 0; i < kids.size(); ++i) {
        QDeclarativeGeoMapParameter *mapParameter = qobject_cast<QDeclarativeGeoMapParameter *>(kids.at(i));
        if (mapParameter)
            addMapParameter(mapParameter);
    }
}

/*!
    \internal
*/
void QDeclarativeGeoMap::setupMapView(QDeclarativeGeoMapItemView *view)
{
    view->setMap(this);
}

/*!
 * \internal
 */
QSGNode *QDeclarativeGeoMap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if (!m_map) {
        delete oldNode;
        return 0;
    }

    QSGRectangleNode *root = static_cast<QSGRectangleNode *>(oldNode);
    if (!root)
        root = window()->createRectangleNode();

    root->setRect(boundingRect());
    root->setColor(m_color);

    QSGNode *content = root->childCount() ? root->firstChild() : 0;
    content = m_map->updateSceneGraph(content, window());
    if (content && root->childCount() == 0)
        root->appendChildNode(content);

    return root;
}

/*!
    \qmlproperty Plugin QtLocation::Map::plugin

    This property holds the plugin which provides the mapping functionality.

    This is a write-once property. Once the map has a plugin associated with
    it, any attempted modifications of the plugin will be ignored.
*/

void QDeclarativeGeoMap::setPlugin(QDeclarativeGeoServiceProvider *plugin)
{
    if (m_plugin) {
        qmlWarning(this) << QStringLiteral("Plugin is a write-once property, and cannot be set again.");
        return;
    }
    m_plugin = plugin;
    emit pluginChanged(m_plugin);

    if (m_plugin->isAttached()) {
        pluginReady();
    } else {
        connect(m_plugin, SIGNAL(attached()),
                this, SLOT(pluginReady()));
    }
}

/*!
    \internal
*/
void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilities &oldCameraCapabilities)
{
    if (m_map->cameraCapabilities() == oldCameraCapabilities)
        return;
    m_cameraCapabilities = m_map->cameraCapabilities();

    //The zoom level limits are only restricted by the plugins values, if the user has set a more
    //strict zoom level limit before initialization nothing is done here.
    //minimum zoom level might be changed to limit gray bundaries
    //This code assumes that plugins' maximum zoom level will never exceed 30.0
    if (m_cameraCapabilities.maximumZoomLevelAt256() < m_gestureArea->maximumZoomLevel()) {
        setMaximumZoomLevel(m_cameraCapabilities.maximumZoomLevelAt256(), false);
    } else if (m_cameraCapabilities.maximumZoomLevelAt256() > m_gestureArea->maximumZoomLevel()) {
        if (!qIsFinite(m_userMaximumZoomLevel)) {
            // If the user didn't set anything
            setMaximumZoomLevel(m_cameraCapabilities.maximumZoomLevelAt256(), false);
        } else {  // Try to set what the user requested
            // Else if the user set something larger, but that got clamped by the previous camera caps
            setMaximumZoomLevel(qMin<qreal>(m_cameraCapabilities.maximumZoomLevelAt256(),
                                            m_userMaximumZoomLevel), false);
        }
    }

    if (m_cameraCapabilities.minimumZoomLevelAt256() > m_gestureArea->minimumZoomLevel()) {
        setMinimumZoomLevel(m_cameraCapabilities.minimumZoomLevelAt256(), false);
    } else if (m_cameraCapabilities.minimumZoomLevelAt256() < m_gestureArea->minimumZoomLevel()) {
        if (!qIsFinite(m_userMinimumZoomLevel)) {
            // If the user didn't set anything, trying to set the new caps.
            setMinimumZoomLevel(m_cameraCapabilities.minimumZoomLevelAt256(), false);
        } else {  // Try to set what the user requested
            // Else if the user set a minimum, m_gestureArea->minimumZoomLevel() might be larger
            // because of different reasons. Resetting it, as if it ends to be the same,
            // no signal will be emitted.
            setMinimumZoomLevel(qMax<qreal>(m_cameraCapabilities.minimumZoomLevelAt256(),
                                            m_userMinimumZoomLevel), false);
        }
    }

    // Tilt
    if (m_cameraCapabilities.maximumTilt() < m_maximumTilt) {
        setMaximumTilt(m_cameraCapabilities.maximumTilt(), false);
    } else if (m_cameraCapabilities.maximumTilt() > m_maximumTilt) {
        if (!qIsFinite(m_userMaximumTilt))
            setMaximumTilt(m_cameraCapabilities.maximumTilt(), false);
        else // Try to set what the user requested
            setMaximumTilt(qMin<qreal>(m_cameraCapabilities.maximumTilt(), m_userMaximumTilt), false);
    }

    if (m_cameraCapabilities.minimumTilt() > m_minimumTilt) {
        setMinimumTilt(m_cameraCapabilities.minimumTilt(), false);
    } else if (m_cameraCapabilities.minimumTilt() < m_minimumTilt) {
        if (!qIsFinite(m_userMinimumTilt))
            setMinimumTilt(m_cameraCapabilities.minimumTilt(), false);
        else // Try to set what the user requested
            setMinimumTilt(qMax<qreal>(m_cameraCapabilities.minimumTilt(), m_userMinimumTilt), false);
    }

    // FoV
    if (m_cameraCapabilities.maximumFieldOfView() < m_maximumFieldOfView) {
        setMaximumFieldOfView(m_cameraCapabilities.maximumFieldOfView(), false);
    } else if (m_cameraCapabilities.maximumFieldOfView() > m_maximumFieldOfView) {
        if (!qIsFinite(m_userMaximumFieldOfView))
            setMaximumFieldOfView(m_cameraCapabilities.maximumFieldOfView(), false);
        else // Try to set what the user requested
            setMaximumFieldOfView(qMin<qreal>(m_cameraCapabilities.maximumFieldOfView(), m_userMaximumFieldOfView), false);
    }

    if (m_cameraCapabilities.minimumFieldOfView() > m_minimumFieldOfView) {
        setMinimumFieldOfView(m_cameraCapabilities.minimumFieldOfView(), false);
    } else if (m_cameraCapabilities.minimumFieldOfView() < m_minimumFieldOfView) {
        if (!qIsFinite(m_userMinimumFieldOfView))
            setMinimumFieldOfView(m_cameraCapabilities.minimumFieldOfView(), false);
        else // Try to set what the user requested
            setMinimumFieldOfView(qMax<qreal>(m_cameraCapabilities.minimumFieldOfView(), m_userMinimumFieldOfView), false);
    }
}

/*!
    \internal
    this function will only be ever called once
*/
void QDeclarativeGeoMap::mappingManagerInitialized()
{
    m_map = m_mappingManager->createMap(this);

    if (!m_map)
        return;

    // Any map items that were added before the plugin was ready
    // need to have setMap called again
    for (const QPointer<QDeclarativeGeoMapItemBase> &item : qAsConst(m_mapItems)) {
        if (item) {
            item->setMap(this, m_map);
            m_map->addMapItem(item.data()); // m_map filters out what is not supported.
        }
    }

    /* COPY NOTICE SETUP */
    m_copyrights = new QDeclarativeGeoMapCopyrightNotice(this);
    m_copyrights->setCopyrightsZ(m_maxChildZ + 1);
    m_copyrights->setCopyrightsVisible(m_copyrightsVisible);
    m_copyrights->setMapSource(this);

    m_gestureArea->setMap(m_map);

    QList<QGeoMapType> types = m_mappingManager->supportedMapTypes();
    for (int i = 0; i < types.size(); ++i) {
        QDeclarativeGeoMapType *type = new QDeclarativeGeoMapType(types[i], this);
        m_supportedMapTypes.append(type);
    }

    if (m_activeMapType && m_plugin->name().toLatin1() == m_activeMapType->mapType().pluginName()) {
        m_map->setActiveMapType(m_activeMapType->mapType());
    } else {
        if (m_activeMapType)
            m_activeMapType->deleteLater();

        if (!m_supportedMapTypes.isEmpty()) {
                m_activeMapType = m_supportedMapTypes.at(0);
                m_map->setActiveMapType(m_activeMapType->mapType());
        } else {
            m_activeMapType = new QDeclarativeGeoMapType(QGeoMapType(QGeoMapType::NoMap,
                                                                     tr("No Map"),
                                                                     tr("No Map"),
                                                                     false,
                                                                     false,
                                                                     0,
                                                                     QByteArrayLiteral(""),
                                                                     QGeoCameraCapabilities()), this);
        }
    }

    // Update camera capabilities
    onCameraCapabilitiesChanged(m_cameraCapabilities);

    // Map tiles are built in this call. m_map->minimumZoom() becomes operational
    // after this has been called at least once, after creation.
    // However, getting into the following block may fire a copyrightsChanged that would get lost,
    // as the connections are set up after.
    QString copyrightString;
    QImage copyrightImage;
    if (!m_initialized && width() > 0 && height() > 0) {
        QMetaObject::Connection copyrightStringCatcherConnection =
                connect(m_map.data(),
                        QOverload<const QString &>::of(&QGeoMap::copyrightsChanged),
                        [&copyrightString](const QString &copy){ copyrightString = copy; });
        QMetaObject::Connection copyrightImageCatcherConnection =
                connect(m_map.data(),
                        QOverload<const QImage &>::of(&QGeoMap::copyrightsChanged),
                        [&copyrightImage](const QImage &copy){ copyrightImage = copy; });
        m_map->setViewportSize(QSize(width(), height()));
        initialize(); // This emits the caught signals above
        QObject::disconnect(copyrightStringCatcherConnection);
        QObject::disconnect(copyrightImageCatcherConnection);
    }


    /* COPYRIGHT SIGNALS REWIRING */
    connect(m_map.data(), SIGNAL(copyrightsChanged(QImage)),
            this,  SIGNAL(copyrightsChanged(QImage)));
    connect(m_map.data(), SIGNAL(copyrightsChanged(QString)),
            this,  SIGNAL(copyrightsChanged(QString)));
    if (!copyrightString.isEmpty())
        emit m_map->copyrightsChanged(copyrightString);
    else if (!copyrightImage.isNull())
        emit m_map->copyrightsChanged(copyrightImage);


    connect(window(), &QQuickWindow::beforeSynchronizing, this, &QDeclarativeGeoMap::updateItemToWindowTransform, Qt::DirectConnection);
    connect(m_map.data(), &QGeoMap::sgNodeChanged, this, &QDeclarativeGeoMap::onSGNodeChanged);
    connect(m_map.data(), &QGeoMap::cameraCapabilitiesChanged, this, &QDeclarativeGeoMap::onCameraCapabilitiesChanged);

    // This prefetches a buffer around the map
    m_map->prefetchData();

    connect(m_mappingManager, SIGNAL(supportedMapTypesChanged()), this, SLOT(onSupportedMapTypesChanged()));
    emit minimumZoomLevelChanged();
    emit maximumZoomLevelChanged();
    emit supportedMapTypesChanged();
    emit activeMapTypeChanged();

    // Any map item groups that were added before the plugin was ready
    // DO NOT need to have setMap called again on their children map items
    // because they have been added to m_mapItems, which is processed right above.


    // All map parameters that were added before the plugin was ready
    // need to be added to m_map
    for (QDeclarativeGeoMapParameter *p : qAsConst(m_mapParameters))
        m_map->addParameter(p);

    if (m_initialized)
        update();
}

/*!
    \internal
*/
QDeclarativeGeoServiceProvider *QDeclarativeGeoMap::plugin() const
{
    return m_plugin;
}

/*!
    \internal
    Sets the gesture areas minimum zoom level. If the camera capabilities
    has been set this method honors the boundaries set by it.
    The minimum zoom level will also have a lower bound dependent on the size
    of the canvas, effectively preventing to display out of bounds areas.
*/
void QDeclarativeGeoMap::setMinimumZoomLevel(qreal minimumZoomLevel, bool userSet)
{
    if (minimumZoomLevel >= 0) {
        qreal oldUserMinimumZoomLevel = m_userMinimumZoomLevel;
        if (userSet)
            m_userMinimumZoomLevel = minimumZoomLevel;
        qreal oldMinimumZoomLevel = this->minimumZoomLevel();

        minimumZoomLevel = qBound(qreal(m_cameraCapabilities.minimumZoomLevelAt256()), minimumZoomLevel, maximumZoomLevel());
        if (m_map)
             minimumZoomLevel = qMax<qreal>(minimumZoomLevel, m_map->minimumZoom());

        // minimumZoomLevel is, at this point, the implicit minimum zoom level
        m_gestureArea->setMinimumZoomLevel(minimumZoomLevel);

        if (zoomLevel() < minimumZoomLevel && (m_gestureArea->enabled() || !m_cameraCapabilities.overzoomEnabled()))
            setZoomLevel(minimumZoomLevel);

        if (qIsNaN(m_userMinimumZoomLevel) && oldMinimumZoomLevel != minimumZoomLevel)
            emit minimumZoomLevelChanged();
        else if (userSet && oldUserMinimumZoomLevel != m_userMinimumZoomLevel)
            emit minimumZoomLevelChanged();
    }
}

/*!
    \qmlproperty real QtLocation::Map::minimumZoomLevel

    This property holds the minimum valid zoom level for the map.

    The minimum zoom level defined by the \l plugin used is a lower bound for
    this property. However, the returned value is also canvas-size-dependent, and
    can be higher than the user-specified value, or than the minimum zoom level
    defined by the plugin used, to prevent the map from being smaller than the
    viewport in either dimension.

    If the \l plugin property is not set or the plugin does not support mapping, this property is \c 0.
*/

qreal QDeclarativeGeoMap::minimumZoomLevel() const
{
    if (!qIsNaN(m_userMinimumZoomLevel))
        return m_userMinimumZoomLevel;
    else
        return m_gestureArea->minimumZoomLevel();
}

/*!
    \internal
*/
qreal QDeclarativeGeoMap::implicitMinimumZoomLevel() const
{
    return m_gestureArea->minimumZoomLevel();
}

/*!
    \internal
*/
qreal QDeclarativeGeoMap::effectiveMinimumZoomLevel() const
{
    return qMax<qreal>(minimumZoomLevel(), implicitMinimumZoomLevel());
}

/*!
    \internal
    Sets the gesture areas maximum zoom level. If the camera capabilities
    has been set this method honors the boundaries set by it.
*/
void QDeclarativeGeoMap::setMaximumZoomLevel(qreal maximumZoomLevel, bool userSet)
{
    if (maximumZoomLevel >= 0) {
        if (userSet)
            m_userMaximumZoomLevel = maximumZoomLevel;
        qreal oldMaximumZoomLevel = this->maximumZoomLevel();

        maximumZoomLevel = qBound(minimumZoomLevel(), maximumZoomLevel, qreal(m_cameraCapabilities.maximumZoomLevelAt256()));

        m_gestureArea->setMaximumZoomLevel(maximumZoomLevel);

        if (zoomLevel() > maximumZoomLevel && (m_gestureArea->enabled() || !m_cameraCapabilities.overzoomEnabled()))
            setZoomLevel(maximumZoomLevel);

        if (oldMaximumZoomLevel != maximumZoomLevel)
            emit maximumZoomLevelChanged();
    }
}

/*!
    \qmlproperty real QtLocation::Map::maximumZoomLevel

    This property holds the maximum valid zoom level for the map.

    The maximum zoom level is defined by the \l plugin used.
    If the \l plugin property is not set or the plugin does not support mapping, this property is \c 30.
*/

qreal QDeclarativeGeoMap::maximumZoomLevel() const
{
    return m_gestureArea->maximumZoomLevel();
}

/*!
    \qmlproperty real QtLocation::Map::zoomLevel

    This property holds the zoom level for the map.

    Larger values for the zoom level provide more detail. Zoom levels
    are always non-negative. The default value is 8.0. Depending on the plugin in use,
    values outside the [minimumZoomLevel, maximumZoomLevel] range, which represent the range for which
    tiles are available, may be accepted, or clamped.
*/
void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel)
{
    return setZoomLevel(zoomLevel, m_cameraCapabilities.overzoomEnabled());
}

/*!
    \internal

    Sets the zoom level.
    Larger values for the zoom level provide more detail. Zoom levels
    are always non-negative. The default value is 8.0. Values outside the
    [minimumZoomLevel, maximumZoomLevel] range, which represent the range for which
    tiles are available, can be accepted or clamped by setting the overzoom argument
    to true or false respectively.
*/
void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel, bool overzoom)
{
    if (zoomLevel < 0)
        return;

    if (m_initialized) {
        QGeoCameraData cameraData = m_map->cameraData();
        if (cameraData.zoomLevel() == zoomLevel)
            return;

        cameraData.setZoomLevel(qBound<qreal>(overzoom ? m_map->minimumZoom() : effectiveMinimumZoomLevel(),
                                                zoomLevel,
                                                overzoom ? 30 : maximumZoomLevel()));
        m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(cameraData);
        m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(cameraData);
        QGeoCoordinate coord = cameraData.center();
        coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
        cameraData.setCenter(coord);
        m_map->setCameraData(cameraData);
    } else {
        const bool zlHasChanged = zoomLevel != m_cameraData.zoomLevel();
        m_cameraData.setZoomLevel(zoomLevel);
        if (zlHasChanged) {
            emit zoomLevelChanged(zoomLevel);
            // do not emit visibleRegionChanged() here, because, if the map isn't initialized,
            // the getter won't return anything updated
        }
    }
}

bool QDeclarativeGeoMap::addMapChild(QObject *child)
{
    // dispatch items appropriately
    QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(child);
    if (mapView)
        return addMapItemView_real(mapView);

    QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);
    if (itemGroup) // addMapItemView calls addMapItemGroup
        return addMapItemGroup_real(itemGroup);

    QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
    if (mapItem)
        return addMapItem_real(mapItem);

    QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(child);
    if (mapObject)
        addMapObject(mapObject); // this emits mapObjectsChanged, != mapItemsChanged
    return false;
}

bool QDeclarativeGeoMap::removeMapChild(QObject *child)
{
    // dispatch items appropriately
    QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(child);
    if (mapView)
        return removeMapItemView_real(mapView);

    QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);
    if (itemGroup) // removeMapItemView calls removeMapItemGroup for itself.
        return removeMapItemGroup_real(itemGroup);

    QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
    if (mapItem)
        return removeMapItem_real(mapItem);

    QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(child);
    if (mapObject)
        removeMapObject(mapObject); // this emits mapObjectsChanged, != mapItemsChanged
    return false;
}

bool QDeclarativeGeoMap::isGroupNested(QDeclarativeGeoMapItemGroup *group)
{
    QObject *parent = group->parent();
    // Nested groups have parent set in parent's componentComplete()
    // Those instantiated by MapItemView's delegateModel, however, do not,
    // but have setParentItem set.
    return qobject_cast<QDeclarativeGeoMapItemGroup *>(parent)
            || qobject_cast<QDeclarativeGeoMapItemGroup *>(group->parentItem());
}

qreal QDeclarativeGeoMap::zoomLevel() const
{
    if (m_initialized)
        return m_map->cameraData().zoomLevel();
    return m_cameraData.zoomLevel();
}

/*!
    \qmlproperty real QtLocation::Map::bearing

    This property holds the bearing for the map.
    The default value is 0.
    If the Plugin used for the Map supports bearing, the valid range for this value is between 0 and 360.
    If the Plugin used for the Map does not support bearing, changing this property will have no effect.

    \since QtLocation 5.9
*/
void QDeclarativeGeoMap::setBearing(qreal bearing)
{
    bearing = sanitizeBearing(bearing);
    if (m_initialized) {
        QGeoCameraData cameraData = m_map->cameraData();
        cameraData.setBearing(bearing);
        m_map->setCameraData(cameraData);
    } else {
        const bool bearingHasChanged = bearing != m_cameraData.bearing();
        m_cameraData.setBearing(bearing);
        if (bearingHasChanged) {
            emit bearingChanged(bearing);
            // do not emit visibleRegionChanged() here, because, if the map isn't initialized,
            // the getter won't return anything updated
        }
    }
}

/*!
    \qmlmethod void QtLocation::Map::setBearing(real bearing, coordinate coordinate)

    Sets the bearing for the map to \a bearing, rotating it around \a coordinate.
    If the Plugin used for the Map supports bearing, the valid range for \a bearing is between 0 and 360.
    If the Plugin used for the Map does not support bearing, or if the map is tilted and \a coordinate happens
    to be behind the camera, or if the map is not ready (see \l mapReady), calling this method will have no effect.

    The release of this API with Qt 5.10 is a Technology Preview.

    \since 5.10
*/
void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate)
{
    if (!m_initialized)
        return;

    const QGeoCoordinate currentCenter = center();
    const qreal currentBearing = QDeclarativeGeoMap::bearing();
    bearing = sanitizeBearing(bearing);

    if (!coordinate.isValid()
            || !qIsFinite(bearing)
            || (coordinate == currentCenter && bearing == currentBearing))
        return;

    if (m_map->capabilities() & QGeoMap::SupportsSetBearing)
        m_map->setBearing(bearing, coordinate);
}

qreal QDeclarativeGeoMap::bearing() const
{
    if (m_initialized)
        return m_map->cameraData().bearing();
    return m_cameraData.bearing();
}

/*!
    \qmlproperty real QtLocation::Map::tilt

    This property holds the tilt for the map, in degrees.
    The default value is 0.
    The valid range for this value is [ minimumTilt, maximumTilt ].
    If the Plugin used for the Map does not support tilting, changing this property will have no effect.

    \sa minimumTilt, maximumTilt

    \since QtLocation 5.9
*/
void QDeclarativeGeoMap::setTilt(qreal tilt)
{
    tilt = qBound(minimumTilt(), tilt, maximumTilt());

    if (m_initialized) {
        QGeoCameraData cameraData = m_map->cameraData();
        cameraData.setTilt(tilt);
        m_map->setCameraData(cameraData);
    } else {
        const bool tiltHasChanged = tilt != m_cameraData.tilt();
        m_cameraData.setTilt(tilt);
        if (tiltHasChanged) {
            emit tiltChanged(tilt);
            // do not emit visibleRegionChanged() here, because, if the map isn't initialized,
            // the getter won't return anything updated
        }
    }
}

qreal QDeclarativeGeoMap::tilt() const
{
    if (m_initialized)
        return m_map->cameraData().tilt();
    return m_cameraData.tilt();
}

void QDeclarativeGeoMap::setMinimumTilt(qreal minimumTilt, bool userSet)
{
    if (minimumTilt >= 0) {
        if (userSet)
            m_userMinimumTilt = minimumTilt;
        qreal oldMinimumTilt = this->minimumTilt();

        m_minimumTilt = qBound<double>(m_cameraCapabilities.minimumTilt(),
                                       minimumTilt,
                                       m_cameraCapabilities.maximumTilt());

        if (tilt() < m_minimumTilt)
            setTilt(m_minimumTilt);

        if (oldMinimumTilt != m_minimumTilt)
            emit minimumTiltChanged(m_minimumTilt);
    }
}

/*!
    \qmlproperty real QtLocation::Map::fieldOfView

    This property holds the field of view of the camera used to look at the map, in degrees.
    If the plugin property of the map is not set, or the plugin does not support mapping, the value is 45 degrees.

    Note that changing this value implicitly changes also the distance between the camera and the map,
    so that, at a tilting angle of 0 degrees, the resulting image is identical for any value used for this property.

    For more information about this parameter, consult the Wikipedia articles about \l {https://en.wikipedia.org/wiki/Field_of_view} {Field of view} and
    \l {https://en.wikipedia.org/wiki/Angle_of_view} {Angle of view}.

    \sa minimumFieldOfView, maximumFieldOfView

    \since QtLocation 5.9
*/
void QDeclarativeGeoMap::setFieldOfView(qreal fieldOfView)
{
    fieldOfView = qBound(minimumFieldOfView(), fieldOfView, maximumFieldOfView());

    if (m_initialized) {
        QGeoCameraData cameraData = m_map->cameraData();
        cameraData.setFieldOfView(fieldOfView);
        m_map->setCameraData(cameraData);
    } else {
        const bool fovChanged = fieldOfView != m_cameraData.fieldOfView();
        m_cameraData.setFieldOfView(fieldOfView);
        if (fovChanged) {
            emit fieldOfViewChanged(fieldOfView);
            // do not emit visibleRegionChanged() here, because, if the map isn't initialized,
            // the getter won't return anything updated
        }
    }
}

qreal QDeclarativeGeoMap::fieldOfView() const
{
    if (m_initialized)
        return m_map->cameraData().fieldOfView();
    return m_cameraData.fieldOfView();
}

void QDeclarativeGeoMap::setMinimumFieldOfView(qreal minimumFieldOfView, bool userSet)
{
    if (minimumFieldOfView > 0 && minimumFieldOfView < 180.0) {
        if (userSet)
            m_userMinimumFieldOfView = minimumFieldOfView;
        qreal oldMinimumFoV = this->minimumFieldOfView();

        m_minimumFieldOfView = qBound<double>(m_cameraCapabilities.minimumFieldOfView(),
                                              minimumFieldOfView,
                                              m_cameraCapabilities.maximumFieldOfView());

        if (fieldOfView() < m_minimumFieldOfView)
            setFieldOfView(m_minimumFieldOfView);

        if (oldMinimumFoV != m_minimumFieldOfView)
            emit minimumFieldOfViewChanged(m_minimumFieldOfView);
    }
}

/*!
    \qmlproperty real QtLocation::Map::minimumFieldOfView

    This property holds the minimum valid field of view for the map, in degrees.

    The minimum tilt field of view by the \l plugin used is a lower bound for
    this property.
    If the \l plugin property is not set or the plugin does not support mapping, this property is \c 1.

    \sa fieldOfView, maximumFieldOfView

    \since QtLocation 5.9
*/
qreal QDeclarativeGeoMap::minimumFieldOfView() const
{
    return m_minimumFieldOfView;
}

void QDeclarativeGeoMap::setMaximumFieldOfView(qreal maximumFieldOfView, bool userSet)
{
    if (maximumFieldOfView > 0 && maximumFieldOfView < 180.0) {
        if (userSet)
            m_userMaximumFieldOfView = maximumFieldOfView;
        qreal oldMaximumFoV = this->maximumFieldOfView();

        m_maximumFieldOfView = qBound<double>(m_cameraCapabilities.minimumFieldOfView(),
                                              maximumFieldOfView,
                                              m_cameraCapabilities.maximumFieldOfView());

        if (fieldOfView() > m_maximumFieldOfView)
            setFieldOfView(m_maximumFieldOfView);

        if (oldMaximumFoV != m_maximumFieldOfView)
            emit maximumFieldOfViewChanged(m_maximumFieldOfView);
    }
}

/*!
    \qmlproperty real QtLocation::Map::maximumFieldOfView

    This property holds the maximum valid field of view for the map, in degrees.

    The minimum tilt field of view by the \l plugin used is an upper bound for
    this property.
    If the \l plugin property is not set or the plugin does not support mapping, this property is \c 179.

    \sa fieldOfView, minimumFieldOfView

    \since QtLocation 5.9
*/
qreal QDeclarativeGeoMap::maximumFieldOfView() const
{
    return m_maximumFieldOfView;
}

/*!
    \qmlproperty real QtLocation::Map::minimumTilt

    This property holds the minimum valid tilt for the map, in degrees.

    The minimum tilt defined by the \l plugin used is a lower bound for
    this property.
    If the \l plugin property is not set or the plugin does not support mapping, this property is \c 0.

    Since QtLocation 5.12, plugins can additionally restrict this value depending on the current zoom level.

    \sa tilt, maximumTilt

    \since QtLocation 5.9
*/
qreal QDeclarativeGeoMap::minimumTilt() const
{
    return m_minimumTilt;
}

void QDeclarativeGeoMap::setMaximumTilt(qreal maximumTilt, bool userSet)
{
    if (maximumTilt >= 0) {
        if (userSet)
            m_userMaximumTilt = maximumTilt;
        qreal oldMaximumTilt = this->maximumTilt();

        m_maximumTilt = qBound<double>(m_cameraCapabilities.minimumTilt(),
                                       maximumTilt,
                                       m_cameraCapabilities.maximumTilt());

        if (tilt() > m_maximumTilt)
            setTilt(m_maximumTilt);

        if (oldMaximumTilt != m_maximumTilt)
            emit maximumTiltChanged(m_maximumTilt);
    }
}

/*!
    \qmlproperty real QtLocation::Map::maximumTilt

    This property holds the maximum valid tilt for the map, in degrees.

    The maximum tilt defined by the \l plugin used is an upper bound for
    this property.
    If the \l plugin property is not set or the plugin does not support mapping, this property is \c 89.5.

    Since QtLocation 5.12, plugins can additionally restrict this value depending on the current zoom level.

    \sa tilt, minimumTilt

    \since QtLocation 5.9
*/
qreal QDeclarativeGeoMap::maximumTilt() const
{
    return m_maximumTilt;
}

/*!
    \qmlproperty coordinate QtLocation::Map::center

    This property holds the coordinate which occupies the center of the
    mapping viewport. Invalid center coordinates are ignored.

    The default value is an arbitrary valid coordinate.
*/
void QDeclarativeGeoMap::setCenter(const QGeoCoordinate &center)
{
    if (!center.isValid())
        return;

    if (m_initialized) {
        QGeoCoordinate coord(center);
        coord.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
        QGeoCameraData cameraData = m_map->cameraData();
        cameraData.setCenter(coord);
        m_map->setCameraData(cameraData);
    } else {
        const bool centerHasChanged = center != m_cameraData.center();
        m_cameraData.setCenter(center);
        if (centerHasChanged) {
            emit centerChanged(center);
            // do not emit visibleRegionChanged() here, because, if the map isn't initialized,
            // the getter won't return anything updated
        }
    }
}

QGeoCoordinate QDeclarativeGeoMap::center() const
{
    if (m_initialized)
        return m_map->cameraData().center();
    return m_cameraData.center();
}


/*!
    \qmlproperty geoshape QtLocation::Map::visibleRegion

    This property holds the region which occupies the viewport of
    the map. 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 the screen. This implies that
    reading this property back shortly after having been set the
    returned area is equal or larger than the set area.

    Setting this property implicitly changes the \l center and
    \l zoomLevel of the map. Any previously set value to those
    properties will be overridden.

    \note Since Qt 5.14 This property provides change notifications.

    \since 5.6
*/
void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape)
{
    if (shape.boundingGeoRectangle() == visibleRegion())
        return;

    m_visibleRegion = shape.boundingGeoRectangle();
    if (!m_visibleRegion.isValid()
        || (m_visibleRegion.bottomRight().latitude() >= 85.0) // rect entirely outside web mercator
        || (m_visibleRegion.topLeft().latitude() <= -85.0)) {
        // shape invalidated -> nothing to fit anymore
        m_visibleRegion = QGeoRectangle();
        m_pendingFitViewport = false;
        emit visibleRegionChanged();
        return;
    }

    if (!m_map || !width() || !height()) {
        m_pendingFitViewport = true;
        emit visibleRegionChanged();
        return;
    }

    fitViewportToGeoShape(m_visibleRegion);
    emit visibleRegionChanged();
}

QGeoShape QDeclarativeGeoMap::visibleRegion() const
{
    if (!m_map || !width() || !height())
        return m_visibleRegion;

    if (m_map->capabilities() & QGeoMap::SupportsVisibleRegion) {
        return m_map->visibleRegion();
    } else {
        // ToDo: handle projections not supporting visible region in a better way.
        // This approach will fail when horizon is in the view or the map is greatly zoomed out.
        QList<QGeoCoordinate> visiblePoly;
        visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0,0), false);
        visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_map->viewportWidth() - 1,
                                                                                       0), false);
        visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_map->viewportWidth() - 1,
                                                                                       m_map->viewportHeight() - 1), false);
        visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0,
                                                                                       m_map->viewportHeight() - 1), false);
        QGeoPath path;
        path.setPath(visiblePoly);
        return path.boundingGeoRectangle();
    }
}

/*!
    \qmlproperty bool QtLocation::Map::copyrightsVisible

    This property holds the visibility of the copyrights notice. The notice is usually
    displayed in the bottom left corner. By default, this property is set to \c true.

    \note Many map providers require the notice to be visible as part of the terms and conditions.
    Please consult the relevant provider documentation before turning this notice off.

    \since 5.7
*/
void QDeclarativeGeoMap::setCopyrightsVisible(bool visible)
{
    if (m_copyrightsVisible == visible)
        return;

    if (!m_copyrights.isNull())
        m_copyrights->setCopyrightsVisible(visible);

    m_copyrightsVisible = visible;
    emit copyrightsVisibleChanged(visible);
}

bool QDeclarativeGeoMap::copyrightsVisible() const
{
    return m_copyrightsVisible;
}



/*!
    \qmlproperty color QtLocation::Map::color

    This property holds the background color of the map element.

    \since 5.6
*/
void QDeclarativeGeoMap::setColor(const QColor &color)
{
    if (color != m_color) {
        m_color = color;
        update();
        emit colorChanged(m_color);
    }
}

QColor QDeclarativeGeoMap::color() const
{
    return m_color;
}

/*!
    \qmlproperty rect QtLocation::Map::visibleArea

    This property holds the visible area inside the Map QML element.
    It is a rect whose coordinates are relative to the Map element.
    Its size will be clamped to the size of the Map element.
    A null visibleArea means that the whole Map is visible.

    \since 5.12
*/
QRectF QDeclarativeGeoMap::visibleArea() const
{
    if (m_initialized)
        return m_map->visibleArea();
    return m_visibleArea;
}

void QDeclarativeGeoMap::setVisibleArea(const QRectF &visibleArea)
{
    const QRectF oldVisibleArea = QDeclarativeGeoMap::visibleArea();
    if (visibleArea == oldVisibleArea)
        return;

    if (!visibleArea.isValid() && !visibleArea.isEmpty()) // values < 0
        return;

    if (m_initialized) {
        m_map->setVisibleArea(visibleArea);
        const QRectF newVisibleArea = QDeclarativeGeoMap::visibleArea();
        if (newVisibleArea != oldVisibleArea) {
            // polish map items
            for (const QPointer<QDeclarativeGeoMapItemBase> &i: qAsConst(m_mapItems)) {
                if (i)
                    i->visibleAreaChanged();
            }
        }
    } else {
        m_visibleArea = visibleArea;
        const QRectF newVisibleArea = QDeclarativeGeoMap::visibleArea();
        if (newVisibleArea != oldVisibleArea)
            emit visibleAreaChanged();
    }
}

/*!
    \qmlproperty bool QtLocation::Map::mapReady

    This property holds whether the map has been successfully initialized and is ready to be used.
    Some methods, such as \l fromCoordinate and \l toCoordinate, will not work before the map is ready.
    Due to the architecture of the \l Map, it's advised to use the signal emitted for this property
    in place of \l {QtQml::Component::completed()}{Component.onCompleted}, to make sure that everything behaves as expected.

    \since 5.9
*/
bool QDeclarativeGeoMap::mapReady() const
{
    return m_initialized;
}

QMargins QDeclarativeGeoMap::mapMargins() const
{
    const QRectF va = m_map->visibleArea();
    if (va.isEmpty())
        return QMargins();
    return QMargins( va.x()
                    , va.y()
                    , width() - va.width() - va.x()
                    , height() - va.height() - va.y());
}

/*!
    \qmlproperty list<MapType> QtLocation::Map::supportedMapTypes

    This read-only property holds the set of \l{MapType}{map types} supported by this map.

    \sa activeMapType
*/
QQmlListProperty<QDeclarativeGeoMapType> QDeclarativeGeoMap::supportedMapTypes()
{
    return QQmlListProperty<QDeclarativeGeoMapType>(this, &m_supportedMapTypes);
}

/*!
    \qmlmethod void QtLocation::Map::alignCoordinateToPoint(coordinate coordinate, QPointF point)

    Aligns \a coordinate to \a point.
    This method effectively extends the functionality offered by the \l center qml property, allowing
    to align a coordinate to point of the Map element other than its center.
    This is useful in those applications where the center of the scene (e.g., a cursor) is not to be
    placed exactly in the center of the map.

    If the map is tilted, and \a coordinate happens to be behind the camera, or if the map is not ready
    (see \l mapReady), calling this method will have no effect.

    The release of this API with Qt 5.10 is a Technology Preview.

    \sa center

    \since 5.10
*/
void QDeclarativeGeoMap::alignCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &point)
{
    if (!m_map || !(m_map->capabilities() & QGeoMap::SupportsAnchoringCoordinate))
        return;

    if (!coordinate.isValid()
            || !qIsFinite(point.x())
            || !qIsFinite(point.y()))
        return;

    m_map->anchorCoordinateToPoint(coordinate, point);
}

/*!
    \qmlmethod coordinate QtLocation::Map::toCoordinate(QPointF position, bool clipToViewPort)

    Returns the coordinate which corresponds to the \a position relative to the map item.

    If \a clipToViewPort is \c true, or not supplied then returns an invalid coordinate if
    \a position is not within the current viewport.
*/
QGeoCoordinate QDeclarativeGeoMap::toCoordinate(const QPointF &position, bool clipToViewPort) const
{
    if (m_map)
        return m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(position), clipToViewPort);
    else
        return QGeoCoordinate();
}

/*!
    \qmlmethod point QtLocation::Map::fromCoordinate(coordinate coordinate, bool clipToViewPort)

    Returns the position relative to the map item which corresponds to the \a coordinate.

    If \a clipToViewPort is \c true, or not supplied then returns an invalid QPointF if
    \a coordinate is not within the current viewport.
*/
QPointF QDeclarativeGeoMap::fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort) const
{
    if (m_map)
        return m_map->geoProjection().coordinateToItemPosition(coordinate, clipToViewPort).toPointF();
    else
        return QPointF(qQNaN(), qQNaN());
}

/*!
    \qmlmethod void QtLocation::Map::pan(int dx, int dy)

    Starts panning the map by \a dx pixels along the x-axis and
    by \a dy pixels along the y-axis.

    Positive values for \a dx move the map right, negative values left.
    Positive values for \a dy move the map down, negative values up.

    During panning the \l center, and \l zoomLevel may change.
*/
void QDeclarativeGeoMap::pan(int dx, int dy)
{
    if (!m_map)
        return;
    if (dx == 0 && dy == 0)
        return;

    QGeoCoordinate coord = m_map->geoProjection().itemPositionToCoordinate(
                                QDoubleVector2D(m_map->viewportWidth() / 2 + dx,
                                        m_map->viewportHeight() / 2 + dy));
    setCenter(coord);
}


/*!
    \qmlmethod void QtLocation::Map::prefetchData()

    Optional hint that allows the map to prefetch during this idle period
*/
void QDeclarativeGeoMap::prefetchData()
{
    if (!m_map)
        return;
    m_map->prefetchData();
}

/*!
    \qmlmethod void QtLocation::Map::clearData()

    Clears map data collected by the currently selected plugin.
    \note This method will delete cached files.
    \sa plugin
*/
void QDeclarativeGeoMap::clearData()
{
    if (m_map)
        m_map->clearData();
}

/*!
    \qmlmethod void QtLocation::Map::fitViewportToGeoShape(geoShape, margins)

    Fits the viewport to a specific geo shape \a geoShape.
    The \a margins are in screen pixels.

    \note If the projection used by the plugin is not WebMercator, and the plugin does not have fitting to
    shape capability, this method will do nothing.

    \sa visibleRegion
    \since 5.13
*/
void QDeclarativeGeoMap::fitViewportToGeoShape(const QGeoShape &shape, QVariant margins)
{
    QMargins m(10, 10, 10, 10); // lets defaults to 10 if margins is invalid
    switch (static_cast<QMetaType::Type>(margins.type())) {
        case QMetaType::Int:
        case QMetaType::Double: {
            const int value = int(margins.toDouble());
            m = QMargins(value, value, value, value);
        }
        break;
        // ToDo: Support distinct margins in some QML form. Perhaps QRect?
        default:
            break;
    }
    fitViewportToGeoShape(shape, m);
}

void QDeclarativeGeoMap::fitViewportToGeoShape(const QGeoShape &shape, const QMargins &borders)
{
    if (!m_map  || !shape.isValid())
        return;

    if (m_map->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) {
        // This case remains handled here, and not inside QGeoMap*::fitViewportToGeoRectangle,
        // in order to honor animations on center and zoomLevel
        const QMargins margins = borders + mapMargins();
        const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
        const QPair<QGeoCoordinate, qreal> fitData = p.fitViewportToGeoRectangle(shape.boundingGeoRectangle(),
                                                                                 margins);
        if (!fitData.first.isValid())
            return;

        // position camera to the center of bounding box
        setProperty("center", QVariant::fromValue(fitData.first)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property

        if (!qIsFinite(fitData.second))
            return;
        double newZoom = qMax<double>(minimumZoomLevel(), fitData.second);
        setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom)  to honor a possible animation set on the zoomLevel property
    } else if (m_map->capabilities() & QGeoMap::SupportsFittingViewportToGeoRectangle) {
        // Animations cannot be honored in this case, as m_map acts as a black box
        m_map->fitViewportToGeoRectangle(m_visibleRegion, borders);
    }
    // else out of luck
}

/*!
    \qmlproperty string QtLocation::Map::errorString

    This read-only property holds the textual presentation of the latest mapping provider error.
    If no error has occurred, an empty string is returned.

    An empty string may also be returned if an error occurred which has no associated
    textual representation.

    \sa QGeoServiceProvider::errorString()
*/

QString QDeclarativeGeoMap::errorString() const
{
    return m_errorString;
}

/*!
    \qmlproperty enumeration QtLocation::Map::error

    This read-only property holds the last occurred mapping service provider error.

    \list
    \li Map.NoError - No error has occurred.
    \li Map.NotSupportedError -The maps plugin property was not set or there is no mapping manager associated with the plugin.
    \li Map.UnknownParameterError -The plugin did not recognize one of the parameters it was given.
    \li Map.MissingRequiredParameterError - The plugin did not find one of the parameters it was expecting.
    \li Map.ConnectionError - The plugin could not connect to its backend service or database.
    \endlist

    \sa QGeoServiceProvider::Error
*/

QGeoServiceProvider::Error QDeclarativeGeoMap::error() const
{
    return m_error;
}

QGeoMap *QDeclarativeGeoMap::map() const
{
    return m_map;
}

void QDeclarativeGeoMap::itemChange(ItemChange change, const ItemChangeData &value)
{
    if (change == ItemChildAddedChange) {
        QQuickItem *child = value.item;
        QQuickItem *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
        if (!mapItem)
            mapItem = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);

        if (mapItem) {
            qreal z = mapItem->z();
            if (z > m_maxChildZ) { // Ignore children removal
                m_maxChildZ = z;
                // put the copyrights notice object at the highest z order
                if (m_copyrights)
                    m_copyrights->setCopyrightsZ(m_maxChildZ + 1);
            }
        }
    }
    QQuickItem::itemChange(change, value);
}

bool QDeclarativeGeoMap::isInteractive()
{
    return (m_gestureArea->enabled() && m_gestureArea->acceptedGestures()) || m_gestureArea->isActive();
}

void QDeclarativeGeoMap::attachCopyrightNotice(bool initialVisibility)
{
    if (initialVisibility) {
        ++m_copyNoticesVisible;
        if (m_map)
            m_map->setCopyrightVisible(m_copyNoticesVisible > 0);
    }
}

void QDeclarativeGeoMap::detachCopyrightNotice(bool currentVisibility)
{
    if (currentVisibility) {
        --m_copyNoticesVisible;
        if (m_map)
            m_map->setCopyrightVisible(m_copyNoticesVisible > 0);
    }
}

void QDeclarativeGeoMap::onAttachedCopyrightNoticeVisibilityChanged()
{
    QDeclarativeGeoMapCopyrightNotice *copy = static_cast<QDeclarativeGeoMapCopyrightNotice *>(sender());
    m_copyNoticesVisible += ( int(copy->copyrightsVisible()) * 2 - 1);
    if (m_map)
        m_map->setCopyrightVisible(m_copyNoticesVisible > 0);
}

void QDeclarativeGeoMap::onCameraDataChanged(const QGeoCameraData &cameraData)
{
    bool centerHasChanged = cameraData.center() != m_cameraData.center();
    bool bearingHasChanged = cameraData.bearing() != m_cameraData.bearing();
    bool tiltHasChanged = cameraData.tilt() != m_cameraData.tilt();
    bool fovHasChanged = cameraData.fieldOfView() != m_cameraData.fieldOfView();
    bool zoomHasChanged = cameraData.zoomLevel() != m_cameraData.zoomLevel();

    m_cameraData = cameraData;
    // polish map items
    for (const QPointer<QDeclarativeGeoMapItemBase> &i: qAsConst(m_mapItems)) {
        if (i)
            i->baseCameraDataChanged(m_cameraData); // Consider optimizing this further, removing the contained duplicate if conditions.
    }

    if (centerHasChanged)
        emit centerChanged(m_cameraData.center());
    if (zoomHasChanged)
        emit zoomLevelChanged(m_cameraData.zoomLevel());
    if (bearingHasChanged)
        emit bearingChanged(m_cameraData.bearing());
    if (tiltHasChanged)
        emit tiltChanged(m_cameraData.tilt());
    if (fovHasChanged)
        emit fieldOfViewChanged(m_cameraData.fieldOfView());
    if (centerHasChanged || zoomHasChanged || bearingHasChanged
            || tiltHasChanged || fovHasChanged)
        emit visibleRegionChanged();
}

/*!
    \qmlmethod void QtLocation::Map::addMapParameter(MapParameter parameter)

    Adds the \a parameter object to the map. The effect of this call is dependent
    on the combination of the content of the MapParameter and the type of
    underlying QGeoMap. If a MapParameter that is not supported by the underlying
    QGeoMap gets added, the call has no effect.

    The release of this API with Qt 5.9 is a Technology Preview.

    \sa MapParameter, removeMapParameter, mapParameters, clearMapParameters

    \since 5.9
*/
void QDeclarativeGeoMap::addMapParameter(QDeclarativeGeoMapParameter *parameter)
{
    if (!parameter->isComponentComplete()) {
        connect(parameter, &QDeclarativeGeoMapParameter::completed, this, &QDeclarativeGeoMap::addMapParameter);
        return;
    }

    disconnect(parameter);
    if (m_mapParameters.contains(parameter))
        return;
    parameter->setParent(this);
    m_mapParameters.append(parameter); // parameter now owned by QDeclarativeGeoMap
    if (m_map)
        m_map->addParameter(parameter);
}

/*!
    \qmlmethod void QtLocation::Map::removeMapParameter(MapParameter parameter)

    Removes the given \a parameter object from the map.

    The release of this API with Qt 5.9 is a Technology Preview.

    \sa MapParameter, addMapParameter, mapParameters, clearMapParameters

    \since 5.9
*/
void QDeclarativeGeoMap::removeMapParameter(QDeclarativeGeoMapParameter *parameter)
{
    if (!m_mapParameters.contains(parameter))
        return;
    if (m_map)
        m_map->removeParameter(parameter);
    m_mapParameters.removeOne(parameter);
}

/*!
    \qmlmethod void QtLocation::Map::clearMapParameters()

    Removes all map parameters from the map.

    The release of this API with Qt 5.9 is a Technology Preview.

    \sa MapParameter, mapParameters, addMapParameter, removeMapParameter, clearMapParameters

    \since 5.9
*/
void QDeclarativeGeoMap::clearMapParameters()
{
    if (m_map)
        m_map->clearParameters();
    m_mapParameters.clear();
}

/*!
    \qmlproperty list<MapParameters> QtLocation::Map::mapParameters

    Returns the list of all map parameters in no particular order.
    These items include map parameters that were declared statically as part of
    the type declaration, as well as dynamical map parameters (\l addMapParameter).

    The release of this API with Qt 5.9 is a Technology Preview.

    \sa MapParameter, addMapParameter, removeMapParameter, clearMapParameters

    \since 5.9
*/
QList<QObject *> QDeclarativeGeoMap::mapParameters()
{
    QList<QObject *> ret;
    for (QDeclarativeGeoMapParameter *p : qAsConst(m_mapParameters))
        ret << p;
    return ret;
}

/*
    \internal
*/
void QDeclarativeGeoMap::addMapObject(QGeoMapObject *object)
{
    if (!object || object->map())
        return;

    if (!m_initialized) {
        m_pendingMapObjects.append(object);
        return;
    }

    int curObjects = m_map->mapObjects().size();
    // object adds itself to the map
    object->setMap(m_map);

    if (curObjects != m_map->mapObjects().size())
        emit mapObjectsChanged();
}

/*
    \internal
*/
void QDeclarativeGeoMap::removeMapObject(QGeoMapObject *object)
{
    if (!object || object->map() != m_map) // if !initialized this is fine, since both object and m_map are supposed to be NULL
        return;

    if (!m_initialized) {
        m_pendingMapObjects.removeOne(object);
        return;
    }

    int curObjects = m_map->mapObjects().size();
    // object adds itself to the map
    object->setMap(nullptr);

    if (curObjects != m_map->mapObjects().size())
        emit mapObjectsChanged();
}

/*
    \internal
*/
void QDeclarativeGeoMap::clearMapObjects()
{
    if (!m_initialized) {
        m_pendingMapObjects.clear();
    } else {
        const QList<QGeoMapObject *> objs = m_map->mapObjects();
        for (QGeoMapObject *o: objs)
            o->setMap(nullptr);
        if (objs.size())
            emit mapObjectsChanged();
    }
}

/*
    \internal
*/
QList<QGeoMapObject *> QDeclarativeGeoMap::mapObjects()
{
    if (!m_initialized)
        return m_pendingMapObjects;
    else
        return m_map->mapObjects();
}

/*!
    \qmlproperty list<MapItem> QtLocation::Map::mapItems

    Returns the list of all map items in no particular order.
    These items include items that were declared statically as part of
    the type declaration, as well as dynamical items (\l addMapItem,
    \l MapItemView).

    \sa addMapItem, removeMapItem, clearMapItems
*/

QList<QObject *> QDeclarativeGeoMap::mapItems()
{
    QList<QObject *> ret;
    foreach (const QPointer<QDeclarativeGeoMapItemBase> &ptr, m_mapItems) {
        if (ptr)
            ret << ptr.data();
    }
    return ret;
}

/*!
    \qmlmethod void QtLocation::Map::addMapItem(MapItem item)

    Adds the given \a item to the Map (for example MapQuickItem, MapCircle). If the object
    already is on the Map, it will not be added again.

    As an example, consider the case where you have a MapCircle representing your current position:

    \snippet declarative/maps.qml QtQuick import
    \snippet declarative/maps.qml QtLocation import
    \codeline
    \snippet declarative/maps.qml Map addMapItem MapCircle at current position

    \note MapItemViews cannot be added with this method.

    \sa mapItems, removeMapItem, clearMapItems
*/

void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item)
{
    if (addMapItem_real(item))
        emit mapItemsChanged();
}

bool QDeclarativeGeoMap::addMapItem_real(QDeclarativeGeoMapItemBase *item)
{
    if (!item || item->quickMap())
        return false;
    // If the item comes from a MapItemGroup, do not reparent it.
    if (!qobject_cast<QDeclarativeGeoMapItemGroup *>(item->parentItem()))
        item->setParentItem(this);
    m_mapItems.append(item);
    if (m_map) {
        item->setMap(this, m_map);
        m_map->addMapItem(item);
    }
    return true;
}

/*!
    \qmlmethod void QtLocation::Map::removeMapItem(MapItem item)

    Removes the given \a item from the Map (for example MapQuickItem, MapCircle). If
    the MapItem does not exist or was not previously added to the map, the
    method does nothing.

    \sa mapItems, addMapItem, clearMapItems
*/
void QDeclarativeGeoMap::removeMapItem(QDeclarativeGeoMapItemBase *ptr)
{
    if (removeMapItem_real(ptr))
        emit mapItemsChanged();
}

bool QDeclarativeGeoMap::removeMapItem_real(QDeclarativeGeoMapItemBase *ptr)
{
    if (!ptr)
        return false;
    QPointer<QDeclarativeGeoMapItemBase> item(ptr);
    if (!m_mapItems.contains(item))
        return false;
    if (m_map)
        m_map->removeMapItem(ptr);
    if (item->parentItem() == this)
        item->setParentItem(0);
    item->setMap(0, 0);
    // these can be optimized for perf, as we already check the 'contains' above
    m_mapItems.removeOne(item);
    return true;
}

/*!
    \qmlmethod void QtLocation::Map::clearMapItems()

    Removes all items and item groups from the map.

    \sa mapItems, addMapItem, removeMapItem, addMapItemGroup, removeMapItemGroup
*/
void QDeclarativeGeoMap::clearMapItems()
{
    if (m_mapItems.isEmpty())
        return;

    int removed = 0;
    for (auto i : qAsConst(m_mapItemGroups)) {
        // Processing only top-level groups (!views)
        QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(i);
        if (view)
            continue;

        if (i->parentItem() != this)
            continue;

        removed += removeMapItemGroup_real(i);
    }

    for (auto i : qAsConst(m_mapItems))
        removed += removeMapItem_real(i);

    if (removed)
        emit mapItemsChanged();
}

/*!
    \qmlmethod void QtLocation::Map::addMapItemGroup(MapItemGroup itemGroup)

    Adds the map items contained in the given \a itemGroup to the Map
    (for example MapQuickItem, MapCircle).

    \sa MapItemGroup, removeMapItemGroup

    \since 5.9
*/
void QDeclarativeGeoMap::addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
{
    if (addMapItemGroup_real(itemGroup))
        emit mapItemsChanged();
}

bool QDeclarativeGeoMap::addMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup)
{
    if (!itemGroup || itemGroup->quickMap()) // Already added to some map
        return false;

    itemGroup->setQuickMap(this);

    if (!isGroupNested(itemGroup))
        itemGroup->setParentItem(this);

    QPointer<QDeclarativeGeoMapItemGroup> g(itemGroup);
    m_mapItemGroups.append(g);

    const QList<QQuickItem *> quickKids = itemGroup->childItems();
    int count = 0;
    for (auto c: quickKids) {
        count += addMapChild(c); // this calls addMapItemGroup recursively, if needed
    }
    return count;
}

/*!
    \qmlmethod void QtLocation::Map::removeMapItemGroup(MapItemGroup itemGroup)

    Removes \a itemGroup and the items contained therein from the Map.

    \sa MapItemGroup, addMapItemGroup

    \since 5.9
*/
void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
{
    if (removeMapItemGroup_real(itemGroup))
        emit mapItemsChanged();
}

bool QDeclarativeGeoMap::removeMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup)
{
    if (!itemGroup || itemGroup->quickMap() != this) // cant remove an itemGroup added to another map
        return false;

    QPointer<QDeclarativeGeoMapItemGroup> g(itemGroup);
    if (!m_mapItemGroups.removeOne(g))
        return false;

    const QList<QQuickItem *> quickKids = itemGroup->childItems();
    int count = 0;
    for (auto c: quickKids) {
        count += removeMapChild(c);
    }
    itemGroup->setQuickMap(nullptr);
    if (itemGroup->parentItem() == this)
        itemGroup->setParentItem(0);
    return count;
}

/*!
    \qmlmethod void QtLocation::Map::removeMapItemView(MapItemView itemView)

    Removes \a itemView and the items instantiated by it from the Map.

    \sa MapItemView, addMapItemView

    \since 5.10
*/
void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView)
{
    if (removeMapItemView_real(itemView))
        emit mapItemsChanged();
}

bool QDeclarativeGeoMap::removeMapItemView_real(QDeclarativeGeoMapItemView *itemView)
{
    if (!itemView || itemView->m_map != this) // can't remove a view that is already added to another map
        return false;

    itemView->removeInstantiatedItems(false); // remove the items without using transitions AND abort ongoing ones
    itemView->m_map = 0;
    m_mapViews.removeOne(itemView);
    return removeMapItemGroup_real(itemView); // at this point, all delegate instances have been removed.
}

void QDeclarativeGeoMap::updateItemToWindowTransform()
{
    if (!m_initialized)
        return;

    // Update itemToWindowTransform into QGeoProjection
    const QTransform item2WindowOld = m_map->geoProjection().itemToWindowTransform();
    QTransform item2Window = QQuickItemPrivate::get(this)->itemToWindowTransform();
    if (!property("layer").isNull() && property("layer").value<QObject *>()->property("enabled").toBool())
        item2Window.reset(); // When layer is enabled, the item is rendered offscreen with no transformation, then the layer is applied

    m_map->setItemToWindowTransform(item2Window);

    // This method is called at every redraw, including those redraws not generated by
    // sgNodeChanged.
    // In these cases, *if* the item2windowTransform has changed (e.g., if transformation of
    // the item or one of its ancestors changed), a forced update of the map items using accelerated
    // GL implementation has to be performed in order to have them pulling the updated itemToWindowTransform.
    if (!m_sgNodeHasChanged && item2WindowOld != item2Window) {
        for (auto i: qAsConst(m_mapItems))
            i->setMaterialDirty();
    }

    m_sgNodeHasChanged = false;
}

void QDeclarativeGeoMap::onSGNodeChanged()
{
    m_sgNodeHasChanged = true;
    update();
}

/*!
    \qmlmethod void QtLocation::Map::addMapItemView(MapItemView itemView)

    Adds \a itemView to the Map.

    \sa MapItemView, removeMapItemView

    \since 5.10
*/
void QDeclarativeGeoMap::addMapItemView(QDeclarativeGeoMapItemView *itemView)
{
    if (addMapItemView_real(itemView))
        emit mapItemsChanged();
}

bool QDeclarativeGeoMap::addMapItemView_real(QDeclarativeGeoMapItemView *itemView)
{
    if (!itemView || itemView->m_map) // can't add a view twice
        return false;

    int count = addMapItemGroup_real(itemView); // at this point, delegates aren't yet incubated.
    // Not appending it to m_mapViews because it seems unnecessary even if the
    // itemView is a child of this (in which case it would be destroyed
    m_mapViews.append(itemView);
    setupMapView(itemView);
    return count;
}

/*!
    \qmlproperty MapType QtLocation::Map::activeMapType

    \brief Access to the currently active \l{MapType}{map type}.

    This property can be set to change the active \l{MapType}{map type}.
    See the \l{Map::supportedMapTypes}{supportedMapTypes} property for possible values.

    \sa MapType
*/
void QDeclarativeGeoMap::setActiveMapType(QDeclarativeGeoMapType *mapType)
{
    if (m_activeMapType->mapType() != mapType->mapType()) {
        if (m_map) {
            if (mapType->mapType().pluginName() == m_plugin->name().toLatin1()) {
                m_map->setActiveMapType(mapType->mapType());
                m_activeMapType = mapType;
                emit activeMapTypeChanged();
            }
        } else {
            m_activeMapType = mapType;
            emit activeMapTypeChanged();
        }
    }
}

QDeclarativeGeoMapType * QDeclarativeGeoMap::activeMapType() const
{
    return m_activeMapType;
}

/*!
    \internal
*/
void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    m_gestureArea->setSize(newGeometry.size());
    QQuickItem::geometryChanged(newGeometry, oldGeometry);

    if (!m_map || newGeometry.size().isEmpty())
        return;

    m_map->setViewportSize(newGeometry.size().toSize());

    if (!m_initialized) {
        initialize();
    } else {
        setMinimumZoomLevel(m_map->minimumZoom(), false);

        // Update the center latitudinal threshold
        QGeoCameraData cameraData = m_map->cameraData();
        const double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(cameraData);
        const double minimumCenterLatitudeAtZoom = m_map->minimumCenterLatitudeAtZoom(cameraData);
        if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude
                || minimumCenterLatitudeAtZoom != m_minimumViewportLatitude) {
            m_maximumViewportLatitude = maximumCenterLatitudeAtZoom;
            m_minimumViewportLatitude = minimumCenterLatitudeAtZoom;
            QGeoCoordinate coord = cameraData.center();
            coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
            cameraData.setCenter(coord);
            m_map->setCameraData(cameraData); // this polishes map items
        } else if (oldGeometry.size() != newGeometry.size()) {
            // polish map items
            for (const QPointer<QDeclarativeGeoMapItemBase> &i: qAsConst(m_mapItems)) {
                if (i)
                    i->polishAndUpdate();
            }
        }
    }

    /*
        The fitViewportTo*() functions depend on a valid map geometry.
        If they were called prior to the first resize they cause
        the zoomlevel to jump to 0 (showing the world). Therefore the
        calls were queued up until now.

        Multiple fitViewportTo*() calls replace each other.
     */
    if (m_pendingFitViewport && width() && height()) {
        fitViewportToGeoShape(m_visibleRegion);
        m_pendingFitViewport = false;
    }

}

/*!
    \qmlmethod void QtLocation::Map::fitViewportToMapItems(list<MapItems> items = {})

    If no argument is provided, fits the current viewport to the boundary of all map items.
    The camera is positioned in the center of the map items, and at the largest integral zoom level
    possible which allows all map items to be visible on screen.
    If \a items is provided, fits the current viewport to the boundary of the specified map items only.

    \note This method gained the optional \a items argument since Qt 5.15.
    In previous releases, this method fitted the map to all map items.

    \sa fitViewportToVisibleMapItems
*/
void QDeclarativeGeoMap::fitViewportToMapItems(const QVariantList &items)
{
    if (items.size()) {
        QList<QPointer<QDeclarativeGeoMapItemBase> > itms;
        for (const QVariant &i: items) {
            QDeclarativeGeoMapItemBase *itm = qobject_cast<QDeclarativeGeoMapItemBase *>(i.value<QObject *>());
            if (itm)
                itms.append(itm);
        }
        fitViewportToMapItemsRefine(itms, true, false);
    } else {
        fitViewportToMapItemsRefine(m_mapItems, true, false);
    }
}

/*!
    \qmlmethod void QtLocation::Map::fitViewportToVisibleMapItems()

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

    \sa fitViewportToMapItems
*/
void QDeclarativeGeoMap::fitViewportToVisibleMapItems()
{
    fitViewportToMapItemsRefine(m_mapItems, true, true);
}

/*!
    \internal
*/
void QDeclarativeGeoMap::fitViewportToMapItemsRefine(const QList<QPointer<QDeclarativeGeoMapItemBase> > &mapItems,
                                                     bool refine,
                                                     bool onlyVisible)
{
    if (!m_map)
        return;

    if (mapItems.size() == 0)
        return;

    double minX = qInf();
    double maxX = -qInf();
    double minY = qInf();
    double maxY = -qInf();
    double topLeftX = 0;
    double topLeftY = 0;
    double bottomRightX = 0;
    double bottomRightY = 0;
    bool haveQuickItem = false;

    // find bounds of all map items
    int itemCount = 0;
    for (int i = 0; i < mapItems.count(); ++i) {
        if (!mapItems.at(i))
            continue;
        QDeclarativeGeoMapItemBase *item = mapItems.at(i).data();
        if (!item || (onlyVisible && (!item->isVisible() || item->mapItemOpacity() <= 0.0)))
            continue;

        // skip quick items in the first pass and refine the fit later
        QDeclarativeGeoMapQuickItem *quickItem =
                qobject_cast<QDeclarativeGeoMapQuickItem*>(item);
        if (refine && quickItem) {
                haveQuickItem = true;
                continue;
        }
        // Force map items to update immediately. Needed to ensure correct item size and positions
        // when recursively calling this function.
        // TODO: See if we really need updatePolish on delegated items, in particular
        // in relation to
        // a) fitViewportToMapItems
        // b) presence of MouseArea
        //
        // This is also legacy code. It must be updated to not operate on screen sizes.
        if (item->isPolishScheduled())
           item->updatePolish();

        if (quickItem && quickItem->matrix_ && !quickItem->matrix_->m_matrix.isIdentity()) {
            // TODO: recalculate the center/zoom level so that the item becomes projectable again
            if (quickItem->zoomLevel() == 0.0) // the item is unprojectable, should be skipped.
                continue;

            QRectF brect = item->boundingRect();
            brect = quickItem->matrix_->m_matrix.mapRect(brect);
            QPointF transformedPosition = quickItem->matrix_->m_matrix * item->position();
            topLeftX = transformedPosition.x();
            topLeftY = transformedPosition.y();
            bottomRightX = topLeftX + brect.width();
            bottomRightY = topLeftY + brect.height();
        } else {
            topLeftX = item->position().x();
            topLeftY = item->position().y();
            bottomRightX = topLeftX + item->width();
            bottomRightY = topLeftY + item->height();
        }

        minX = qMin(minX, topLeftX);
        maxX = qMax(maxX, bottomRightX);
        minY = qMin(minY, topLeftY);
        maxY = qMax(maxY, bottomRightY);

        ++itemCount;
    }

    if (itemCount == 0) {
        if (haveQuickItem)
            fitViewportToMapItemsRefine(mapItems, false, onlyVisible);
        return;
    }
    double bboxWidth = maxX - minX;
    double bboxHeight = maxY - minY;
    double bboxCenterX = minX + (bboxWidth / 2.0);
    double bboxCenterY = minY + (bboxHeight / 2.0);

    // position camera to the center of bounding box
    QGeoCoordinate coordinate;
    coordinate = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(bboxCenterX, bboxCenterY), false);
    setProperty("center", QVariant::fromValue(coordinate));

    // 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(), (zoomLevel() + newZoom)));
    setProperty("zoomLevel", QVariant::fromValue(newZoom));

    // as map quick items retain the same screen size after the camera zooms in/out
    // we refine the viewport again to achieve better results
    if (refine)
        fitViewportToMapItemsRefine(mapItems, false, onlyVisible);
}

/*!
    \internal
*/
void QDeclarativeGeoMap::mousePressEvent(QMouseEvent *event)
{
    if (isInteractive())
        m_gestureArea->handleMousePressEvent(event);
    else
        QQuickItem::mousePressEvent(event);
}

/*!
    \internal
*/
void QDeclarativeGeoMap::mouseMoveEvent(QMouseEvent *event)
{
    if (isInteractive())
        m_gestureArea->handleMouseMoveEvent(event);
    else
        QQuickItem::mouseMoveEvent(event);
}

/*!
    \internal
*/
void QDeclarativeGeoMap::mouseReleaseEvent(QMouseEvent *event)
{
    if (isInteractive())
        m_gestureArea->handleMouseReleaseEvent(event);
    else
        QQuickItem::mouseReleaseEvent(event);
}

/*!
    \internal
*/
void QDeclarativeGeoMap::mouseUngrabEvent()
{
    if (isInteractive())
        m_gestureArea->handleMouseUngrabEvent();
    else
        QQuickItem::mouseUngrabEvent();
}

void QDeclarativeGeoMap::touchUngrabEvent()
{
    if (isInteractive())
        m_gestureArea->handleTouchUngrabEvent();
    else
        QQuickItem::touchUngrabEvent();
}

/*!
    \internal
*/
void QDeclarativeGeoMap::touchEvent(QTouchEvent *event)
{
    if (isInteractive()) {
        m_gestureArea->handleTouchEvent(event);
    } else {
        //ignore event so sythesized event is generated;
        QQuickItem::touchEvent(event);
    }
}

#if QT_CONFIG(wheelevent)
/*!
    \internal
*/
void QDeclarativeGeoMap::wheelEvent(QWheelEvent *event)
{
    if (isInteractive())
        m_gestureArea->handleWheelEvent(event);
    else
        QQuickItem::wheelEvent(event);

}
#endif

/*!
    \internal
*/
bool QDeclarativeGeoMap::childMouseEventFilter(QQuickItem *item, QEvent *event)
{
    Q_UNUSED(item);
    if (!isVisible() || !isEnabled() || !isInteractive())
        return QQuickItem::childMouseEventFilter(item, event);

    switch (event->type()) {
    case QEvent::MouseButtonPress:
    case QEvent::MouseMove:
    case QEvent::MouseButtonRelease:
        return sendMouseEvent(static_cast<QMouseEvent *>(event));
    case QEvent::UngrabMouse: {
        QQuickWindow *win = window();
        if (!win) break;
        if (!win->mouseGrabberItem() ||
                (win->mouseGrabberItem() &&
                 win->mouseGrabberItem() != this)) {
            // child lost grab, we could even lost
            // some events if grab already belongs for example
            // in item in diffrent window , clear up states
            mouseUngrabEvent();
        }
        break;
    }
    case QEvent::TouchBegin:
    case QEvent::TouchUpdate:
    case QEvent::TouchEnd:
    case QEvent::TouchCancel:
        if (static_cast<QTouchEvent *>(event)->touchPoints().count() >= 2) {
            // 1 touch point = handle with MouseEvent (event is always synthesized)
            // let the synthesized mouse event grab the mouse,
            // note there is no mouse grabber at this point since
            // touch event comes first (see Qt::AA_SynthesizeMouseForUnhandledTouchEvents)
            return sendTouchEvent(static_cast<QTouchEvent *>(event));
        }
    default:
        break;
    }
    return QQuickItem::childMouseEventFilter(item, event);
}

bool QDeclarativeGeoMap::sendMouseEvent(QMouseEvent *event)
{
    QPointF localPos = mapFromScene(event->windowPos());
    QQuickWindow *win = window();
    QQuickItem *grabber = win ? win->mouseGrabberItem() : 0;
    bool stealEvent = m_gestureArea->isActive();

    if ((stealEvent || contains(localPos)) && (!grabber || (!grabber->keepMouseGrab() && !grabber->keepTouchGrab()))) {
        QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
        mouseEvent->setAccepted(false);

        switch (mouseEvent->type()) {
        case QEvent::MouseMove:
            m_gestureArea->handleMouseMoveEvent(mouseEvent.data());
            break;
        case QEvent::MouseButtonPress:
            m_gestureArea->handleMousePressEvent(mouseEvent.data());
            break;
        case QEvent::MouseButtonRelease:
            m_gestureArea->handleMouseReleaseEvent(mouseEvent.data());
            break;
        default:
            break;
        }

        stealEvent = m_gestureArea->isActive();
        grabber = win ? win->mouseGrabberItem() : 0;

        if (grabber && stealEvent && !grabber->keepMouseGrab() && !grabber->keepTouchGrab() && grabber != this)
            grabMouse();

        if (stealEvent) {
            //do not deliver
            event->setAccepted(true);
            return true;
        } else {
            return false;
        }
    }

    return false;
}

bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event)
{
    QQuickPointerDevice *touchDevice = QQuickPointerDevice::touchDevice(event->device());
    const QTouchEvent::TouchPoint &point = event->touchPoints().first();
    QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window());

    auto touchPointGrabberItem = [touchDevice, windowPriv](const QTouchEvent::TouchPoint &point) -> QQuickItem* {
        if (QQuickEventPoint *eventPointer = windowPriv->pointerEventInstance(touchDevice)->pointById(point.id()))
            return eventPointer->grabberItem();
        return nullptr;
    };

    QQuickItem *grabber = touchPointGrabberItem(point);

    bool stealEvent = m_gestureArea->isActive();
    bool containsPoint = contains(mapFromScene(point.scenePos()));

    if ((stealEvent || containsPoint) && (!grabber || !grabber->keepTouchGrab())) {
        QScopedPointer<QTouchEvent> touchEvent(new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints()));
        touchEvent->setTimestamp(event->timestamp());
        touchEvent->setAccepted(false);

        m_gestureArea->handleTouchEvent(touchEvent.data());
        stealEvent = m_gestureArea->isActive();
        grabber = touchPointGrabberItem(point);

        if (grabber && stealEvent && !grabber->keepTouchGrab() && grabber != this) {
            QVector<int> ids;
            foreach (const QTouchEvent::TouchPoint &tp, event->touchPoints()) {
                if (!(tp.state() & Qt::TouchPointReleased)) {
                    ids.append(tp.id());
                }
            }
            grabTouchPoints(ids);
        }

        if (stealEvent) {
            //do not deliver
            event->setAccepted(true);
            return true;
        } else {
            return false;
        }
    }

    return false;
}

QT_END_NAMESPACE
