Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdeclarativegeomapcopyrightsnotice.cpp
Go to the documentation of this file.
1// Copyright (C) 2014 Aaron McCarthy <mccarthy.aaron@gmail.com>
2// Copyright (C) 2022 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
6
7#include <QtGui/QTextDocument>
8#include <QtGui/QAbstractTextDocumentLayout>
9#include <QtGui/QPainter>
10#include <QtGui/QImage>
11#include <QtQuick/private/qquickanchors_p.h>
12#include <QtLocation/private/qdeclarativegeomap_p.h>
13#include <QtQuick/private/qquickpainteditem_p.h>
14
16
18{
19 Q_DECLARE_PUBLIC(QDeclarativeGeoMapCopyrightNotice)
20public:
22};
23
24/*!
25 \qmltype MapCopyrightNotice
26 \nativetype QDeclarativeGeoMapCopyrightNotice
27 \inqmlmodule QtLocation
28 \ingroup qml-QtLocation5-maps
29 \since QtLocation 5.9
30
31 \brief The MapCopyrightNotice item displays the current valid
32 copyright notice for a Map element.
33
34 This object can be used to place an additional copyright notices
35 programmatically.
36
37 Note that declaring a MapCopyrightNotice inside a QtLocation::Map element
38 is not possible, like for any other QQuickItem.
39
40 The release of this API with Qt 5.9 is a Technology Preview.
41*/
42
43/*!
44 \qmlproperty Map QtLocation::MapCopyrightNotice::mapSource
45
46 This property holds the current map source providing the copyright data shown
47 in this notice.
48 In order to let the MapCopyrightNotice display a copyright, this property must
49 be set, as it is the only data source for this element.
50*/
51
52/*!
53 \qmlproperty string QtLocation::MapCopyrightNotice::styleSheet
54
55 This property holds the current css2.1 style sheet used to style the copyright notice, if in HTML form.
56
57 Example:
58 \code
59 MapCopyrightNotice {
60 mapSource: myMap
61 styleSheet: "body { color : green; font-family: \"Lucida\"; font-size: 8px} a{ font-size: 8px; color:#A62900}"
62 }
63 \endcode
64*/
65
66QDeclarativeGeoMapCopyrightNotice::QDeclarativeGeoMapCopyrightNotice(QQuickItem *parent)
67: QQuickPaintedItem(parent)
68{
69 // If this item is constructed inside the map, automatically anchor it where it always used to be.
70 if (qobject_cast<QDeclarativeGeoMap *>(parent))
71 anchorToBottomLeft();
72}
73
74QDeclarativeGeoMapCopyrightNotice::~QDeclarativeGeoMapCopyrightNotice()
75{
76 setMapSource(nullptr);
77}
78
79void QDeclarativeGeoMapCopyrightNotice::anchorToBottomLeft()
80{
81 if (!parent())
82 return;
83 QQuickAnchors *anchors = property("anchors").value<QQuickAnchors *>();
84 if (anchors) {
85 anchors->setLeft(QQuickAnchorLine(qobject_cast<QQuickItem *>(parent()), QQuickAnchors::LeftAnchor));
86 anchors->setBottom(QQuickAnchorLine(qobject_cast<QQuickItem *>(parent()), QQuickAnchors::BottomAnchor));
87 }
88}
89
90void QDeclarativeGeoMapCopyrightNotice::setMapSource(QDeclarativeGeoMap *map)
91{
92 if (m_mapSource == map)
93 return;
94
95 if (m_mapSource) {
96 // disconnect this object from current map source
97 m_mapSource->detachCopyrightNotice(copyrightsVisible());
98 m_mapSource->disconnect(this);
99 m_mapSource->m_map->disconnect(this);
100 if (m_copyrightsHtml)
101 m_copyrightsHtml->clear();
102 m_copyrightsImage = QImage();
103 m_mapSource = nullptr;
104 }
105
106 if (map) {
107 m_mapSource = map;
108 m_mapSource->attachCopyrightNotice(copyrightsVisible());
109 connect(this, &QDeclarativeGeoMapCopyrightNotice::copyrightsVisibleChanged,
110 mapSource(), &QDeclarativeGeoMap::onAttachedCopyrightNoticeVisibilityChanged);
111
112 // First update the copyright. Only Image will do here, no need to store HTML right away.
113 if (m_mapSource->m_copyrights && !m_mapSource->m_copyrights->m_copyrightsImage.isNull())
114 m_copyrightsImage = m_mapSource->m_copyrights->m_copyrightsImage;
115
116 connect(mapSource(), &QDeclarativeGeoMap::copyrightsImageChanged,
117 this, &QDeclarativeGeoMapCopyrightNotice::copyrightsImageChanged);
118 connect(mapSource(), &QDeclarativeGeoMap::copyrightsChanged,
119 this, &QDeclarativeGeoMapCopyrightNotice::copyrightsChanged);
120
121 if (m_mapSource->m_map)
122 connectMap();
123 else
124 connect(mapSource(), &QDeclarativeGeoMap::mapReadyChanged, this, &QDeclarativeGeoMapCopyrightNotice::connectMap);
125 }
126}
127
128void QDeclarativeGeoMapCopyrightNotice::connectMap()
129{
130 connect(m_mapSource->m_map.data(), &QGeoMap::copyrightsStyleSheetChanged,
131 this, &QDeclarativeGeoMapCopyrightNotice::onCopyrightsStyleSheetChanged);
132 connect(this, &QDeclarativeGeoMapCopyrightNotice::linkActivated,
133 mapSource(), &QDeclarativeGeoMap::copyrightLinkActivated);
134
135 onCopyrightsStyleSheetChanged(m_mapSource->m_map->copyrightsStyleSheet());
136
137 update();
138 emit mapSourceChanged();
139}
140
141QDeclarativeGeoMap *QDeclarativeGeoMapCopyrightNotice::mapSource()
142{
143 return m_mapSource.data();
144}
145
146QString QDeclarativeGeoMapCopyrightNotice::styleSheet() const
147{
148 return m_styleSheet;
149}
150
151void QDeclarativeGeoMapCopyrightNotice::setStyleSheet(const QString &styleSheet)
152{
153 m_userDefinedStyleSheet = true;
154
155 if (styleSheet == m_styleSheet)
156 return;
157
158 m_styleSheet = styleSheet;
159 if (!m_html.isEmpty() && m_copyrightsHtml) {
160 delete m_copyrightsHtml;
161 createCopyright();
162#if QT_CONFIG(texthtmlparser)
163 m_copyrightsHtml->setHtml(m_html);
164#else
165 m_copyrightsHtml->setPlainText(m_html);
166#endif
167 }
168 rasterizeHtmlAndUpdate();
169 emit styleSheetChanged(m_styleSheet);
170}
171
172/*!
173 \internal
174*/
175void QDeclarativeGeoMapCopyrightNotice::paint(QPainter *painter)
176{
177 painter->drawImage(0, 0, m_copyrightsImage);
178}
179
180void QDeclarativeGeoMapCopyrightNotice::mousePressEvent(QMouseEvent *event)
181{
182 if (m_copyrightsHtml) {
183 m_activeAnchor = m_copyrightsHtml->documentLayout()->anchorAt(event->pos());
184 if (!m_activeAnchor.isEmpty())
185 return;
186 }
187
188 QQuickPaintedItem::mousePressEvent(event);
189}
190
191void QDeclarativeGeoMapCopyrightNotice::mouseReleaseEvent(QMouseEvent *event)
192{
193 if (m_copyrightsHtml) {
194 QString anchor = m_copyrightsHtml->documentLayout()->anchorAt(event->pos());
195 if (anchor == m_activeAnchor && !anchor.isEmpty()) {
196 emit linkActivated(anchor);
197 m_activeAnchor.clear();
198 }
199 }
200}
201
202void QDeclarativeGeoMapCopyrightNotice::rasterizeHtmlAndUpdate()
203{
204 if (!m_copyrightsHtml || m_copyrightsHtml->isEmpty())
205 return;
206
207 m_copyrightsImage = QImage(m_copyrightsHtml->size().toSize(),
208 QImage::Format_ARGB32_Premultiplied);
209
210 m_copyrightsImage.fill(qPremultiply(QColor(Qt::transparent).rgba()));
211 QPainter painter(&m_copyrightsImage);
212 QAbstractTextDocumentLayout::PaintContext ctx;
213 ctx.palette.setColor(QPalette::Text, QColor::fromString("black"));
214 m_copyrightsHtml->documentLayout()->draw(&painter, ctx);
215
216 setImplicitSize(m_copyrightsImage.width(), m_copyrightsImage.height());
217 setContentsSize(m_copyrightsImage.size());
218
219 setKeepMouseGrab(true);
220 setAcceptedMouseButtons(Qt::LeftButton);
221
222 update();
223}
224
225void QDeclarativeGeoMapCopyrightNotice::createCopyright()
226{
227 m_copyrightsHtml = new QTextDocument(this);
228#if QT_CONFIG(cssparser)
229 if (!m_styleSheet.isEmpty())
230 m_copyrightsHtml->setDefaultStyleSheet(m_styleSheet);
231#endif
232
233 // The default 4 makes the copyright too wide and tall.
234 m_copyrightsHtml->setDocumentMargin(0);
235}
236
237void QDeclarativeGeoMapCopyrightNoticePrivate::setVisible(bool visible)
238{
239 Q_Q(QDeclarativeGeoMapCopyrightNotice);
240 q->m_copyrightsVisible = visible;
241 QQuickItemPrivate::setVisible(visible);
242}
243
244/*!
245 \internal
246*/
247void QDeclarativeGeoMapCopyrightNotice::setCopyrightsVisible(bool visible)
248{
249 Q_D(QDeclarativeGeoMapCopyrightNotice);
250 if (visible == m_copyrightsVisible)
251 return;
252
253 m_copyrightsVisible = visible;
254 d->QQuickItemPrivate::setVisible(!m_copyrightsImage.isNull() && visible);
255 emit copyrightsVisibleChanged();
256}
257
258bool QDeclarativeGeoMapCopyrightNotice::copyrightsVisible() const
259{
260 return m_copyrightsVisible;
261}
262
263/*!
264 \internal
265*/
266void QDeclarativeGeoMapCopyrightNotice::setCopyrightsZ(qreal copyrightsZ)
267{
268 setZ(copyrightsZ);
269 update();
270}
271
272/*!
273 \internal
274*/
275void QDeclarativeGeoMapCopyrightNotice::copyrightsImageChanged(const QImage &copyrightsImage)
276{
277 Q_D(QDeclarativeGeoMapCopyrightNotice);
278 delete m_copyrightsHtml;
279 m_copyrightsHtml = nullptr;
280
281 m_copyrightsImage = copyrightsImage;
282
283 setImplicitSize(m_copyrightsImage.width(), m_copyrightsImage.height());
284
285 setKeepMouseGrab(false);
286 setAcceptedMouseButtons(Qt::NoButton);
287 d->QQuickItemPrivate::setVisible(m_copyrightsVisible && !m_copyrightsImage.isNull());
288
289 update();
290}
291
292void QDeclarativeGeoMapCopyrightNotice::copyrightsChanged(const QString &copyrightsHtml)
293{
294 Q_D(QDeclarativeGeoMapCopyrightNotice);
295 if (copyrightsHtml.isEmpty()) {
296 d->QQuickItemPrivate::setVisible(false);
297 return;
298 } else {
299 d->QQuickItemPrivate::setVisible(m_copyrightsVisible);
300 }
301
302 // Divfy, so we can style the background. The extra <span> is a
303 // workaround to QTBUG-58838 and should be removed when it gets fixed.
304#if QT_CONFIG(texthtmlparser)
305 m_html = QStringLiteral("<div id='copyright-root'><span>") + copyrightsHtml + QStringLiteral("</span></div>");
306#else
307 m_html = copyrightsHtml;
308#endif
309
310 if (!m_copyrightsHtml)
311 createCopyright();
312
313#if QT_CONFIG(texthtmlparser)
314 m_copyrightsHtml->setHtml(m_html);
315#else
316 m_copyrightsHtml->setPlainText(m_html);
317#endif
318 rasterizeHtmlAndUpdate();
319}
320
321void QDeclarativeGeoMapCopyrightNotice::onCopyrightsStyleSheetChanged(const QString &styleSheet)
322{
323 if (m_userDefinedStyleSheet || styleSheet == m_styleSheet)
324 return;
325
326 m_styleSheet = styleSheet;
327 if (!m_html.isEmpty() && m_copyrightsHtml) {
328 delete m_copyrightsHtml;
329 createCopyright();
330#if QT_CONFIG(texthtmlparser)
331 m_copyrightsHtml->setHtml(m_html);
332#else
333 m_copyrightsHtml->setPlainText(m_html);
334#endif
335 }
336 rasterizeHtmlAndUpdate();
337 emit styleSheetChanged(m_styleSheet);
338}
339
340QT_END_NAMESPACE