1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtLocation module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36
37 #include "qmappolygonobject_p.h"
38 #include "qmappolygonobject_p_p.h"
39 #include <QtLocation/private/locationvaluetypehelper_p.h>
40
41 QT_BEGIN_NAMESPACE
42
43 /*!
44 \qmltype MapPolygonObject
45 \instantiates QMapPolygonObject
46 \inqmlmodule Qt.labs.location
47 \ingroup qml-QtLocation5-maps
48 \inherits QGeoMapObject
49
50 \brief The MapPolygonObject displays a polygon on a Map.
51
52 The MapPolygonObject displays a polygon on a Map.
53 The MapPolygonObject type only makes sense when contained in a Map or in a \l MapObjectView.
54 */
55
QMapPolygonObjectPrivate(QGeoMapObject * q)56 QMapPolygonObjectPrivate::QMapPolygonObjectPrivate(QGeoMapObject *q) : QGeoMapObjectPrivate(q)
57 {
58
59 }
60
~QMapPolygonObjectPrivate()61 QMapPolygonObjectPrivate::~QMapPolygonObjectPrivate()
62 {
63
64 }
65
QMapPolygonObjectPrivateDefault(QGeoMapObject * q)66 QMapPolygonObjectPrivateDefault::QMapPolygonObjectPrivateDefault(QGeoMapObject *q) : QMapPolygonObjectPrivate(q)
67 {
68
69 }
70
QMapPolygonObjectPrivateDefault(const QMapPolygonObjectPrivate & other)71 QMapPolygonObjectPrivateDefault::QMapPolygonObjectPrivateDefault(const QMapPolygonObjectPrivate &other) : QMapPolygonObjectPrivate(other.q)
72 {
73 m_path.setPath(other.path()); // to stay on the safe side
74 QGeoPolygon poly(other.geoShape()); // to handle holes
75 for (int i = 0; i < poly.holesCount(); i++)
76 m_path.addHole(poly.holePath(i));
77 m_borderColor = other.borderColor();
78 m_fillColor = other.fillColor();
79 m_borderWidth = other.borderWidth();
80 }
81
~QMapPolygonObjectPrivateDefault()82 QMapPolygonObjectPrivateDefault::~QMapPolygonObjectPrivateDefault()
83 {
84
85 }
86
type() const87 QGeoMapObject::Type QMapPolygonObjectPrivate::type() const
88 {
89 return QGeoMapObject::PolygonType;
90 }
91
path() const92 QList<QGeoCoordinate> QMapPolygonObjectPrivateDefault::path() const
93 {
94 return m_path.path();
95 }
96
setPath(const QList<QGeoCoordinate> & path)97 void QMapPolygonObjectPrivateDefault::setPath(const QList<QGeoCoordinate> &path)
98 {
99 m_path.setPath(path);
100 }
101
fillColor() const102 QColor QMapPolygonObjectPrivateDefault::fillColor() const
103 {
104 return m_fillColor;
105 }
106
setFillColor(const QColor & color)107 void QMapPolygonObjectPrivateDefault::setFillColor(const QColor &color)
108 {
109 m_fillColor = color;
110 }
111
borderColor() const112 QColor QMapPolygonObjectPrivateDefault::borderColor() const
113 {
114 return m_borderColor;
115 }
116
setBorderColor(const QColor & color)117 void QMapPolygonObjectPrivateDefault::setBorderColor(const QColor &color)
118 {
119 m_borderColor = color;
120 }
121
borderWidth() const122 qreal QMapPolygonObjectPrivateDefault::borderWidth() const
123 {
124 return m_borderWidth;
125 }
126
setBorderWidth(qreal width)127 void QMapPolygonObjectPrivateDefault::setBorderWidth(qreal width)
128 {
129 m_borderWidth = width;
130 }
131
clone()132 QGeoMapObjectPrivate *QMapPolygonObjectPrivateDefault::clone()
133 {
134 return new QMapPolygonObjectPrivateDefault(static_cast<QMapPolygonObjectPrivate &>(*this));
135 }
136
geoShape() const137 QGeoShape QMapPolygonObjectPrivateDefault::geoShape() const
138 {
139 return m_path;
140 }
141
setGeoShape(const QGeoShape & shape)142 void QMapPolygonObjectPrivateDefault::setGeoShape(const QGeoShape &shape)
143 {
144 if (shape == m_path)
145 return;
146
147 const QGeoPolygon poly(shape);
148 for (int i = 0; i < poly.holesCount(); i++)
149 m_path.addHole(poly.holePath(i));
150 setPath(poly.path()); // to handle overrides. Last as it normally emits static_cast<QMapPolygonObject *>(q)->pathChanged();
151 }
152
equals(const QGeoMapObjectPrivate & other) const153 bool QMapPolygonObjectPrivate::equals(const QGeoMapObjectPrivate &other) const
154 {
155 if (other.type() != type()) // This check might be unnecessary, depending on how equals gets used
156 return false;
157
158 const QMapPolygonObjectPrivate &o = static_cast<const QMapPolygonObjectPrivate &>(other);
159 return (QGeoMapObjectPrivate::equals(o)
160 && geoShape() == o.geoShape()
161 && borderColor() == o.borderColor()
162 && fillColor() == o.fillColor()
163 && borderWidth() == o.borderWidth());
164 }
165
geoShape() const166 QGeoShape QMapPolygonObjectPrivate::geoShape() const
167 {
168 return QGeoPolygon(path());
169 }
170
setGeoShape(const QGeoShape & shape)171 void QMapPolygonObjectPrivate::setGeoShape(const QGeoShape &shape)
172 {
173 if (shape == geoShape())
174 return;
175
176 const QGeoPolygon poly(shape);
177 setPath(poly.path()); // to handle overrides
178 emit static_cast<QMapPolygonObject *>(q)->pathChanged();
179 }
180
181
182
183
QMapPolygonObject(QObject * parent)184 QMapPolygonObject::QMapPolygonObject(QObject *parent)
185 : QGeoMapObject(QExplicitlySharedDataPointer<QGeoMapObjectPrivate>(new QMapPolygonObjectPrivateDefault(this)), parent)
186 {
187 QMapPolygonObjectPrivate *d = static_cast<QMapPolygonObjectPrivate*>(d_ptr.data());
188 d->setBorderColor(QColor(Qt::black)); // These are QDeclarativeMapLineProperties defaults
189 d->setBorderWidth(1.0);
190 }
191
~QMapPolygonObject()192 QMapPolygonObject::~QMapPolygonObject()
193 {}
194
195 /*!
196 \qmlproperty VariantList Qt.labs.location::MapPolygonObject::path
197
198 This property holds the ordered list of coordinates which
199 define the polygon border.
200 */
path() const201 QVariantList QMapPolygonObject::path() const
202 {
203 QVariantList p;
204 for (const QGeoCoordinate &c: static_cast<const QMapPolygonObjectPrivate *>(d_ptr.data())->path())
205 p << QVariant::fromValue(c);
206 return p;
207 }
208
setPath(const QVariantList & path)209 void QMapPolygonObject::setPath(const QVariantList &path)
210 {
211 QList<QGeoCoordinate> p;
212 bool ok = false;
213 for (const auto &c: path) {
214 const QGeoCoordinate coord = parseCoordinate(c, &ok);
215 if (ok)
216 p << coord;
217 }
218 auto pimpl = static_cast<QMapPolygonObjectPrivate *>(d_ptr.data());
219 if (p != pimpl->path()) {
220 pimpl->setPath(p);
221 emit pathChanged();
222 }
223 }
224
225 /*!
226 \qmlproperty color Qt.labs.location::MapPolygonObject::color
227
228 This property holds the fill color of the polygon when drawn. For no fill,
229 use a transparent color.
230 */
color() const231 QColor QMapPolygonObject::color() const
232 {
233 return static_cast<const QMapPolygonObjectPrivate*>(d_ptr.data())->fillColor();
234 }
235
236 /*!
237 \qmlpropertygroup Qt.labs.location::MapPolygonObject::border
238 \qmlproperty int MapPolygonObject::border.width
239 \qmlproperty color MapPolygonObject::border.color
240
241 This property is part of the border property group. The border
242 property group holds the width and color used to draw the border.
243
244 The width is in pixels and is independent of the zoom level of the map.
245 The default values correspond to a black border with a width of 1 pixel.
246
247 For no border, use a width of 0 or a transparent color.
248 */
border()249 QDeclarativeMapLineProperties *QMapPolygonObject::border()
250 {
251 if (!m_border) {
252 m_border = new QDeclarativeMapLineProperties(this);
253 connect(m_border, &QDeclarativeMapLineProperties::colorChanged, this, [this](const QColor &color){
254 static_cast<QMapPolygonObjectPrivate*>(d_ptr.data())->setBorderColor(color);
255 });
256 connect(m_border, &QDeclarativeMapLineProperties::widthChanged, this, [this](qreal width){
257 static_cast<QMapPolygonObjectPrivate*>(d_ptr.data())->setBorderWidth(width);
258 });
259 }
260 return m_border;
261 }
262
setColor(const QColor & fillColor)263 void QMapPolygonObject::setColor(const QColor &fillColor)
264 {
265 auto ptr = static_cast<QMapPolygonObjectPrivate*>(d_ptr.data());
266
267 if (ptr->fillColor() == fillColor)
268 return;
269
270 ptr->setFillColor(fillColor);
271 emit colorChanged();
272 }
273
setMap(QGeoMap * map)274 void QMapPolygonObject::setMap(QGeoMap *map)
275 {
276 QMapPolygonObjectPrivate *d = static_cast<QMapPolygonObjectPrivate *>(d_ptr.data());
277 if (d->m_map == map)
278 return;
279
280 QGeoMapObject::setMap(map); // This is where the specialized pimpl gets created and injected
281
282 if (!map) {
283 // Map was set, now it has ben re-set to NULL, but not inside d_ptr.
284 // so m_map inside d_ptr can still be used to remove itself, inside the destructor.
285 d_ptr = new QMapPolygonObjectPrivateDefault(*d);
286 // Old pimpl deleted implicitly by QExplicitlySharedDataPointer
287 }
288 }
289
290 QT_END_NAMESPACE
291