| /**************************************************************************** |
| ** |
| ** Copyright (C) 2018 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 "qmapiconobjectqsg_p_p.h" |
| #include <QtQuick/qsgimagenode.h> |
| #include <QtQuick/qsgnode.h> |
| #include <QtQuick/private/qquickimage_p.h> |
| #include <QtQuick/qquickimageprovider.h> |
| #include <QtQuick/qquickwindow.h> |
| #include <QtQml/qqmlengine.h> |
| #include <QtQml/qqml.h> |
| #include <QtNetwork/qnetworkaccessmanager.h> |
| #include <QtLocation/private/qdeclarativepolylinemapitem_p.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| class RootNode : public QSGTransformNode, public VisibleNode |
| { |
| public: |
| RootNode() { } |
| |
| bool isSubtreeBlocked() const override |
| { |
| return subtreeBlocked(); |
| } |
| }; |
| |
| QMapIconObjectPrivateQSG::QMapIconObjectPrivateQSG(QGeoMapObject *q) |
| : QMapIconObjectPrivateDefault(q) |
| { |
| |
| } |
| |
| QMapIconObjectPrivateQSG::QMapIconObjectPrivateQSG(const QMapIconObjectPrivate &other) |
| : QMapIconObjectPrivateDefault(other) |
| { |
| // Data already cloned by the *Default copy constructor, but necessary |
| // update operations triggered only by setters overrides |
| setContent(content()); |
| // setCoordinate(coordinate()); |
| } |
| |
| QMapIconObjectPrivateQSG::~QMapIconObjectPrivateQSG() |
| { |
| if (m_map) |
| m_map->removeMapObject(q); |
| } |
| |
| void QMapIconObjectPrivateQSG::updateGeometry() |
| { |
| if (!m_map) |
| return; |
| |
| m_geometryDirty = true; |
| const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection()); |
| |
| m_itemPosition = p.coordinateToItemPosition(coordinate()); |
| if (m_itemPosition.isFinite()) { |
| m_transformation.setToIdentity(); |
| m_transformation.translate(QVector3D(m_itemPosition.x(), m_itemPosition.y(), 0)); |
| } |
| |
| // TODO: support and test for zoomLevel |
| } |
| |
| QSGNode *QMapIconObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, |
| VisibleNode **visibleNode, |
| QSGNode *root, |
| QQuickWindow *window) |
| { |
| Q_UNUSED(visibleNode); |
| bool created = false; |
| RootNode *node = static_cast<RootNode *>(oldNode); |
| if (!node) { |
| node = new RootNode(); |
| m_imageNode = window->createImageNode(); |
| m_imageNode->setOwnsTexture(true); |
| node->appendChildNode(m_imageNode); |
| *visibleNode = static_cast<VisibleNode *>(node); |
| created = true; |
| } |
| |
| if (m_imageDirty) { |
| m_imageDirty = false; |
| m_imageNode->setTexture(window->createTextureFromImage(m_image)); |
| QRect rect = m_image.rect(); |
| m_imageNode->setSourceRect(rect); |
| m_imageNode->setRect(QRectF(QPointF(0,0), iconSize())); |
| } |
| |
| if (m_geometryDirty) { |
| m_geometryDirty = false; |
| if (!m_itemPosition.isFinite()) { |
| node->setSubtreeBlocked(true); |
| } else { |
| node->setSubtreeBlocked(false); |
| node->setMatrix(m_transformation); |
| } |
| } |
| |
| if (created) |
| root->appendChildNode(node); |
| |
| return node; |
| } |
| |
| void QMapIconObjectPrivateQSG::setCoordinate(const QGeoCoordinate &coordinate) |
| { |
| QMapIconObjectPrivateDefault::setCoordinate(coordinate); |
| updateGeometry(); |
| } |
| |
| template<typename T> |
| static T *getContent(const QVariant &content) |
| { |
| QObject *obj = qvariant_cast<QObject *>(content); |
| return qobject_cast<T *>(obj); |
| } |
| |
| static inline QString imageId(const QUrl &url) |
| { |
| return url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1); |
| } |
| |
| void QMapIconObjectPrivateQSG::clearContent() |
| { |
| m_image = QImage(); |
| } |
| |
| void QMapIconObjectPrivateQSG::setContent(const QVariant &content) |
| { |
| // First reset all local containers |
| clearContent(); |
| QQmlEngine *engine = qmlEngine(q); |
| |
| // Then pull the new content |
| QMapIconObjectPrivateDefault::setContent(content); |
| switch (content.type()) { |
| case QVariant::UserType: { |
| // TODO: Handle QObject subclasses -- first decide which ones |
| break; |
| } |
| case QVariant::String: |
| case QVariant::Url: { |
| // URL, including image/texture providers |
| // Supporting only image providers for now |
| const QUrl url = content.toUrl(); |
| if (!url.isValid()) { |
| m_image = QImage(content.toString()); |
| m_imageDirty = true; |
| updateGeometry(); |
| } else if (url.scheme().isEmpty() || url.scheme() == QLatin1String("file")) { |
| m_image = QImage(url.toString(QUrl::RemoveScheme)); |
| m_imageDirty = true; |
| updateGeometry(); |
| } else if (url.scheme() == QLatin1String("image")) { |
| QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(engine->imageProvider(url.host())); |
| QSize outSize; |
| m_image = provider->requestImage(imageId(url), &outSize, QSize()); |
| if (outSize.isEmpty()) |
| break; |
| m_imageDirty = true; |
| updateGeometry(); |
| } else { // ToDo: Use QNAM |
| |
| } |
| |
| break; |
| } |
| case QVariant::ByteArray: { |
| // ToDo: Build the image from bytearray |
| break; |
| } |
| default: |
| qWarning() << "Unsupported parameter type: " << content.type(); |
| break; |
| } |
| |
| if (m_map && m_imageDirty) |
| emit m_map->sgNodeChanged(); |
| } |
| |
| void QMapIconObjectPrivateQSG::setIconSize(const QSizeF &size) |
| { |
| QMapIconObjectPrivateDefault::setIconSize(size); |
| updateGeometry(); |
| } |
| |
| QGeoMapObjectPrivate *QMapIconObjectPrivateQSG::clone() |
| { |
| return new QMapIconObjectPrivateQSG(static_cast<QMapIconObjectPrivate &>(*this)); |
| } |
| |
| QT_END_NAMESPACE |