summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2018-05-07 16:46:12 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2018-07-27 08:18:38 +0000
commitfd6c6e9654a14788fc4eb7384c9dfa5de1f5ffde (patch)
treed15088fbdac71e31fc5ef8aa445df39b6fb4070d
parent6815fd10c51c72ea91bdbc18acddaee2302871f8 (diff)
downloadqtlocation-fd6c6e9654a14788fc4eb7384c9dfa5de1f5ffde.tar.gz
Enable nested MapItemViews
This change allows MapItemView to use a MapItem, MapItemGroup or MapItemView as delegate. To achieve this, MapItemView base class also changes from QObject to MapItemGroup, effectively making MapItemView a MapItemGroup. Note, though, that MapItemGroup API in Map should be avoided, when dealing with a MapItemView, and only MapItemView-specific API should be used. Tests and example coming after [ChangeLog][QtLocation] Enabled nesting of MapItemView. This required a behavioral change, as MapItemView is now a MapItemGroup, not anymore a plain QObject. Due to a bug, MapItemView was previously not a Qt Quick Item, making it possible to create it as a child of any QObject. This has now been fixed, so if you happen to have a MapItemView in your scene which is not a child of a Qt Quick Item, you will get an error message. Task-number: QTBUG-62683 Task-number: QTBUG-62397 Change-Id: Id97e480429e7f952a541fe88df5c01317afeac18 Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r--src/location/declarativemaps/declarativemaps.pri109
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap.cpp293
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap_p.h10
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase.cpp90
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase_p.h37
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp63
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h23
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp81
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h120
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview.cpp226
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview_p.h29
-rw-r--r--tests/auto/declarative_ui/tst_map_itemview.qml12
12 files changed, 768 insertions, 325 deletions
diff --git a/src/location/declarativemaps/declarativemaps.pri b/src/location/declarativemaps/declarativemaps.pri
index 3cd7a529..28001f99 100644
--- a/src/location/declarativemaps/declarativemaps.pri
+++ b/src/location/declarativemaps/declarativemaps.pri
@@ -3,61 +3,64 @@ QT += quick-private network positioning-private qml-private core-private gui-pri
INCLUDEPATH += declarativemaps
PRIVATE_HEADERS += \
- declarativemaps/error_messages_p.h \
- declarativemaps/qdeclarativegeomapitemview_p.h \
- declarativemaps/qdeclarativegeoserviceprovider_p.h \
- declarativemaps/qdeclarativegeocodemodel_p.h \
- declarativemaps/qdeclarativegeoroutemodel_p.h \
- declarativemaps/qdeclarativegeoroute_p.h \
- declarativemaps/qdeclarativegeoroutesegment_p.h \
- declarativemaps/qdeclarativegeomaneuver_p.h \
- declarativemaps/qdeclarativegeomap_p.h \
- declarativemaps/qdeclarativegeomaptype_p.h \
- declarativemaps/qdeclarativegeomapitembase_p.h \
- declarativemaps/qdeclarativegeomapquickitem_p.h \
- declarativemaps/qdeclarativecirclemapitem_p.h \
- declarativemaps/qdeclarativerectanglemapitem_p.h \
- declarativemaps/qdeclarativepolygonmapitem_p.h \
- declarativemaps/qdeclarativepolylinemapitem_p.h \
- declarativemaps/qdeclarativeroutemapitem_p.h \
- declarativemaps/qdeclarativegeomapparameter_p.h \
- declarativemaps/qgeomapitemgeometry_p.h \
- declarativemaps/qdeclarativegeomapcopyrightsnotice_p.h \
- declarativemaps/locationvaluetypehelper_p.h \
- declarativemaps/qquickgeomapgesturearea_p.h \
- declarativemaps/qdeclarativegeomapitemgroup_p.h \
- declarativemaps/qparameterizableobject_p.h \
- declarativemaps/qgeomapobject_p.h \
- declarativemaps/qgeomapobject_p_p.h \
- ../imports/positioning/qquickgeocoordinateanimation_p.h
+ declarativemaps/error_messages_p.h \
+ declarativemaps/locationvaluetypehelper_p.h \
+ declarativemaps/mapitemviewdelegateincubator_p.h \
+ declarativemaps/qdeclarativecirclemapitem_p.h \
+ declarativemaps/qdeclarativegeocodemodel_p.h \
+ declarativemaps/qdeclarativegeomaneuver_p.h \
+ declarativemaps/qdeclarativegeomapcopyrightsnotice_p.h \
+ declarativemaps/qdeclarativegeomapitembase_p.h \
+ declarativemaps/qdeclarativegeomapitemgroup_p.h \
+ declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h \
+ declarativemaps/qdeclarativegeomapitemview_p.h \
+ declarativemaps/qdeclarativegeomapparameter_p.h \
+ declarativemaps/qdeclarativegeomap_p.h \
+ declarativemaps/qdeclarativegeomapquickitem_p.h \
+ declarativemaps/qdeclarativegeomaptype_p.h \
+ declarativemaps/qdeclarativegeoroutemodel_p.h \
+ declarativemaps/qdeclarativegeoroute_p.h \
+ declarativemaps/qdeclarativegeoroutesegment_p.h \
+ declarativemaps/qdeclarativegeoserviceprovider_p.h \
+ declarativemaps/qdeclarativepolygonmapitem_p.h \
+ declarativemaps/qdeclarativepolylinemapitem_p.h \
+ declarativemaps/qdeclarativerectanglemapitem_p.h \
+ declarativemaps/qdeclarativeroutemapitem_p.h \
+ declarativemaps/qgeomapitemgeometry_p.h \
+ declarativemaps/qgeomapobject_p.h \
+ declarativemaps/qgeomapobject_p_p.h \
+ declarativemaps/qparameterizableobject_p.h \
+ declarativemaps/qquickgeomapgesturearea_p.h \
+ ../imports/positioning/qquickgeocoordinateanimation_p.h
SOURCES += \
- declarativemaps/qdeclarativegeomapitemview.cpp \
- declarativemaps/qdeclarativegeoserviceprovider.cpp \
- declarativemaps/qdeclarativegeocodemodel.cpp \
- declarativemaps/qdeclarativegeoroutemodel.cpp \
- declarativemaps/qdeclarativegeoroute.cpp \
- declarativemaps/qdeclarativegeoroutesegment.cpp \
- declarativemaps/qdeclarativegeomaneuver.cpp \
- declarativemaps/qdeclarativegeomap.cpp \
- declarativemaps/qdeclarativegeomaptype.cpp \
- declarativemaps/qdeclarativegeomapitembase.cpp \
- declarativemaps/qdeclarativegeomapquickitem.cpp \
- declarativemaps/qdeclarativecirclemapitem.cpp \
- declarativemaps/qdeclarativerectanglemapitem.cpp \
- declarativemaps/qdeclarativepolygonmapitem.cpp \
- declarativemaps/qdeclarativepolylinemapitem.cpp \
- declarativemaps/qdeclarativeroutemapitem.cpp \
- declarativemaps/qdeclarativegeomapparameter.cpp \
- declarativemaps/qgeomapitemgeometry.cpp \
- declarativemaps/qdeclarativegeomapcopyrightsnotice.cpp \
- declarativemaps/error_messages.cpp \
- declarativemaps/locationvaluetypehelper.cpp \
- declarativemaps/qquickgeomapgesturearea.cpp \
- declarativemaps/qparameterizableobject.cpp \
- declarativemaps/qdeclarativegeomapitemgroup.cpp \
- declarativemaps/qgeomapobject.cpp \
- ../imports/positioning/qquickgeocoordinateanimation.cpp
+ declarativemaps/error_messages.cpp \
+ declarativemaps/locationvaluetypehelper.cpp \
+ declarativemaps/qdeclarativecirclemapitem.cpp \
+ declarativemaps/qdeclarativegeocodemodel.cpp \
+ declarativemaps/qdeclarativegeomaneuver.cpp \
+ declarativemaps/qdeclarativegeomapcopyrightsnotice.cpp \
+ declarativemaps/qdeclarativegeomap.cpp \
+ declarativemaps/qdeclarativegeomapitembase.cpp \
+ declarativemaps/qdeclarativegeomapitemgroup.cpp \
+ declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp \
+ declarativemaps/qdeclarativegeomapitemview.cpp \
+ declarativemaps/qdeclarativegeomapparameter.cpp \
+ declarativemaps/qdeclarativegeomapquickitem.cpp \
+ declarativemaps/qdeclarativegeomaptype.cpp \
+ declarativemaps/qdeclarativegeoroute.cpp \
+ declarativemaps/qdeclarativegeoroutemodel.cpp \
+ declarativemaps/qdeclarativegeoroutesegment.cpp \
+ declarativemaps/qdeclarativegeoserviceprovider.cpp \
+ declarativemaps/qdeclarativepolygonmapitem.cpp \
+ declarativemaps/qdeclarativepolylinemapitem.cpp \
+ declarativemaps/qdeclarativerectanglemapitem.cpp \
+ declarativemaps/qdeclarativeroutemapitem.cpp \
+ declarativemaps/qgeomapitemgeometry.cpp \
+ declarativemaps/qgeomapobject.cpp \
+ declarativemaps/qparameterizableobject.cpp \
+ declarativemaps/qquickgeomapgesturearea.cpp \
+ ../imports/positioning/qquickgeocoordinateanimation.cpp
load(qt_build_paths)
LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lpoly2tri$$qtPlatformTargetSuffix() -lclip2tri$$qtPlatformTargetSuffix()
diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp
index d201b6ab..00643ea1 100644
--- a/src/location/declarativemaps/qdeclarativegeomap.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomap.cpp
@@ -240,10 +240,13 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap()
for (QDeclarativeGeoMapItemView *v : qAsConst(m_mapViews)) {
if (!v)
continue;
- if (v->parent() == this)
+ if (v->parent() == this) {
delete v;
- else
- v->removeInstantiatedItems();
+ } else {
+ // FIXME: removeInstantiatedItems should abort, as well as exit transitions terminated
+ v->removeInstantiatedItems(false);
+ v->m_map = nullptr;
+ }
}
}
// remove any map items associations
@@ -251,19 +254,12 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap()
if (m_mapItems.at(i))
m_mapItems.at(i).data()->setMap(0,0);
}
- m_mapItems.clear();
- for (auto g: qAsConst(m_mapItemGroups)) {
- if (!g)
- continue;
- const QList<QQuickItem *> quickKids = g->childItems();
- for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *itemBase = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (itemBase)
- itemBase->setMap(0,0);
- }
+ // remove any map item groups associations
+ for (int i = 0; i < m_mapItemGroups.count(); ++i) {
+ if (m_mapItemGroups.at(i))
+ m_mapItemGroups.at(i).data()->setQuickMap(nullptr);
}
- m_mapItemGroups.clear();
if (m_copyrights.data())
delete m_copyrights.data();
@@ -470,28 +466,7 @@ void QDeclarativeGeoMap::populateMap()
kids.insert(ite);
for (QObject *k : qAsConst(kids)) {
- // dispatch items appropriately
- QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(k);
- if (mapView) {
- m_mapViews.append(mapView);
- setupMapView(mapView);
- continue;
- }
- QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(k);
- if (mapItem) {
- addMapItem(mapItem);
- continue;
- }
- // Allow to add to the map Map items contained inside a parent QQuickItem, but only those at one level of nesting.
- QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(k);
- if (itemGroup) {
- addMapItemGroup(itemGroup);
- continue;
- }
-
- QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(k);
- if (mapObject)
- addMapObject(mapObject);
+ addMapChild(k);
}
}
@@ -751,15 +726,9 @@ void QDeclarativeGeoMap::mappingManagerInitialized()
}
// Any map item groups that were added before the plugin was ready
- // need to have setMap called again on their children map items
- for (auto g: qAsConst(m_mapItemGroups)) {
- const QList<QQuickItem *> quickKids = g->childItems();
- for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *itemBase = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (itemBase)
- itemBase->setMap(this, m_map);
- }
- }
+ // DO NOT need to have setMap called again on their children map items
+ // because they have been added to m_mapItems, which is processed right above.
+
// All map parameters that were added before the plugin was ready
// need to be added to m_map
@@ -943,6 +912,58 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel, bool overzoom)
emit zoomLevelChanged(m_cameraData.zoomLevel());
}
+bool QDeclarativeGeoMap::addMapChild(QObject *child)
+{
+ // dispatch items appropriately
+ QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(child);
+ if (mapView)
+ return addMapItemView_real(mapView);
+
+ QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);
+ if (itemGroup) // addMapItemView calls addMapItemGroup
+ return addMapItemGroup_real(itemGroup);
+
+ QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
+ if (mapItem)
+ return addMapItem_real(mapItem);
+
+ QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(child);
+ if (mapObject)
+ addMapObject(mapObject); // this emits mapObjectsChanged, != mapItemsChanged
+ return false;
+}
+
+bool QDeclarativeGeoMap::removeMapChild(QObject *child)
+{
+ // dispatch items appropriately
+ QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(child);
+ if (mapView)
+ return removeMapItemView_real(mapView);
+
+ QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);
+ if (itemGroup) // removeMapItemView calls removeMapItemGroup for itself.
+ return removeMapItemGroup_real(itemGroup);
+
+ QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
+ if (mapItem)
+ return removeMapItem_real(mapItem);
+
+ QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(child);
+ if (mapObject)
+ removeMapObject(mapObject); // this emits mapObjectsChanged, != mapItemsChanged
+ return false;
+}
+
+bool QDeclarativeGeoMap::isGroupNested(QDeclarativeGeoMapItemGroup *group)
+{
+ QObject *parent = group->parent();
+ // Nested groups have parent set in parent's componentComplete()
+ // Those instantiated by MapItemView's delegateModel, however, do not,
+ // but have setParentItem set.
+ return qobject_cast<QDeclarativeGeoMapItemGroup *>(parent)
+ || qobject_cast<QDeclarativeGeoMapItemGroup *>(group->parentItem());
+}
+
qreal QDeclarativeGeoMap::zoomLevel() const
{
return m_cameraData.zoomLevel();
@@ -1708,39 +1729,6 @@ void QDeclarativeGeoMap::onAttachedCopyrightNoticeVisibilityChanged()
}
/*!
- \qmlmethod void QtLocation::Map::addMapItem(MapItem item)
-
- Adds the given \a item to the Map (for example MapQuickItem, MapCircle). If the object
- already is on the Map, it will not be added again.
-
- As an example, consider the case where you have a MapCircle representing your current position:
-
- \snippet declarative/maps.qml QtQuick import
- \snippet declarative/maps.qml QtLocation import
- \codeline
- \snippet declarative/maps.qml Map addMapItem MapCircle at current position
-
- \note MapItemViews cannot be added with this method.
-
- \sa mapItems, removeMapItem, clearMapItems
-*/
-
-void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item)
-{
- if (!item || item->quickMap())
- return;
- // If the item comes from a MapItemGroup, do not reparent it.
- if (!qobject_cast<QDeclarativeGeoMapItemGroup *>(item->parentItem()))
- item->setParentItem(this);
- m_mapItems.append(item);
- if (m_map) {
- item->setMap(this, m_map);
- m_map->addMapItem(item);
- }
- emit mapItemsChanged();
-}
-
-/*!
\qmlmethod void QtLocation::Map::addMapParameter(MapParameter parameter)
Adds a MapParameter object to the map. The effect of this call is dependent
@@ -1920,6 +1908,45 @@ QList<QObject *> QDeclarativeGeoMap::mapItems()
}
/*!
+ \qmlmethod void QtLocation::Map::addMapItem(MapItem item)
+
+ Adds the given \a item to the Map (for example MapQuickItem, MapCircle). If the object
+ already is on the Map, it will not be added again.
+
+ As an example, consider the case where you have a MapCircle representing your current position:
+
+ \snippet declarative/maps.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/maps.qml Map addMapItem MapCircle at current position
+
+ \note MapItemViews cannot be added with this method.
+
+ \sa mapItems, removeMapItem, clearMapItems
+*/
+
+void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ if (addMapItem_real(item))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::addMapItem_real(QDeclarativeGeoMapItemBase *item)
+{
+ if (!item || item->quickMap())
+ return false;
+ // If the item comes from a MapItemGroup, do not reparent it.
+ if (!qobject_cast<QDeclarativeGeoMapItemGroup *>(item->parentItem()))
+ item->setParentItem(this);
+ m_mapItems.append(item);
+ if (m_map) {
+ item->setMap(this, m_map);
+ m_map->addMapItem(item);
+ }
+ return true;
+}
+
+/*!
\qmlmethod void QtLocation::Map::removeMapItem(MapItem item)
Removes the given \a item from the Map (for example MapQuickItem, MapCircle). If
@@ -1930,18 +1957,25 @@ QList<QObject *> QDeclarativeGeoMap::mapItems()
*/
void QDeclarativeGeoMap::removeMapItem(QDeclarativeGeoMapItemBase *ptr)
{
- if (!ptr || !m_map)
- return;
- m_map->removeMapItem(ptr);
+ if (removeMapItem_real(ptr))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::removeMapItem_real(QDeclarativeGeoMapItemBase *ptr)
+{
+ if (!ptr)
+ return false;
QPointer<QDeclarativeGeoMapItemBase> item(ptr);
if (!m_mapItems.contains(item))
- return;
+ return false;
+ if (m_map)
+ m_map->removeMapItem(ptr);
if (item->parentItem() == this)
item->setParentItem(0);
item->setMap(0, 0);
// these can be optimized for perf, as we already check the 'contains' above
m_mapItems.removeOne(item);
- emit mapItemsChanged();
+ return true;
}
/*!
@@ -1955,18 +1989,25 @@ void QDeclarativeGeoMap::clearMapItems()
{
if (m_mapItems.isEmpty())
return;
- if (m_map)
- m_map->clearMapItems();
- for (auto i : qAsConst(m_mapItems)) {
- if (i) {
- i->setMap(0, 0);
- if (i->parentItem() == this)
- i->setParentItem(0);
- }
+
+ int removed = 0;
+ for (auto i : qAsConst(m_mapItemGroups)) {
+ // Processing only top-level groups (!views)
+ QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(i);
+ if (view)
+ continue;
+
+ if (i->parentItem() != this)
+ continue;
+
+ removed += removeMapItemGroup_real(i);
}
- m_mapItems.clear();
- m_mapItemGroups.clear();
- emit mapItemsChanged();
+
+ for (auto i : qAsConst(m_mapItems))
+ removed += removeMapItem_real(i);
+
+ if (removed)
+ emit mapItemsChanged();
}
/*!
@@ -1981,19 +2022,29 @@ void QDeclarativeGeoMap::clearMapItems()
*/
void QDeclarativeGeoMap::addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
{
- if (!itemGroup || itemGroup->quickMap()) // || Already added to some map
- return;
+ if (addMapItemGroup_real(itemGroup))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::addMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup)
+{
+ if (!itemGroup || itemGroup->quickMap()) // Already added to some map
+ return false;
itemGroup->setQuickMap(this);
+
+ if (!isGroupNested(itemGroup))
+ itemGroup->setParentItem(this);
+
QPointer<QDeclarativeGeoMapItemGroup> g(itemGroup);
m_mapItemGroups.append(g);
- const QList<QQuickItem *> quickKids = g->childItems();
+
+ const QList<QQuickItem *> quickKids = itemGroup->childItems();
+ int count = 0;
for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (mapItem)
- addMapItem(mapItem);
+ count += addMapChild(c); // this calls addMapItemGroup recursively, if needed
}
- itemGroup->setParentItem(this);
+ return count;
}
/*!
@@ -2007,21 +2058,28 @@ void QDeclarativeGeoMap::addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
*/
void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
{
+ if (removeMapItemGroup_real(itemGroup))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::removeMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup)
+{
if (!itemGroup || itemGroup->quickMap() != this) // cant remove an itemGroup added to another map
- return;
+ return false;
QPointer<QDeclarativeGeoMapItemGroup> g(itemGroup);
if (!m_mapItemGroups.removeOne(g))
- return;
+ return false;
const QList<QQuickItem *> quickKids = itemGroup->childItems();
+ int count = 0;
for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (mapItem)
- removeMapItem(mapItem);
+ count += removeMapChild(c);
}
itemGroup->setQuickMap(nullptr);
- itemGroup->setParentItem(0);
+ if (itemGroup->parentItem() == this)
+ itemGroup->setParentItem(0);
+ return count;
}
/*!
@@ -2035,14 +2093,23 @@ void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGro
*/
void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView)
{
+ if (removeMapItemView_real(itemView))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::removeMapItemView_real(QDeclarativeGeoMapItemView *itemView)
+{
if (!itemView || itemView->m_map != this) // can't remove a view that is already added to another map
- return;
+ return false;
+ // Leaving this as void since the removal is async (potentially transitioned)
+ // && the delegates *could* be empty mapItemGroups.
itemView->removeInstantiatedItems();
itemView->m_map = 0;
// it can be removed from the list at this point, since no operations that require a Map have to be done
// anymore on destruction.
m_mapViews.removeOne(itemView);
+ return removeMapItemGroup_real(itemView); // at this point, delegate instances have been removed.
}
/*!
@@ -2056,13 +2123,21 @@ void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView)
*/
void QDeclarativeGeoMap::addMapItemView(QDeclarativeGeoMapItemView *itemView)
{
+ if (addMapItemView_real(itemView))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::addMapItemView_real(QDeclarativeGeoMapItemView *itemView)
+{
if (!itemView || itemView->m_map) // can't add a view twice
- return;
+ return false;
+ int count = addMapItemGroup_real(itemView); // at this point, delegates aren't yet incubated.
// Not appending it to m_mapViews because it seems unnecessary even if the
// itemView is a child of this (in which case it would be destroyed
m_mapViews.append(itemView);
setupMapView(itemView);
+ return count;
}
/*!
diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h
index 6948b15b..02379411 100644
--- a/src/location/declarativemaps/qdeclarativegeomap_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomap_p.h
@@ -254,6 +254,16 @@ protected:
void setError(QGeoServiceProvider::Error error, const QString &errorString);
void initialize();
void setZoomLevel(qreal zoomLevel, bool overzoom);
+ bool addMapChild(QObject *child);
+ bool removeMapChild(QObject *child);
+ bool isGroupNested(QDeclarativeGeoMapItemGroup *group);
+
+ bool addMapItem_real(QDeclarativeGeoMapItemBase *item);
+ bool removeMapItem_real(QDeclarativeGeoMapItemBase *item);
+ bool addMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup);
+ bool removeMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup);
+ bool addMapItemView_real(QDeclarativeGeoMapItemView *itemView);
+ bool removeMapItemView_real(QDeclarativeGeoMapItemView *itemView);
private Q_SLOTS:
void mappingManagerInitialized();
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
index 366992ed..7de6afb5 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
@@ -85,10 +85,6 @@ QDeclarativeGeoMapItemBase::QDeclarativeGeoMapItemBase(QQuickItem *parent)
// Changing opacity on a mapItemGroup should affect also the opacity on the children.
// This must be notified to plugins, if they are to render the item.
connect(this, &QQuickItem::opacityChanged, this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
- parentGroup_ = qobject_cast<QDeclarativeGeoMapItemGroup *>(parent);
- if (parentGroup_)
- connect(qobject_cast<QDeclarativeGeoMapItemGroup *>(parent), &QQuickItem::opacityChanged,
- this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
}
QDeclarativeGeoMapItemBase::~QDeclarativeGeoMapItemBase()
@@ -285,49 +281,26 @@ QSGNode *QDeclarativeGeoMapItemBase::updateMapItemPaintNode(QSGNode *oldNode, Up
return 0;
}
+/*!
+ \internal
+
+ The actual combined opacity of the item. Needed by custom renderer to look like
+ the scene-graph one.
+*/
qreal QDeclarativeGeoMapItemBase::mapItemOpacity() const
{
if (parentGroup_)
- return parentGroup_->opacity() * opacity();
+ return parentGroup_->mapItemOpacity() * opacity();
return opacity();
}
-bool QDeclarativeGeoMapItemBase::prepareEnterTransition()
-{
- if (m_transitionManager->m_transitionState == QDeclarativeGeoMapItemTransitionManager::EnterTransition
- && m_transitionManager->isRunning())
- return false;
-
- if (m_transitionManager->m_transitionState != QDeclarativeGeoMapItemTransitionManager::EnterTransition) {
- setVisible(true);
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::EnterTransition;
- }
- return true;
-}
-
-bool QDeclarativeGeoMapItemBase::prepareExitTransition()
+void QDeclarativeGeoMapItemBase::setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup)
{
- if (m_transitionManager->m_transitionState == QDeclarativeGeoMapItemTransitionManager::ExitTransition
- && m_transitionManager->isRunning())
- return false;
-
- if (m_transitionManager->m_transitionState != QDeclarativeGeoMapItemTransitionManager::ExitTransition) {
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::ExitTransition;
+ parentGroup_ = &parentGroup;
+ if (parentGroup_) {
+ connect(parentGroup_, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged,
+ this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
}
- return true;
-}
-
-void QDeclarativeGeoMapItemBase::finalizeEnterTransition()
-{
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
- emit enterTransitionFinished();
-}
-
-void QDeclarativeGeoMapItemBase::finalizeExitTransition()
-{
- setVisible(false);
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
- emit exitTransitionFinished();
}
bool QDeclarativeGeoMapItemBase::isPolishScheduled() const
@@ -341,43 +314,4 @@ void QDeclarativeGeoMapItemBase::polishAndUpdate()
update();
}
-QDeclarativeGeoMapItemTransitionManager::QDeclarativeGeoMapItemTransitionManager(QDeclarativeGeoMapItemBase *mapItem)
- : QQuickTransitionManager(), m_mapItem(mapItem)
-{
-}
-
-void QDeclarativeGeoMapItemTransitionManager::transitionEnter()
-{
- if (m_transitionState == ExitTransition)
- cancel();
-
- if (!m_mapItem->prepareEnterTransition())
- return;
-
- if (m_view && m_view->m_enter)
- transition(enterActions, m_view->m_enter, m_mapItem);
- else
- finished();
-}
-
-void QDeclarativeGeoMapItemTransitionManager::transitionExit()
-{
- if (!m_mapItem->prepareExitTransition())
- return;
-
- if (m_view && m_view->m_exit)
- transition(exitActions, m_view->m_exit, m_mapItem);
- else
- finished();
-}
-
-void QDeclarativeGeoMapItemTransitionManager::finished()
-{
- if (m_transitionState == EnterTransition)
- m_mapItem->finalizeEnterTransition();
- else if (m_transitionState == ExitTransition)
- m_mapItem->finalizeExitTransition();
-}
-
-
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
index 4a2f9282..f884c13e 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
@@ -56,12 +56,11 @@
#include <QtLocation/private/qdeclarativegeomap_p.h>
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtLocation/private/qgeomap_p.h>
-#include <QtQuick/private/qquicktransitionmanager_p_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemtransitionmanager_p.h>
#include <QScopedPointer>
QT_BEGIN_NAMESPACE
-class QDeclarativeGeoMapItemTransitionManager;
-class QDeclarativeGeoMapItemBase;
+
class Q_LOCATION_PRIVATE_EXPORT QGeoMapViewportChangeEvent
{
public:
@@ -80,29 +79,6 @@ public:
bool rollChanged;
};
-class QDeclarativeGeoMapItemTransitionManager : public QQuickTransitionManager
-{
-public:
- enum TransitionState {
- NoTransition, EnterTransition, ExitTransition
- };
-
- QDeclarativeGeoMapItemTransitionManager(QDeclarativeGeoMapItemBase *mapItem);
-
- void transitionEnter();
- void transitionExit();
-
-protected:
- void finished() override;
-
-public:
- QDeclarativeGeoMapItemBase *m_mapItem;
- QDeclarativeGeoMapItemView *m_view = nullptr;
- QList<QQuickStateAction> enterActions;
- QList<QQuickStateAction> exitActions;
- TransitionState m_transitionState = NoTransition;
-};
-
class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemBase : public QQuickItem
{
Q_OBJECT
@@ -125,15 +101,12 @@ public:
virtual QGeoMap::ItemType itemType() const = 0;
qreal mapItemOpacity() const;
- virtual bool prepareEnterTransition();
- virtual bool prepareExitTransition();
- virtual void finalizeEnterTransition();
- virtual void finalizeExitTransition();
+ void setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup);
Q_SIGNALS:
void mapItemOpacityChanged();
- Q_REVISION(11) void enterTransitionFinished();
- Q_REVISION(11) void exitTransitionFinished();
+ Q_REVISION(12) void addTransitionFinished();
+ Q_REVISION(12) void removeTransitionFinished();
protected Q_SLOTS:
virtual void afterChildrenChanged();
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp b/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp
index b4d214ad..a51dcb31 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp
@@ -35,6 +35,8 @@
****************************************************************************/
#include "qdeclarativegeomapitemgroup_p.h"
+#include "qdeclarativegeomapitembase_p.h"
+#include "qdeclarativegeomap_p.h"
QT_BEGIN_NAMESPACE
@@ -135,9 +137,11 @@ QT_BEGIN_NAMESPACE
\image api-mapitemgroup.png
*/
-QDeclarativeGeoMapItemGroup::QDeclarativeGeoMapItemGroup(QQuickItem *parent): QQuickItem(parent), m_quickMap(nullptr)
+QDeclarativeGeoMapItemGroup::QDeclarativeGeoMapItemGroup(QQuickItem *parent)
+: QQuickItem(parent), m_quickMap(nullptr)
{
-
+ connect(this, &QQuickItem::opacityChanged,
+ this, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged);
}
QDeclarativeGeoMapItemGroup::~QDeclarativeGeoMapItemGroup()
@@ -145,9 +149,23 @@ QDeclarativeGeoMapItemGroup::~QDeclarativeGeoMapItemGroup()
}
+void QDeclarativeGeoMapItemGroup::setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup)
+{
+ m_parentGroup = &parentGroup;
+ connect(m_parentGroup, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged,
+ this, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged);
+}
+
void QDeclarativeGeoMapItemGroup::setQuickMap(QDeclarativeGeoMap *quickMap)
{
+ if (!quickMap && m_quickMap)
+ m_quickMap->disconnect(this);
m_quickMap = quickMap;
+ if (m_quickMap) {
+ onMapSizeChanged();
+ connect(m_quickMap, &QQuickItem::widthChanged, this, &QDeclarativeGeoMapItemGroup::onMapSizeChanged);
+ connect(m_quickMap, &QQuickItem::heightChanged, this, &QDeclarativeGeoMapItemGroup::onMapSizeChanged);
+ }
}
QDeclarativeGeoMap *QDeclarativeGeoMapItemGroup::quickMap() const
@@ -155,4 +173,45 @@ QDeclarativeGeoMap *QDeclarativeGeoMapItemGroup::quickMap() const
return m_quickMap;
}
+qreal QDeclarativeGeoMapItemGroup::mapItemOpacity() const
+{
+ return ((m_parentGroup) ? m_parentGroup->mapItemOpacity() : 1.0) * opacity();
+}
+
+void QDeclarativeGeoMapItemGroup::classBegin()
+{
+ QQuickItem::classBegin();
+}
+
+void QDeclarativeGeoMapItemGroup::componentComplete()
+{
+ QQuickItem::componentComplete();
+
+ // In certain cases the parent won't be set via the constructor, but rather later on
+ // during the instantiation/incubation process.
+ // Therefore calling setParentGroup here, when the parent is known.
+ // The childrenChanged use case to handle dynamically-added items is currently unsupported.
+ const QList<QQuickItem *> &quickKids = childItems();
+ for (QQuickItem *k : quickKids) {
+ QDeclarativeGeoMapItemGroup *childGroup
+ = qobject_cast<QDeclarativeGeoMapItemGroup *>(k);
+ if (childGroup) {
+ childGroup->setParentGroup(*this);
+ continue;
+ }
+ QDeclarativeGeoMapItemBase *childItem
+ = qobject_cast<QDeclarativeGeoMapItemBase *>(k);
+ if (childItem) {
+ childItem->setParentGroup(*this);
+ continue;
+ }
+ }
+}
+
+void QDeclarativeGeoMapItemGroup::onMapSizeChanged()
+{
+ setWidth(m_quickMap->width());
+ setHeight(m_quickMap->height());
+}
+
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h b/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h
index f91d291c..395e74a1 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h
@@ -49,6 +49,7 @@
//
#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemtransitionmanager_p.h>
#include <QtQuick/QQuickItem>
QT_BEGIN_NAMESPACE
@@ -61,10 +62,32 @@ public:
explicit QDeclarativeGeoMapItemGroup(QQuickItem *parent = 0);
virtual ~QDeclarativeGeoMapItemGroup();
+ void setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup);
void setQuickMap(QDeclarativeGeoMap *quickMap);
QDeclarativeGeoMap *quickMap() const;
+
+ qreal mapItemOpacity() const;
+
+Q_SIGNALS:
+ void mapItemOpacityChanged();
+ void addTransitionFinished();
+ void removeTransitionFinished();
+
+protected:
+ // QQmlParserStatus interface
+ void classBegin() override;
+ void componentComplete() override;
+
+protected slots:
+ void onMapSizeChanged();
+
private:
QDeclarativeGeoMap *m_quickMap;
+ QDeclarativeGeoMapItemGroup *m_parentGroup = nullptr;
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager> m_transitionManager;
+
+ friend class QDeclarativeGeoMapItemView;
+ friend class QDeclarativeGeoMapItemTransitionManager;
};
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp
new file mode 100644
index 00000000..549ab2cb
--- /dev/null
+++ b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativegeomapitemtransitionmanager_p.h"
+#include "qdeclarativegeomapitemview_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeGeoMapItemTransitionManager::QDeclarativeGeoMapItemTransitionManager(QObject *mapItem)
+ : QQuickTransitionManager(), m_mapItem(mapItem)
+{
+}
+
+void QDeclarativeGeoMapItemTransitionManager::transitionEnter()
+{
+ if (m_transitionState == ExitTransition)
+ cancel();
+
+ if (!prepareEnterTransition())
+ return;
+
+ if (m_view && m_view->m_enter)
+ transition(enterActions, m_view->m_enter, m_mapItem);
+ else
+ finished();
+}
+
+void QDeclarativeGeoMapItemTransitionManager::transitionExit()
+{
+ if (!prepareExitTransition())
+ return;
+
+ if (m_view && m_view->m_exit)
+ transition(exitActions, m_view->m_exit, m_mapItem);
+ else
+ finished();
+}
+
+void QDeclarativeGeoMapItemTransitionManager::finished()
+{
+ if (m_transitionState == EnterTransition)
+ finalizeEnterTransition();
+ else if (m_transitionState == ExitTransition)
+ finalizeExitTransition();
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h
new file mode 100644
index 00000000..0a83fe39
--- /dev/null
+++ b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEGEOMAPITEMTRANSITIONMANAGER_H
+#define QDECLARATIVEGEOMAPITEMTRANSITIONMANAGER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtQuick/QQuickItem>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeGeoMapItemView;
+
+class QDeclarativeGeoMapItemTransitionManager : public QQuickTransitionManager
+{
+public:
+ enum TransitionState {
+ NoTransition, EnterTransition, ExitTransition
+ };
+
+ QDeclarativeGeoMapItemTransitionManager(QObject *mapItem);
+
+ void transitionEnter();
+ void transitionExit();
+
+ bool prepareEnterTransition()
+ {
+ if (m_transitionState == QDeclarativeGeoMapItemTransitionManager::EnterTransition
+ && isRunning())
+ return false;
+
+ if (m_transitionState != QDeclarativeGeoMapItemTransitionManager::EnterTransition) {
+ // setVisible(true);
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::EnterTransition;
+ }
+ return true;
+ }
+ bool prepareExitTransition()
+ {
+ if (m_transitionState == QDeclarativeGeoMapItemTransitionManager::ExitTransition
+ && isRunning())
+ return false;
+
+ if (m_transitionState != QDeclarativeGeoMapItemTransitionManager::ExitTransition) {
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::ExitTransition;
+ }
+ return true;
+ }
+ void finalizeEnterTransition()
+ {
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
+ // use invokeMethod since this is used on both QDeclarativeGeoMapItemBase and QDeclarativeGeoMapItemGroup
+ QMetaObject::invokeMethod(m_mapItem, QByteArrayLiteral("addTransitionFinished").constData(), Qt::DirectConnection);
+ }
+ void finalizeExitTransition()
+ {
+// setVisible(false);
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
+ QMetaObject::invokeMethod(m_mapItem, QByteArrayLiteral("removeTransitionFinished").constData(), Qt::DirectConnection);
+ }
+
+protected:
+ void finished() override;
+
+public:
+ QObject *m_mapItem;
+ QDeclarativeGeoMapItemView *m_view = nullptr;
+ QList<QQuickStateAction> enterActions;
+ QList<QQuickStateAction> exitActions;
+ TransitionState m_transitionState = NoTransition;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
index dca92269..415eecb3 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
@@ -94,7 +94,7 @@ QT_BEGIN_NAMESPACE
*/
QDeclarativeGeoMapItemView::QDeclarativeGeoMapItemView(QQuickItem *parent)
- : QObject(parent), m_componentCompleted(false), m_delegate(0),
+ : QDeclarativeGeoMapItemGroup(parent), m_componentCompleted(false), m_delegate(0),
m_map(0), m_fitViewport(false), m_delegateModel(0)
{
m_exit = new QQuickTransition(this);
@@ -116,6 +116,7 @@ QDeclarativeGeoMapItemView::~QDeclarativeGeoMapItemView()
*/
void QDeclarativeGeoMapItemView::componentComplete()
{
+ QDeclarativeGeoMapItemGroup::componentComplete();
m_componentCompleted = true;
if (!m_itemModel.isNull())
m_delegateModel->setModel(m_itemModel);
@@ -128,6 +129,7 @@ void QDeclarativeGeoMapItemView::componentComplete()
void QDeclarativeGeoMapItemView::classBegin()
{
+ QDeclarativeGeoMapItemGroup::classBegin();
QQmlContext *ctx = qmlContext(this);
m_delegateModel = new QQmlDelegateModel(ctx, this);
m_delegateModel->classBegin();
@@ -154,10 +156,15 @@ void QDeclarativeGeoMapItemView::createdItem(int index, QObject */*object*/)
return;
// createdItem is emitted on asynchronous creation. In which case, object has to be invoked again.
// See QQmlDelegateModel::object for further info.
- QDeclarativeGeoMapItemBase *item =
- qobject_cast<QDeclarativeGeoMapItemBase *>(m_delegateModel->object(index, QQmlIncubator::Asynchronous));
+
+ if (m_incubationMode == QQmlIncubator::Synchronous) {
+ qWarning() << "createdItem invoked on Synchronous incubation";
+ return;
+ }
+
+ QQuickItem *item = qobject_cast<QQuickItem *>(m_delegateModel->object(index, m_incubationMode));
if (item)
- addItemToMap(item, index);
+ addDelegateToMap(item, index);
else
qWarning() << "createdItem for " << index << " produced a null item";
}
@@ -179,16 +186,13 @@ void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bo
for (auto rit = mapRemoves.rbegin(); rit != mapRemoves.rend(); ++rit) {
const QQmlChangeSet::Change &c = removes.at(rit->second);
for (int idx = c.end() - 1; idx >= c.start(); --idx)
- removeItemFromMap(idx);
+ removeDelegateFromMap(idx);
}
}
for (const QQmlChangeSet::Change &c: changeSet.inserts()) {
- for (int idx = c.start(); idx < c.end(); idx++) {
- QDeclarativeGeoMapItemBase *item =
- qobject_cast<QDeclarativeGeoMapItemBase *>(m_delegateModel->object(idx, QQmlIncubator::Asynchronous));
- addItemToMap(item, idx); // if not item, a createdItem signal will be emitted.
- }
+ for (int idx = c.start(); idx < c.end(); idx++)
+ addDelegateToMap(qobject_cast<QQuickItem *>(m_delegateModel->object(idx, m_incubationMode)), idx);
}
fitViewport();
@@ -290,14 +294,15 @@ void QDeclarativeGeoMapItemView::setMap(QDeclarativeGeoMap *map)
/*!
\internal
*/
-void QDeclarativeGeoMapItemView::removeInstantiatedItems()
+void QDeclarativeGeoMapItemView::removeInstantiatedItems(bool transition)
{
if (!m_map)
return;
+ // FIXME: removeInstantiatedItems should abort, as well as exit transitions terminated QTBUG-69195
// Backward as removeItemFromMap modifies m_instantiatedItems
for (int i = m_instantiatedItems.size() -1; i >= 0 ; i--)
- removeItemFromMap(i);
+ removeDelegateFromMap(i, transition);
}
/*!
@@ -312,19 +317,36 @@ void QDeclarativeGeoMapItemView::instantiateAllItems()
return;
// If here, m_delegateModel may contain data, but QQmlInstanceModel::object for each row hasn't been called yet.
- for (int i = 0; i < m_delegateModel->count(); i++) {
- QDeclarativeGeoMapItemBase *item =
- qobject_cast<QDeclarativeGeoMapItemBase *>(m_delegateModel->object(i, QQmlIncubator::Asynchronous));
- addItemToMap(item, i); // if not item, createdItem will be emitted.
- }
+ for (int i = 0; i < m_delegateModel->count(); i++)
+ addDelegateToMap(qobject_cast<QQuickItem *>(m_delegateModel->object(i, m_incubationMode)), i);
fitViewport();
}
-void QDeclarativeGeoMapItemView::removeItemFromMap(int index)
+void QDeclarativeGeoMapItemView::setIncubateDelegates(bool useIncubators)
+{
+ const QQmlIncubator::IncubationMode incubationMode =
+ (useIncubators) ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous;
+ if (m_incubationMode == incubationMode)
+ return;
+ m_incubationMode = incubationMode;
+ emit incubateDelegatesChanged();
+}
+
+bool QDeclarativeGeoMapItemView::incubateDelegates() const
+{
+ return m_incubationMode == QQmlIncubator::Asynchronous;
+}
+
+QList<QQuickItem *> QDeclarativeGeoMapItemView::mapItems()
+{
+ return m_instantiatedItems;
+}
+
+void QDeclarativeGeoMapItemView::removeDelegateFromMap(int index, bool transition)
{
if (index >= 0 && index < m_instantiatedItems.size()) {
- QDeclarativeGeoMapItemBase *item = m_instantiatedItems.takeAt(index);
+ QQuickItem *item = m_instantiatedItems.takeAt(index);
if (!item) {
if (m_incubatingItems.contains(index)) {
// cancel request
@@ -333,50 +355,106 @@ void QDeclarativeGeoMapItemView::removeItemFromMap(int index)
}
return;
}
- if (m_exit && m_map) {
- if (!item->m_transitionManager) {
- QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(item));
- item->m_transitionManager.swap(manager);
- item->m_transitionManager->m_view = this;
- }
- connect(item, &QDeclarativeGeoMapItemBase::exitTransitionFinished,
- this, &QDeclarativeGeoMapItemView::exitTransitionFinished);
- item->m_transitionManager->transitionExit();
+ // item can be either a QDeclarativeGeoMapItemBase or a QDeclarativeGeoMapItemGroup
+ if (m_exit && m_map && transition) {
+ transitionItemOut(item);
} else {
disconnect(item, 0, this, 0);
- if (m_map)
- m_map->removeMapItem(item);
+ removeDelegateFromMap(item);
+ item->setParentItem(nullptr); // Needed because
+ item->setParent(nullptr); // m_delegateModel->release(item) does not destroy the item most of the times!!
QQmlInstanceModel::ReleaseFlags releaseStatus = m_delegateModel->release(item);
+#ifdef QT_DEBUG
if (releaseStatus == QQmlInstanceModel::Referenced)
- qWarning() << "item "<< index << " still referenced";
+ qWarning() << "item "<< index << "(" << item << ") still referenced";
+#else
+ Q_UNUSED(releaseStatus)
+#endif
}
}
}
+void QDeclarativeGeoMapItemView::removeDelegateFromMap(QQuickItem *o)
+{
+ if (!m_map)
+ return;
+
+ QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(o);
+ if (item) {
+ m_map->removeMapItem(item);
+ return;
+ }
+ QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(o);
+ if (view) {
+ m_map->removeMapItemView(view);
+ return;
+ }
+ QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(o);
+ if (group) {
+ m_map->removeMapItemGroup(group);
+ return;
+ }
+}
+
+void QDeclarativeGeoMapItemView::transitionItemOut(QQuickItem *o)
+{
+ QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(o);
+ if (group) {
+ if (!group->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(group));
+ group->m_transitionManager.swap(manager);
+ group->m_transitionManager->m_view = this;
+ }
+ connect(group, SIGNAL(removeTransitionFinished()),
+ this, SLOT(exitTransitionFinished()));
+
+ group->m_transitionManager->transitionExit();
+ return;
+ }
+ QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(o);
+ if (item) {
+ if (!item->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager> manager(new QDeclarativeGeoMapItemTransitionManager(item));
+ item->m_transitionManager.swap(manager);
+ item->m_transitionManager->m_view = this;
+ }
+ connect(item, SIGNAL(removeTransitionFinished()),
+ this, SLOT(exitTransitionFinished()) );
+
+ item->m_transitionManager->transitionExit();
+ return;
+ }
+}
+
void QDeclarativeGeoMapItemView::exitTransitionFinished()
{
- QDeclarativeGeoMapItemBase *item = static_cast<QDeclarativeGeoMapItemBase *>(sender());
+ QQuickItem *item = qobject_cast<QQuickItem *>(sender());
+ if (!item)
+ return;
disconnect(item, 0, this, 0);
- if (m_map)
- m_map->removeMapItem(item);
+ removeDelegateFromMap(item);
+ item->setParentItem(nullptr);
+ item->setParent(nullptr);
QQmlInstanceModel::ReleaseFlags releaseStatus = m_delegateModel->release(item);
+#ifdef QT_DEBUG
if (releaseStatus == QQmlInstanceModel::Referenced)
qWarning() << "item "<<item<<" still referenced";
+#else
+ Q_UNUSED(releaseStatus)
+#endif
}
void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item, int index)
{
- if (m_map && item && item->quickMap() == m_map) // belonging to another map??
- return;
- if (m_map) {
- if (!item) {
- m_incubatingItems.insert(index);
- m_instantiatedItems.insert(index, nullptr);
+ if (m_map && item) { // belonging to another map??
+ if (item->quickMap() == m_map)
return;
- }
+ }
+ if (m_map) {
insertInstantiatedItem(index, item);
+ item->setParentItem(this);
m_map->addMapItem(item);
if (m_enter) {
if (!item->m_transitionManager) {
@@ -389,7 +467,7 @@ void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item,
}
}
-void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QDeclarativeGeoMapItemBase *o)
+void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QQuickItem *o)
{
if (m_incubatingItems.contains(index)) {
m_incubatingItems.remove(index);
@@ -399,6 +477,70 @@ void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QDeclarativeG
}
}
+void QDeclarativeGeoMapItemView::addItemViewToMap(QDeclarativeGeoMapItemView *item, int index)
+{
+ if (!item || (m_map && item->quickMap() == m_map))
+ return;
+
+ if (m_map) {
+ insertInstantiatedItem(index, item);
+ item->setParentItem(this);
+ m_map->addMapItemView(item);
+ if (m_enter) {
+ if (!item->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager> manager(new QDeclarativeGeoMapItemTransitionManager(item));
+ item->m_transitionManager.swap(manager);
+ }
+ item->m_transitionManager->m_view = this;
+ item->m_transitionManager->transitionEnter();
+ }
+ }
+}
+
+void QDeclarativeGeoMapItemView::addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index)
+{
+ if (!item || (m_map && item->quickMap() == m_map))
+ return;
+
+ if (m_map) {
+ insertInstantiatedItem(index, item);
+ item->setParentItem(this);
+ m_map->addMapItemGroup(item);
+ if (m_enter) {
+ if (!item->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(item));
+ item->m_transitionManager.swap(manager);
+ }
+ item->m_transitionManager->m_view = this;
+ item->m_transitionManager->transitionEnter();
+ }
+ }
+}
+
+void QDeclarativeGeoMapItemView::addDelegateToMap(QQuickItem *object, int index)
+{
+ if (!object) {
+ m_incubatingItems.insert(index);
+ m_instantiatedItems.insert(index, nullptr);
+ return;
+ }
+ QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object);
+ if (item) { // else createdItem will be emitted.
+ addItemToMap(item, index);
+ return;
+ }
+ QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(object);
+ if (view) {
+ addItemViewToMap(view, index);
+ return;
+ }
+ QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object);
+ if (group) {
+ addItemGroupToMap(group, index);
+ return;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
index 9e1bebad..58ef2835 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
@@ -58,6 +58,7 @@
#include <QtQml/qqml.h>
#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquicktransition_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemgroup_p.h>
QT_BEGIN_NAMESPACE
@@ -71,18 +72,19 @@ class QQmlOpenMetaObjectType;
class MapItemViewDelegateIncubator;
class QDeclarativeGeoMapItemViewItemData;
class QDeclarativeGeoMapItemView;
+class QDeclarativeGeoMapItemGroup;
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemView : public QObject, public QQmlParserStatus
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemView : public QDeclarativeGeoMapItemGroup
{
Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
-
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(bool autoFitViewport READ autoFitViewport WRITE setAutoFitViewport NOTIFY autoFitViewportChanged)
Q_PROPERTY(QQuickTransition *add MEMBER m_enter REVISION 12)
Q_PROPERTY(QQuickTransition *remove MEMBER m_exit REVISION 12)
+ Q_PROPERTY(QList<QQuickItem *> mapItems READ mapItems REVISION 12)
+ Q_PROPERTY(bool incubateDelegates READ incubateDelegates WRITE setIncubateDelegates NOTIFY incubateDelegatesChanged REVISION 12)
public:
explicit QDeclarativeGeoMapItemView(QQuickItem *parent = 0);
@@ -98,9 +100,14 @@ public:
void setAutoFitViewport(const bool &fit);
void setMap(QDeclarativeGeoMap *);
- void removeInstantiatedItems();
+ void removeInstantiatedItems(bool transition = true);
void instantiateAllItems();
+ void setIncubateDelegates(bool useIncubators);
+ bool incubateDelegates() const;
+
+ QList<QQuickItem *> mapItems();
+
// From QQmlParserStatus
void componentComplete() override;
void classBegin() override;
@@ -109,6 +116,7 @@ Q_SIGNALS:
void modelChanged();
void delegateChanged();
void autoFitViewportChanged();
+ void incubateDelegatesChanged();
private Q_SLOTS:
void destroyingItem(QObject *object);
@@ -119,15 +127,22 @@ private Q_SLOTS:
private:
void fitViewport();
- void removeItemFromMap(int index);
+ void removeDelegateFromMap(int index, bool transition = true);
+ void removeDelegateFromMap(QQuickItem *o);
+ void transitionItemOut(QQuickItem *o);
+
+ void insertInstantiatedItem(int index, QQuickItem *o);
void addItemToMap(QDeclarativeGeoMapItemBase *item, int index);
- void insertInstantiatedItem(int index, QDeclarativeGeoMapItemBase *o);
+ void addItemViewToMap(QDeclarativeGeoMapItemView *item, int index);
+ void addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index);
+ void addDelegateToMap(QQuickItem *object, int index);
bool m_componentCompleted;
+ QQmlIncubator::IncubationMode m_incubationMode = QQmlIncubator::Asynchronous;
QQmlComponent *m_delegate;
QVariant m_itemModel;
QDeclarativeGeoMap *m_map;
- QList<QDeclarativeGeoMapItemBase *> m_instantiatedItems;
+ QList<QQuickItem *> m_instantiatedItems;
QSet<int> m_incubatingItems;
bool m_fitViewport;
QQmlDelegateModel *m_delegateModel;
diff --git a/tests/auto/declarative_ui/tst_map_itemview.qml b/tests/auto/declarative_ui/tst_map_itemview.qml
index 097212ca..0ab9d494 100644
--- a/tests/auto/declarative_ui/tst_map_itemview.qml
+++ b/tests/auto/declarative_ui/tst_map_itemview.qml
@@ -28,7 +28,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtLocation 5.6
+import QtLocation 5.12
import QtPositioning 5.5
import QtLocation.Test 5.5
@@ -49,6 +49,7 @@ Item {
MapItemView {
id: routeItemViewExtra
model: routeModel
+ incubateDelegates: false
delegate: Component {
MapRoute {
route: routeData
@@ -58,6 +59,10 @@ Item {
MapItemView {
id: listModelItemViewExtra
+ objectName: "listModelItemViewExtra"
+ incubateDelegates: false
+ add: null
+ remove: null
model: ListModel {
id: testingListModelExtra
ListElement { lat: 11; lon: 31 }
@@ -252,6 +257,9 @@ Item {
MapItemView {
id: listModelItemView
+ incubateDelegates: false
+ add: null
+ remove: null
model: ListModel {
id: testingListModel
ListElement { lat: 11; lon: 31 }
@@ -487,7 +495,7 @@ Item {
testingListModelExtra.clear()
tryCompare(mapForTestingListModel, "mapItemsLength", 0)
mapForTestingListModel.removeMapItemView(listModelItemViewExtra)
-
+ tryCompare(mapForTestingListModel, "mapItemsLength", 0)
mapForTestingListModel.addMapItemView(listModelItemView)
tryCompare(mapForTestingListModel, "mapItemsLength", 3)