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