/**************************************************************************** ** ** Copyright (C) 2014 Aaron McCarthy ** 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 "qdeclarativegeomapcopyrightsnotice_p.h" #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QDeclarativeGeoMapCopyrightNoticePrivate: public QQuickPaintedItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeGeoMapCopyrightNotice) public: void setVisible(bool visible) override; }; /*! \qmltype MapCopyrightNotice \instantiates QDeclarativeGeoMapCopyrightNotice \inqmlmodule QtLocation \ingroup qml-QtLocation5-maps \since QtLocation 5.9 \brief The MapCopyrightNotice item displays the current valid copyright notice for a Map element. This object can be used to place an additional copyright notices programmatically. Note that declaring a MapCopyrightNotice inside a QtLocation::Map element is not possible, like for any other QQuickItem. The release of this API with Qt 5.9 is a Technology Preview. */ /*! \qmlproperty Map QtLocation::MapCopyrightNotice::mapSource This property holds the current map source providing the copyright data shown in this notice. In order to let the MapCopyrightNotice display a copyright, this property must be set, as it is the only data source for this element. */ /*! \qmlproperty string QtLocation::MapCopyrightNotice::styleSheet This property holds the current css2.1 style sheet used to style the copyright notice, if in HTML form. Example: \code MapCopyrightNotice { mapSource: myMap styleSheet: "body { color : green; font-family: \"Lucida\"; font-size: 8px} a{ font-size: 8px; color:#A62900}" } \endcode */ QDeclarativeGeoMapCopyrightNotice::QDeclarativeGeoMapCopyrightNotice(QQuickItem *parent) : QQuickPaintedItem(parent), m_copyrightsHtml(0), m_copyrightsVisible(true), m_mapSource(0), m_userDefinedStyleSheet(false) { // If this item is constructed inside the map, automatically anchor it where it always used to be. if (qobject_cast(parent)) anchorToBottomLeft(); } QDeclarativeGeoMapCopyrightNotice::~QDeclarativeGeoMapCopyrightNotice() { setMapSource(nullptr); } void QDeclarativeGeoMapCopyrightNotice::anchorToBottomLeft() { if (!parent()) return; QQuickAnchors *anchors = property("anchors").value(); if (anchors) { anchors->setLeft(QQuickAnchorLine(qobject_cast(parent()), QQuickAnchors::LeftAnchor)); anchors->setBottom(QQuickAnchorLine(qobject_cast(parent()), QQuickAnchors::BottomAnchor)); } } void QDeclarativeGeoMapCopyrightNotice::setMapSource(QDeclarativeGeoMap *map) { if (m_mapSource == map) return; if (m_mapSource) { // disconnect this object from current map source m_mapSource->detachCopyrightNotice(copyrightsVisible()); m_mapSource->disconnect(this); m_mapSource->m_map->disconnect(this); if (m_copyrightsHtml) m_copyrightsHtml->clear(); m_copyrightsImage = QImage(); m_mapSource = nullptr; } if (map) { m_mapSource = map; m_mapSource->attachCopyrightNotice(copyrightsVisible()); connect(this, &QDeclarativeGeoMapCopyrightNotice::copyrightsVisibleChanged, mapSource(), &QDeclarativeGeoMap::onAttachedCopyrightNoticeVisibilityChanged); // First update the copyright. Only Image will do here, no need to store HTML right away. if (m_mapSource->m_copyrights && !m_mapSource->m_copyrights->m_copyrightsImage.isNull()) m_copyrightsImage = m_mapSource->m_copyrights->m_copyrightsImage; connect(mapSource(), SIGNAL(copyrightsChanged(QImage)), this, SLOT(copyrightsChanged(QImage))); connect(mapSource(), SIGNAL(copyrightsChanged(QString)), this, SLOT(copyrightsChanged(QString))); if (m_mapSource->m_map) connectMap(); else connect(mapSource(), &QDeclarativeGeoMap::mapReadyChanged, this, &QDeclarativeGeoMapCopyrightNotice::connectMap); } } void QDeclarativeGeoMapCopyrightNotice::connectMap() { connect(m_mapSource->m_map, SIGNAL(copyrightsStyleSheetChanged(QString)), this, SLOT(onCopyrightsStyleSheetChanged(QString))); connect(this, SIGNAL(linkActivated(QString)), mapSource(), SIGNAL(copyrightLinkActivated(QString))); onCopyrightsStyleSheetChanged(m_mapSource->m_map->copyrightsStyleSheet()); update(); emit mapSourceChanged(); } QDeclarativeGeoMap *QDeclarativeGeoMapCopyrightNotice::mapSource() { return m_mapSource.data(); } QString QDeclarativeGeoMapCopyrightNotice::styleSheet() const { return m_styleSheet; } void QDeclarativeGeoMapCopyrightNotice::setStyleSheet(const QString &styleSheet) { m_userDefinedStyleSheet = true; if (styleSheet == m_styleSheet) return; m_styleSheet = styleSheet; if (!m_html.isEmpty() && m_copyrightsHtml) { delete m_copyrightsHtml; createCopyright(); #if QT_CONFIG(texthtmlparser) m_copyrightsHtml->setHtml(m_html); #else m_copyrightsHtml->setPlainText(m_html); #endif } rasterizeHtmlAndUpdate(); emit styleSheetChanged(m_styleSheet); } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::paint(QPainter *painter) { painter->drawImage(0, 0, m_copyrightsImage); } void QDeclarativeGeoMapCopyrightNotice::mousePressEvent(QMouseEvent *event) { if (m_copyrightsHtml) { m_activeAnchor = m_copyrightsHtml->documentLayout()->anchorAt(event->pos()); if (!m_activeAnchor.isEmpty()) return; } QQuickPaintedItem::mousePressEvent(event); } void QDeclarativeGeoMapCopyrightNotice::mouseReleaseEvent(QMouseEvent *event) { if (m_copyrightsHtml) { QString anchor = m_copyrightsHtml->documentLayout()->anchorAt(event->pos()); if (anchor == m_activeAnchor && !anchor.isEmpty()) { emit linkActivated(anchor); m_activeAnchor.clear(); } } } void QDeclarativeGeoMapCopyrightNotice::rasterizeHtmlAndUpdate() { if (!m_copyrightsHtml || m_copyrightsHtml->isEmpty()) return; m_copyrightsImage = QImage(m_copyrightsHtml->size().toSize(), QImage::Format_ARGB32_Premultiplied); m_copyrightsImage.fill(qPremultiply(QColor(Qt::transparent).rgba())); QPainter painter(&m_copyrightsImage); QAbstractTextDocumentLayout::PaintContext ctx; ctx.palette.setColor(QPalette::Text, QStringLiteral("black")); m_copyrightsHtml->documentLayout()->draw(&painter, ctx); setImplicitSize(m_copyrightsImage.width(), m_copyrightsImage.height()); setContentsSize(m_copyrightsImage.size()); setKeepMouseGrab(true); setAcceptedMouseButtons(Qt::LeftButton); update(); } void QDeclarativeGeoMapCopyrightNotice::createCopyright() { m_copyrightsHtml = new QTextDocument(this); #if QT_CONFIG(cssparser) if (!m_styleSheet.isEmpty()) m_copyrightsHtml->setDefaultStyleSheet(m_styleSheet); #endif // The default 4 makes the copyright too wide and tall. m_copyrightsHtml->setDocumentMargin(0); } void QDeclarativeGeoMapCopyrightNoticePrivate::setVisible(bool visible) { Q_Q(QDeclarativeGeoMapCopyrightNotice); q->m_copyrightsVisible = visible; QQuickItemPrivate::setVisible(visible); } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::setCopyrightsVisible(bool visible) { Q_D(QDeclarativeGeoMapCopyrightNotice); if (visible == m_copyrightsVisible) return; m_copyrightsVisible = visible; d->QQuickItemPrivate::setVisible(!m_copyrightsImage.isNull() && visible); emit copyrightsVisibleChanged(); } bool QDeclarativeGeoMapCopyrightNotice::copyrightsVisible() const { return m_copyrightsVisible; } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::setCopyrightsZ(qreal copyrightsZ) { setZ(copyrightsZ); update(); } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QImage ©rightsImage) { Q_D(QDeclarativeGeoMapCopyrightNotice); delete m_copyrightsHtml; m_copyrightsHtml = 0; m_copyrightsImage = copyrightsImage; setImplicitSize(m_copyrightsImage.width(), m_copyrightsImage.height()); setKeepMouseGrab(false); setAcceptedMouseButtons(Qt::NoButton); d->QQuickItemPrivate::setVisible(m_copyrightsVisible && !m_copyrightsImage.isNull()); update(); } void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QString ©rightsHtml) { Q_D(QDeclarativeGeoMapCopyrightNotice); if (copyrightsHtml.isEmpty()) { d->QQuickItemPrivate::setVisible(false); return; } else { d->QQuickItemPrivate::setVisible(m_copyrightsVisible); } // Divfy, so we can style the background. The extra is a // workaround to QTBUG-58838 and should be removed when it gets fixed. #if QT_CONFIG(texthtmlparser) m_html = QStringLiteral(""); #else m_html = copyrightsHtml; #endif if (!m_copyrightsHtml) createCopyright(); #if QT_CONFIG(texthtmlparser) m_copyrightsHtml->setHtml(m_html); #else m_copyrightsHtml->setPlainText(m_html); #endif rasterizeHtmlAndUpdate(); } void QDeclarativeGeoMapCopyrightNotice::onCopyrightsStyleSheetChanged(const QString &styleSheet) { if (m_userDefinedStyleSheet || styleSheet == m_styleSheet) return; m_styleSheet = styleSheet; if (!m_html.isEmpty() && m_copyrightsHtml) { delete m_copyrightsHtml; createCopyright(); #if QT_CONFIG(texthtmlparser) m_copyrightsHtml->setHtml(m_html); #else m_copyrightsHtml->setPlainText(m_html); #endif } rasterizeHtmlAndUpdate(); emit styleSheetChanged(m_styleSheet); } QT_END_NAMESPACE