/**************************************************************************** ** ** 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 QT_BEGIN_NAMESPACE /*! \qmltype MapCopyrightNotice \instantiates QDeclarativeGeoMapCopyrightNotice \inqmlmodule QtLocation \ingroup qml-QtLocation5-maps \since Qt Location 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() { } 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 *mapSource) { if (m_mapSource == mapSource) return; if (m_mapSource) { // disconnect this object from current map source m_mapSource->disconnect(this); m_mapSource->m_map->disconnect(this); m_copyrightsHtml->clear(); m_copyrightsImage = QImage(); m_mapSource = Q_NULLPTR; } if (mapSource) { m_mapSource = mapSource; // First update the copyright. Only Image will do here, no need to store HTML right away. if (mapSource->m_copyrights && !mapSource->m_copyrights->m_copyrightsImage.isNull()) m_copyrightsImage = mapSource->m_copyrights->m_copyrightsImage; connect(m_mapSource, SIGNAL(copyrightsChanged(QImage)), this, SLOT(copyrightsChanged(QImage))); connect(m_mapSource, SIGNAL(copyrightsChanged(QString)), this, SLOT(copyrightsChanged(QString))); if (m_mapSource->m_map) connectMap(); else connect(m_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)), m_mapSource, SIGNAL(copyrightLinkActivated(QString))); onCopyrightsStyleSheetChanged(m_mapSource->m_map->copyrightsStyleSheet()); update(); emit mapSourceChanged(); } QDeclarativeGeoMap *QDeclarativeGeoMapCopyrightNotice::mapSource() { return m_mapSource; } 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); } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::setCopyrightsVisible(bool visible) { m_copyrightsVisible = visible; setVisible(!m_copyrightsImage.isNull() && visible); } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::setCopyrightsZ(int copyrightsZ) { setZ(copyrightsZ); update(); } /*! \internal */ void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QImage ©rightsImage) { delete m_copyrightsHtml; m_copyrightsHtml = 0; m_copyrightsImage = copyrightsImage; setImplicitSize(m_copyrightsImage.width(), m_copyrightsImage.height()); setKeepMouseGrab(false); setAcceptedMouseButtons(Qt::NoButton); setVisible(m_copyrightsVisible); update(); } void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QString ©rightsHtml) { if (copyrightsHtml.isEmpty()) { setVisible(false); return; } else if (!m_copyrightsVisible) { setVisible(false); } else { setVisible(true); } // 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