From c6d41bdb24dbfcd846ca2669cee7b83be3e7be0a Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 9 Jun 2017 15:56:41 +0200 Subject: Add invokables to add/remove mapItemViews This patch adds two new methods to QDeclarativeGeoMap, to allow users to add or remove MapItemViews at runtime. [ChangeLog][QtLocation][Map] Added methods to add or remove MapItemViews at runtime. Task-number: QTBUG-55782 Change-Id: I4e612a9476a864331f61d49dac811a8069ae010f Reviewed-by: Alex Blasche --- .../declarativemaps/qdeclarativegeomap.cpp | 55 +++++++++++++++- .../declarativemaps/qdeclarativegeomap_p.h | 3 + .../declarativemaps/qdeclarativegeomapitemview.cpp | 3 + .../declarativemaps/qdeclarativegeomapitemview_p.h | 1 + tests/auto/declarative_ui/tst_map_itemview.qml | 77 ++++++++++++++++++++++ 5 files changed, 137 insertions(+), 2 deletions(-) diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp index 67130bb9..19bc57ce 100644 --- a/src/location/declarativemaps/qdeclarativegeomap.cpp +++ b/src/location/declarativemaps/qdeclarativegeomap.cpp @@ -222,8 +222,18 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap() m_map->clearMapItems(); } - if (!m_mapViews.isEmpty()) - qDeleteAll(m_mapViews); + // This forces the destruction of the associated items now, not when QObject destructor is called, at which point + // QDeclarativeGeoMap is long gone + if (!m_mapViews.isEmpty()) { + for (QDeclarativeGeoMapItemView *v : qAsConst(m_mapViews)) { + if (!v) + continue; + if (v->parent() == this) + delete v; + else + v->removeInstantiatedItems(); + } + } // remove any map items associations for (int i = 0; i < m_mapItems.count(); ++i) { if (m_mapItems.at(i)) @@ -1952,6 +1962,47 @@ void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGro itemGroup->setParentItem(0); } +/*! + \qmlmethod void QtLocation::Map::removeMapItemView(MapItemView itemView) + + Removes \a itemView and the items instantiated by it from the Map. + + \sa MapItemView, addMapItemView + + \since 5.10 +*/ +void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView) +{ + if (!itemView || itemView->map_ != this) // can't remove a view that is already added to another map + return; + + itemView->removeInstantiatedItems(); + itemView->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); +} + +/*! + \qmlmethod void QtLocation::Map::addMapItemView(MapItemView itemView) + + Adds \a itemView to the Map. + + \sa MapItemView, removeMapItemView + + \since 5.10 +*/ +void QDeclarativeGeoMap::addMapItemView(QDeclarativeGeoMapItemView *itemView) +{ + if (!itemView || itemView->map_) // can't add a view twice + return; + + // 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); +} + /*! \qmlproperty MapType QtLocation::Map::activeMapType diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h index f88eb03f..90e73420 100644 --- a/src/location/declarativemaps/qdeclarativegeomap_p.h +++ b/src/location/declarativemaps/qdeclarativegeomap_p.h @@ -164,6 +164,9 @@ public: Q_INVOKABLE void addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup); Q_INVOKABLE void removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup); + Q_INVOKABLE void removeMapItemView(QDeclarativeGeoMapItemView *itemView); + Q_INVOKABLE void addMapItemView(QDeclarativeGeoMapItemView *itemView); + Q_INVOKABLE void clearMapItems(); QList mapItems(); diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp index a17bf672..d8c19528 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp @@ -431,6 +431,9 @@ void QDeclarativeGeoMapItemView::instantiateAllItems() fitViewport(); } +/* + * used internally +*/ void QDeclarativeGeoMapItemView::removeItemData(QDeclarativeGeoMapItemViewItemData *itemData) { if (!itemData) diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h index 8c83e37d..8f1a081f 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h +++ b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h @@ -141,6 +141,7 @@ private: int m_readyIncubators; bool m_repopulating; + friend class QDeclarativeGeoMap; friend class QDeclarativeGeoMapItemViewItemData; friend class MapItemViewDelegateIncubator; }; diff --git a/tests/auto/declarative_ui/tst_map_itemview.qml b/tests/auto/declarative_ui/tst_map_itemview.qml index bbd70c8e..ff24e7af 100644 --- a/tests/auto/declarative_ui/tst_map_itemview.qml +++ b/tests/auto/declarative_ui/tst_map_itemview.qml @@ -46,6 +46,35 @@ Item { && mapForTestingListModel.mapReady && mapForTestingRouteModel.mapReady + MapItemView { + id: routeItemViewExtra + model: routeModel + delegate: Component { + MapRoute { + route: routeData + } + } + } + + MapItemView { + id: listModelItemViewExtra + model: ListModel { + id: testingListModelExtra + ListElement { lat: 11; lon: 31 } + ListElement { lat: 12; lon: 32 } + ListElement { lat: 13; lon: 33 } + } + delegate: Component { + MapCircle { + radius: 1500000 + center { + latitude: lat + longitude: lon + } + } + } + } + Map { id: map objectName: 'staticallyDeclaredMap' @@ -432,6 +461,42 @@ Item { testingListModel.clear() compare(mapForTestingListModel.mapItems.length, 0) + + // Repopulating the model with initial data + testingListModel.append({ "lat": 11, "lon": 31 }) + testingListModel.append({ "lat": 12, "lon": 32 }) + testingListModel.append({ "lat": 13, "lon": 33 }) + } + + function test_add_extra_listmodel() { + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 6) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 6) + mapForTestingListModel.removeMapItemView(listModelItemView) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 0) + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + testingListModelExtra.clear() + tryCompare(mapForTestingListModel, "mapItemsLength", 0) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + + mapForTestingListModel.addMapItemView(listModelItemView) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + + testingListModelExtra.append({ "lat": 11, "lon": 31 }) + testingListModelExtra.append({ "lat": 12, "lon": 32 }) + testingListModelExtra.append({ "lat": 13, "lon": 33 }) + + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 6) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) } function test_routemodel() { @@ -451,6 +516,18 @@ Item { routeQuery.numberAlternativeRoutes = 3 routeModel.update(); tryCompare(mapForTestingRouteModel, "mapItemsLength", 3) + + // Test adding the extra mapitemview fed from the same route model + mapForTestingRouteModel.addMapItemView(routeItemViewExtra) + tryCompare(mapForTestingRouteModel, "mapItemsLength", 6) + routeQuery.numberAlternativeRoutes = 4 + routeModel.update(); + tryCompare(mapForTestingRouteModel, "mapItemsLength", 8) + routeQuery.numberAlternativeRoutes = 3 + routeModel.update(); + mapForTestingRouteModel.removeMapItemView(routeItemViewExtra) + tryCompare(mapForTestingRouteModel, "mapItemsLength", 3) + mapForTestingRouteModel.addMapItem(externalCircle2) compare(mapForTestingRouteModel.mapItems.length, 4) compare(mapForTestingRouteModel.mapItems[3], externalCircle2) -- cgit v1.2.1