1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 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 "qdeclarativegeomapitemgroup_p.h"
38 #include "qdeclarativegeomapitembase_p.h"
39 #include "qdeclarativegeomap_p.h"
40 
41 QT_BEGIN_NAMESPACE
42 
43 /*!
44     \qmltype MapItemGroup
45     \instantiates QDeclarativeGeoMapItemGroup
46     \inqmlmodule QtLocation
47     \ingroup qml-QtLocation5-maps
48     \since QtLocation 5.9
49 
50     \brief The MapItemGroup type is a container for map items.
51 
52     Its purpose is to enable code modularization by allowing the usage
53     of qml files containing map elements related to each other, and
54     the associated bindings.
55 
56     \note The release of this API with Qt 5.9 is a Technology Preview.
57 
58     \section2 Example Usage
59 
60     The following snippet shows how to use a MapItemGroup to create a MapCircle, centered at
61     the coordinate (63, -18) with a radius of 100km, filled in red, surrounded by an ondulated green border,
62     both contained in a semitransparent blue circle with a MouseArea that moves the whole group.
63     This group is defined in a separate file named PolygonGroup.qml:
64 
65     \code
66     import QtQuick 2.4
67     import QtPositioning 5.6
68     import QtLocation 5.9
69 
70     MapItemGroup {
71         id: itemGroup
72         property alias position: mainCircle.center
73         property var radius: 100 * 1000
74         property var borderHeightPct : 0.3
75 
76         MapCircle {
77             id: mainCircle
78             center : QtPositioning.coordinate(40, 0)
79             radius: itemGroup.radius * (1.0 + borderHeightPct)
80             opacity: 0.05
81             visible: true
82             color: 'blue'
83 
84             MouseArea{
85                 anchors.fill: parent
86                 drag.target: parent
87                 id: maItemGroup
88             }
89         }
90 
91         MapCircle {
92             id: groupCircle
93             center: itemGroup.position
94             radius: itemGroup.radius
95             color: 'crimson'
96 
97             onCenterChanged: {
98                 groupPolyline.populateBorder();
99             }
100         }
101 
102         MapPolyline {
103             id: groupPolyline
104             line.color: 'green'
105             line.width: 3
106 
107             function populateBorder() {
108                 groupPolyline.path = [] // clearing the path
109                 var waveLength = 8.0;
110                 var waveAmplitude = groupCircle.radius * borderHeightPct;
111                 for (var i=0; i <= 360; i++) {
112                     var wavePhase = (i/360.0 * 2.0 * Math.PI )* waveLength
113                     var waveHeight = (Math.cos(wavePhase) + 1.0) / 2.0
114                     groupPolyline.addCoordinate(groupCircle.center.atDistanceAndAzimuth(groupCircle.radius + waveAmplitude * waveHeight , i))
115                 }
116             }
117 
118             Component.onCompleted: {
119                 populateBorder()
120             }
121         }
122     }
123     \endcode
124 
125     PolygonGroup.qml is now a reusable component that can then be used in a Map as:
126 
127     \code
128     Map {
129         id: map
130         PolygonGroup {
131             id: polygonGroup
132             position: QtPositioning.coordinate(63,-18)
133         }
134     }
135     \endcode
136 
137     \image api-mapitemgroup.png
138 */
139 
QDeclarativeGeoMapItemGroup(QQuickItem * parent)140 QDeclarativeGeoMapItemGroup::QDeclarativeGeoMapItemGroup(QQuickItem *parent)
141 :   QQuickItem(parent), m_quickMap(nullptr)
142 {
143     connect(this, &QQuickItem::opacityChanged,
144             this, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged);
145 }
146 
~QDeclarativeGeoMapItemGroup()147 QDeclarativeGeoMapItemGroup::~QDeclarativeGeoMapItemGroup()
148 {
149 
150 }
151 
setParentGroup(QDeclarativeGeoMapItemGroup & parentGroup)152 void QDeclarativeGeoMapItemGroup::setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup)
153 {
154     m_parentGroup = &parentGroup;
155     connect(m_parentGroup, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged,
156             this, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged);
157 }
158 
setQuickMap(QDeclarativeGeoMap * quickMap)159 void QDeclarativeGeoMapItemGroup::setQuickMap(QDeclarativeGeoMap *quickMap)
160 {
161     if (!quickMap && m_quickMap)
162         m_quickMap->disconnect(this);
163     m_quickMap = quickMap;
164     if (m_quickMap) {
165         onMapSizeChanged();
166         connect(m_quickMap, &QQuickItem::widthChanged, this, &QDeclarativeGeoMapItemGroup::onMapSizeChanged);
167         connect(m_quickMap, &QQuickItem::heightChanged, this, &QDeclarativeGeoMapItemGroup::onMapSizeChanged);
168     }
169 }
170 
quickMap() const171 QDeclarativeGeoMap *QDeclarativeGeoMapItemGroup::quickMap() const
172 {
173     return m_quickMap;
174 }
175 
mapItemOpacity() const176 qreal QDeclarativeGeoMapItemGroup::mapItemOpacity() const
177 {
178     return ((m_parentGroup) ? m_parentGroup->mapItemOpacity() : 1.0) * opacity();
179 }
180 
classBegin()181 void QDeclarativeGeoMapItemGroup::classBegin()
182 {
183     QQuickItem::classBegin();
184 }
185 
componentComplete()186 void QDeclarativeGeoMapItemGroup::componentComplete()
187 {
188     QQuickItem::componentComplete();
189 
190     // In certain cases the parent won't be set via the constructor, but rather later on
191     // during the instantiation/incubation process.
192     // Therefore calling setParentGroup here, when the parent is known.
193     // The childrenChanged use case to handle dynamically-added items is currently unsupported.
194     const QList<QQuickItem *> &quickKids = childItems();
195     for (QQuickItem *k : quickKids) {
196         QDeclarativeGeoMapItemGroup *childGroup
197                 = qobject_cast<QDeclarativeGeoMapItemGroup *>(k);
198         if (childGroup) {
199             childGroup->setParentGroup(*this);
200             continue;
201         }
202         QDeclarativeGeoMapItemBase *childItem
203                 = qobject_cast<QDeclarativeGeoMapItemBase *>(k);
204         if (childItem) {
205             childItem->setParentGroup(*this);
206             continue;
207         }
208     }
209 }
210 
onMapSizeChanged()211 void QDeclarativeGeoMapItemGroup::onMapSizeChanged()
212 {
213     setWidth(m_quickMap->width());
214     setHeight(m_quickMap->height());
215 }
216 
217 QT_END_NAMESPACE
218