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 "qmapcircleobject_p.h"
38 #include "qmapcircleobject_p_p.h"
39 #include <QExplicitlySharedDataPointer>
40 #include <QtPositioning/qgeocircle.h>
41 
42 QT_BEGIN_NAMESPACE
43 
44 /*!
45     \qmltype MapCircleObject
46     \instantiates QMapCircleObject
47     \inqmlmodule Qt.labs.location
48     \ingroup qml-QtLocation5-maps
49     \inherits QGeoMapObject
50 
51     \brief The MapCircleObject displays a circle on a Map.
52 
53     The MapCircleObject displays a circle on a Map.
54     The MapIconObject type only makes sense when contained in a Map or in a \l MapObjectView.
55 */
56 
QMapCircleObjectPrivate(QGeoMapObject * q)57 QMapCircleObjectPrivate::QMapCircleObjectPrivate(QGeoMapObject *q) : QGeoMapObjectPrivate(q)
58 {
59 
60 }
61 
~QMapCircleObjectPrivate()62 QMapCircleObjectPrivate::~QMapCircleObjectPrivate()
63 {
64 
65 }
66 
type() const67 QGeoMapObject::Type QMapCircleObjectPrivate::type() const
68 {
69     return QGeoMapObject::CircleType;
70 }
71 
geoShape() const72 QGeoShape QMapCircleObjectPrivate::geoShape() const
73 {
74     return QGeoCircle(center(), radius());
75 }
76 
setGeoShape(const QGeoShape & shape)77 void QMapCircleObjectPrivate::setGeoShape(const QGeoShape &shape)
78 {
79     if (shape == geoShape())
80         return;
81 
82     const QGeoCircle circle(shape); // if shape isn't a circle, circle will be created as a default-constructed circle
83     const bool centerHasChanged = circle.center() != center();
84     const bool radiusHasChanged = circle.radius() != radius();
85 
86     if (centerHasChanged)
87         setCenter(circle.center()); // to handle overrides
88     if (radiusHasChanged)
89         setRadius(circle.radius()); // to handle overrides
90 
91     if (centerHasChanged)
92         emit static_cast<QMapCircleObject *>(q)->centerChanged();
93     if (radiusHasChanged)
94         emit static_cast<QMapCircleObject *>(q)->radiusChanged();
95 }
96 
97 //
98 // QMapCircleObjectPrivate default implementation
99 //
100 
QMapCircleObjectPrivateDefault(QGeoMapObject * q)101 QMapCircleObjectPrivateDefault::QMapCircleObjectPrivateDefault(QGeoMapObject *q) : QMapCircleObjectPrivate(q)
102 {
103 
104 }
105 
QMapCircleObjectPrivateDefault(const QMapCircleObjectPrivate & other)106 QMapCircleObjectPrivateDefault::QMapCircleObjectPrivateDefault(const QMapCircleObjectPrivate &other) : QMapCircleObjectPrivate(other.q)
107 {
108     m_center = other.center();
109     m_radius = other.radius();
110     m_fillColor = other.color();
111     m_borderColor = other.borderColor();
112     m_borderWidth = other.borderWidth();
113 }
114 
~QMapCircleObjectPrivateDefault()115 QMapCircleObjectPrivateDefault::~QMapCircleObjectPrivateDefault()
116 {
117 
118 }
119 
center() const120 QGeoCoordinate QMapCircleObjectPrivateDefault::center() const
121 {
122     return m_center;
123 }
124 
setCenter(const QGeoCoordinate & center)125 void QMapCircleObjectPrivateDefault::setCenter(const QGeoCoordinate &center)
126 {
127     m_center = center;
128 }
129 
radius() const130 qreal QMapCircleObjectPrivateDefault::radius() const
131 {
132     return m_radius;
133 }
134 
setRadius(qreal radius)135 void QMapCircleObjectPrivateDefault::setRadius(qreal radius)
136 {
137     m_radius = radius;
138 }
139 
color() const140 QColor QMapCircleObjectPrivateDefault::color() const
141 {
142     return m_fillColor;
143 }
144 
setColor(const QColor & color)145 void QMapCircleObjectPrivateDefault::setColor(const QColor &color)
146 {
147     m_fillColor = color;
148 }
149 
borderColor() const150 QColor QMapCircleObjectPrivateDefault::borderColor() const
151 {
152     return m_borderColor;
153 }
154 
setBorderColor(const QColor & color)155 void QMapCircleObjectPrivateDefault::setBorderColor(const QColor &color)
156 {
157     m_borderColor = color;
158 }
159 
borderWidth() const160 qreal QMapCircleObjectPrivateDefault::borderWidth() const
161 {
162     return m_borderWidth;
163 }
164 
setBorderWidth(qreal width)165 void QMapCircleObjectPrivateDefault::setBorderWidth(qreal width)
166 {
167     m_borderWidth = width;
168 }
169 
equals(const QGeoMapObjectPrivate & other) const170 bool QMapCircleObjectPrivate::equals(const QGeoMapObjectPrivate &other) const
171 {
172     if (other.type() != type()) // This check might be unnecessary, depending on how equals gets used
173         return false;
174 
175     const QMapCircleObjectPrivate &o = static_cast<const QMapCircleObjectPrivate &>(other);
176     return (QGeoMapObjectPrivate::equals(o)
177             && center() == o.center()
178             && radius() == o.radius()
179             && color() == o.color()
180             && borderColor() == o.borderColor()
181             && borderWidth() == o.borderWidth());
182 }
183 
clone()184 QGeoMapObjectPrivate *QMapCircleObjectPrivateDefault::clone()
185 {
186     return new QMapCircleObjectPrivateDefault(static_cast<QMapCircleObjectPrivate &>(*this));
187 }
188 
QMapCircleObject(QObject * parent)189 QMapCircleObject::QMapCircleObject(QObject *parent)
190     : QGeoMapObject(QExplicitlySharedDataPointer<QGeoMapObjectPrivate>(new QMapCircleObjectPrivateDefault(this)), parent)
191 
192 {
193     QMapCircleObjectPrivate *d = static_cast<QMapCircleObjectPrivate*>(d_ptr.data());
194     d->setBorderColor(QColor(Qt::black)); // These are QDeclarativeMapLineProperties defaults
195     d->setBorderWidth(1.0);
196 }
197 
~QMapCircleObject()198 QMapCircleObject::~QMapCircleObject()
199 {
200 
201 }
202 
203 /*!
204     \qmlproperty coordinate Qt.labs.location::MapCircleObject::center
205 
206     This property holds the central point about which the circle is defined.
207 
208     \sa radius
209 */
center() const210 QGeoCoordinate QMapCircleObject::center() const
211 {
212     return static_cast<const QMapCircleObjectPrivate*>(d_ptr.data())->center();
213 }
214 
215 /*!
216     \qmlproperty real Qt.labs.location::MapCircleObject::radius
217 
218     This property holds the radius of the circle, in meters on the ground.
219 
220     \sa center
221 */
radius() const222 qreal QMapCircleObject::radius() const
223 {
224     return static_cast<const QMapCircleObjectPrivate*>(d_ptr.data())->radius();
225 }
226 
227 /*!
228     \qmlproperty color Qt.labs.location::MapCircleObject::color
229 
230     This property holds the fill color of the circle when drawn. For no fill,
231     use a transparent color.
232 */
color() const233 QColor QMapCircleObject::color() const
234 {
235     return static_cast<const QMapCircleObjectPrivate*>(d_ptr.data())->color();
236 }
237 
238 /*!
239     \qmlpropertygroup Qt.labs.location::MapCircleObject::border
240     \qmlproperty int MapCircleObject::border.width
241     \qmlproperty color MapCircleObject::border.color
242 
243     This property is part of the border group property.
244     The border property holds the width and color used to draw the border of the circle.
245     The width is in pixels and is independent of the zoom level of the map.
246 
247     The default values correspond to a black border with a width of 1 pixel.
248     For no line, use a width of 0 or a transparent color.
249 */
border()250 QDeclarativeMapLineProperties *QMapCircleObject::border()
251 {
252     if (!m_border) {
253         m_border = new QDeclarativeMapLineProperties(this);
254         connect(m_border, &QDeclarativeMapLineProperties::colorChanged, this, [this](const QColor &color){
255             static_cast<QMapCircleObjectPrivate*>(d_ptr.data())->setBorderColor(color);
256         });
257         connect(m_border, &QDeclarativeMapLineProperties::widthChanged, this, [this](qreal width){
258             static_cast<QMapCircleObjectPrivate*>(d_ptr.data())->setBorderWidth(width);
259         });
260     }
261     return m_border;
262 }
263 
setCenter(const QGeoCoordinate & center)264 void QMapCircleObject::setCenter(const QGeoCoordinate &center)
265 {
266     auto ptr = static_cast<QMapCircleObjectPrivate*>(d_ptr.data());
267     if (ptr->center() == center)
268         return;
269 
270     ptr->setCenter(center);
271     emit centerChanged();
272 }
273 
setRadius(qreal radius)274 void QMapCircleObject::setRadius(qreal radius)
275 {
276     auto d = static_cast<QMapCircleObjectPrivate*>(d_ptr.data());
277     if (d->radius() == radius)
278         return;
279 
280     d->setRadius(radius);
281     emit radiusChanged();
282 }
283 
setColor(const QColor & color)284 void QMapCircleObject::setColor(const QColor &color)
285 {
286     auto d = static_cast<QMapCircleObjectPrivate*>(d_ptr.data());
287     if (d->color() == color)
288         return;
289 
290     d->setColor(color);
291     emit colorChanged();
292 }
293 
setMap(QGeoMap * map)294 void QMapCircleObject::setMap(QGeoMap *map)
295 {
296     QMapCircleObjectPrivate *d = static_cast<QMapCircleObjectPrivate *>(d_ptr.data());
297     if (d->m_map == map)
298         return;
299 
300     QGeoMapObject::setMap(map); // This is where the specialized pimpl gets created and injected
301 
302     if (!map) {
303         // Map was set, now it has ben re-set to NULL, but not inside d_ptr.
304         // so m_map inside d_ptr can still be used to remove itself, inside the destructor.
305         d_ptr = new QMapCircleObjectPrivateDefault(*d);
306         // Old pimpl deleted implicitly by QExplicitlySharedDataPointer
307     }
308 }
309 
310 QT_END_NAMESPACE
311