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