| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2015 Jolla Ltd. | 
| 4 | ** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> | 
| 5 | ** Copyright (C) 2015 The Qt Company Ltd. | 
| 6 | ** Contact: http://www.qt.io/licensing/ | 
| 7 | ** | 
| 8 | ** This file is part of the QtLocation module of the Qt Toolkit. | 
| 9 | ** | 
| 10 | ** $QT_BEGIN_LICENSE:LGPL3$ | 
| 11 | ** Commercial License Usage | 
| 12 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 13 | ** accordance with the commercial license agreement provided with the | 
| 14 | ** Software or, alternatively, in accordance with the terms contained in | 
| 15 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 16 | ** and conditions see http://www.qt.io/terms-conditions. For further | 
| 17 | ** information use the contact form at http://www.qt.io/contact-us. | 
| 18 | ** | 
| 19 | ** GNU Lesser General Public License Usage | 
| 20 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 21 | ** General Public License version 3 as published by the Free Software | 
| 22 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the | 
| 23 | ** packaging of this file. Please review the following information to | 
| 24 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 25 | ** will be met: https://www.gnu.org/licenses/lgpl.html. | 
| 26 | ** | 
| 27 | ** GNU General Public License Usage | 
| 28 | ** Alternatively, this file may be used under the terms of the GNU | 
| 29 | ** General Public License version 2.0 or later as published by the Free | 
| 30 | ** Software Foundation and appearing in the file LICENSE.GPL included in | 
| 31 | ** the packaging of this file. Please review the following information to | 
| 32 | ** ensure the GNU General Public License version 2.0 requirements will be | 
| 33 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. | 
| 34 | ** | 
| 35 | ** $QT_END_LICENSE$ | 
| 36 | ** | 
| 37 | ****************************************************************************/ | 
| 38 |  | 
| 39 | #include "qdeclarativegeomapitemview_p.h" | 
| 40 | #include "qdeclarativegeomap_p.h" | 
| 41 | #include "qdeclarativegeomapitembase_p.h" | 
| 42 |  | 
| 43 | #include <QtCore/QAbstractItemModel> | 
| 44 | #include <QtQml/QQmlContext> | 
| 45 | #include <QtQml/private/qqmlopenmetaobject_p.h> | 
| 46 | #include <QtQuick/private/qquickanimation_p.h> | 
| 47 | #include <QtQml/QQmlListProperty> | 
| 48 |  | 
| 49 | QT_BEGIN_NAMESPACE | 
| 50 |  | 
| 51 | /*! | 
| 52 |     \qmltype MapItemView | 
| 53 |     \instantiates QDeclarativeGeoMapItemView | 
| 54 |     \inqmlmodule QtLocation | 
| 55 |     \ingroup qml-QtLocation5-maps | 
| 56 |     \since QtLocation 5.5 | 
| 57 |     \inherits QObject | 
| 58 |  | 
| 59 |     \brief The MapItemView is used to populate Map from a model. | 
| 60 |  | 
| 61 |     The MapItemView is used to populate Map with MapItems from a model. | 
| 62 |     The MapItemView type only makes sense when contained in a Map, | 
| 63 |     meaning that it has no standalone presentation. | 
| 64 |  | 
| 65 |     \section2 Example Usage | 
| 66 |  | 
| 67 |     This example demonstrates how to use the MapViewItem object to display | 
| 68 |     a \l{Route}{route} on a \l{Map}{map}: | 
| 69 |  | 
| 70 |     \snippet declarative/maps.qml QtQuick import | 
| 71 |     \snippet declarative/maps.qml QtLocation import | 
| 72 |     \codeline | 
| 73 |     \snippet declarative/maps.qml MapRoute | 
| 74 | */ | 
| 75 |  | 
| 76 | /*! | 
| 77 |     \qmlproperty Transition QtLocation::MapItemView::add | 
| 78 |  | 
| 79 |     This property holds the transition that is applied to the map items created by the view | 
| 80 |     when they are instantiated and added to the map. | 
| 81 |  | 
| 82 |     \since QtLocation 5.12 | 
| 83 | */ | 
| 84 |  | 
| 85 | /*! | 
| 86 |     \qmlproperty Transition QtLocation::MapItemView::remove | 
| 87 |  | 
| 88 |     This property holds the transition that is applied to the map items created by the view | 
| 89 |     when they are removed. | 
| 90 |  | 
| 91 |     \since QtLocation 5.12 | 
| 92 | */ | 
| 93 |  | 
| 94 | QDeclarativeGeoMapItemView::QDeclarativeGeoMapItemView(QQuickItem *parent) | 
| 95 |     : QDeclarativeGeoMapItemGroup(parent), m_componentCompleted(false), m_delegate(0), | 
| 96 |       m_map(0), m_fitViewport(false), m_delegateModel(0) | 
| 97 | { | 
| 98 |         m_exit = new QQuickTransition(this); | 
| 99 |         QQmlListProperty<QQuickAbstractAnimation> anims = m_exit->animations(); | 
| 100 |         QQuickNumberAnimation *ani = new QQuickNumberAnimation(m_exit); | 
| 101 |         ani->setProperty(QStringLiteral("opacity" )); | 
| 102 |         ani->setTo(0.0); | 
| 103 |         ani->setDuration(300.0); | 
| 104 |         anims.append(&anims, ani); | 
| 105 | } | 
| 106 |  | 
| 107 | QDeclarativeGeoMapItemView::~QDeclarativeGeoMapItemView() | 
| 108 | { | 
| 109 |     // No need to remove instantiated items: if the MIV has instantiated items because it has been added | 
| 110 |     // to a Map (or is child of a Map), the Map destructor takes care of removing it and the instantiated items. | 
| 111 | } | 
| 112 |  | 
| 113 | /*! | 
| 114 |     \internal | 
| 115 | */ | 
| 116 | void QDeclarativeGeoMapItemView::componentComplete() | 
| 117 | { | 
| 118 |     QDeclarativeGeoMapItemGroup::componentComplete(); | 
| 119 |     m_componentCompleted = true; | 
| 120 |     if (!m_itemModel.isNull()) | 
| 121 |         m_delegateModel->setModel(m_itemModel); | 
| 122 |  | 
| 123 |     if (m_delegate) | 
| 124 |         m_delegateModel->setDelegate(m_delegate); | 
| 125 |  | 
| 126 |     m_delegateModel->componentComplete(); | 
| 127 | } | 
| 128 |  | 
| 129 | void QDeclarativeGeoMapItemView::classBegin() | 
| 130 | { | 
| 131 |     QDeclarativeGeoMapItemGroup::classBegin(); | 
| 132 |     QQmlContext *ctx = qmlContext(this); | 
| 133 |     m_delegateModel = new QQmlDelegateModel(ctx, this); | 
| 134 |     m_delegateModel->classBegin(); | 
| 135 |  | 
| 136 |     connect(sender: m_delegateModel, signal: &QQmlInstanceModel::modelUpdated, receiver: this, slot: &QDeclarativeGeoMapItemView::modelUpdated); | 
| 137 |     connect(sender: m_delegateModel, signal: &QQmlInstanceModel::createdItem, receiver: this, slot: &QDeclarativeGeoMapItemView::createdItem); | 
| 138 | //    connect(m_delegateModel, &QQmlInstanceModel::destroyingItem, this, &QDeclarativeGeoMapItemView::destroyingItem); | 
| 139 | //    connect(m_delegateModel, &QQmlInstanceModel::initItem, this, &QDeclarativeGeoMapItemView::initItem); | 
| 140 | } | 
| 141 |  | 
| 142 | void QDeclarativeGeoMapItemView::destroyingItem(QObject * /*object*/) | 
| 143 | { | 
| 144 |  | 
| 145 | } | 
| 146 |  | 
| 147 | void QDeclarativeGeoMapItemView::initItem(int /*index*/, QObject * /*object*/) | 
| 148 | { | 
| 149 |  | 
| 150 | } | 
| 151 |  | 
| 152 | void QDeclarativeGeoMapItemView::createdItem(int index, QObject * /*object*/) | 
| 153 | { | 
| 154 |     if (!m_map) | 
| 155 |         return; | 
| 156 |     // createdItem is emitted on asynchronous creation. In which case, object has to be invoked again. | 
| 157 |     // See QQmlDelegateModel::object for further info. | 
| 158 |  | 
| 159 |     // DelegateModel apparently triggers this method in any case, that is: | 
| 160 |     // 1. Synchronous incubation, delegate instantiated on the first object() call (during the object() call!) | 
| 161 |     // 2. Async incubation, delegate not instantiated on the first object() call | 
| 162 |     // 3. Async incubation, delegate present in the cache, and returned on the first object() call. | 
| 163 |     //   createdItem also called during the object() call. | 
| 164 |     if (m_creatingObject) { | 
| 165 |         // Falling into case 1. or 3. Returning early to prevent double referencing the delegate instance. | 
| 166 |         return; | 
| 167 |     } | 
| 168 |  | 
| 169 |     QQuickItem *item = qobject_cast<QQuickItem *>(object: m_delegateModel->object(index, incubationMode: m_incubationMode)); | 
| 170 |     if (item) | 
| 171 |         addDelegateToMap(object: item, index, createdItem: true); | 
| 172 |     else | 
| 173 |         qWarning() << "QQmlDelegateModel:: object called in createdItem for "  << index << " produced a null item" ; | 
| 174 | } | 
| 175 |  | 
| 176 | void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset) | 
| 177 | { | 
| 178 |     if (!m_map) // everything will be done in instantiateAllItems. Removal is done by declarativegeomap. | 
| 179 |         return; | 
| 180 |  | 
| 181 |     // move changes are expressed as one remove + one insert, with the same moveId. | 
| 182 |     // For simplicity, they will be treated as remove + insert. | 
| 183 |     // Changes will be also ignored, as they represent only data changes, not layout changes | 
| 184 |     if (reset) { // Assuming this means "remove everything already instantiated" | 
| 185 |         removeInstantiatedItems(); | 
| 186 |     } else { | 
| 187 |         // Remove items from the back to the front to retain the mapping to what is received from the changesets | 
| 188 |         const QVector<QQmlChangeSet::Change> &removes = changeSet.removes(); | 
| 189 |         std::map<int, int> mapRemoves; | 
| 190 |         for (int i = 0; i < removes.size(); i++) | 
| 191 |             mapRemoves.insert(x: std::pair<int, int>(removes.at(i).start(), i)); | 
| 192 |  | 
| 193 |         for (auto rit = mapRemoves.rbegin(); rit != mapRemoves.rend(); ++rit) { | 
| 194 |             const QQmlChangeSet::Change &c = removes.at(i: rit->second); | 
| 195 |             for (int idx = c.end() - 1; idx >= c.start(); --idx) | 
| 196 |                 removeDelegateFromMap(index: idx); | 
| 197 |         } | 
| 198 |     } | 
| 199 |  | 
| 200 |     QBoolBlocker createBlocker(m_creatingObject, true); | 
| 201 |     for (const QQmlChangeSet::Change &c: changeSet.inserts()) { | 
| 202 |         for (int idx = c.start(); idx < c.end(); idx++) { | 
| 203 |             QObject *delegateInstance = m_delegateModel->object(index: idx, incubationMode: m_incubationMode); | 
| 204 |             addDelegateToMap(object: qobject_cast<QQuickItem *>(object: delegateInstance), index: idx); | 
| 205 |         } | 
| 206 |     } | 
| 207 |  | 
| 208 |     fitViewport(); | 
| 209 | } | 
| 210 |  | 
| 211 | /*! | 
| 212 |     \qmlproperty model QtLocation::MapItemView::model | 
| 213 |  | 
| 214 |     This property holds the model that provides data used for creating the map items defined by the | 
| 215 |     delegate. Only QAbstractItemModel based models are supported. | 
| 216 | */ | 
| 217 | QVariant QDeclarativeGeoMapItemView::model() const | 
| 218 | { | 
| 219 |     return m_itemModel; | 
| 220 | } | 
| 221 |  | 
| 222 | void QDeclarativeGeoMapItemView::setModel(const QVariant &model) | 
| 223 | { | 
| 224 |     if (model == m_itemModel) | 
| 225 |         return; | 
| 226 |  | 
| 227 |     m_itemModel = model; | 
| 228 |     if (m_componentCompleted) | 
| 229 |         m_delegateModel->setModel(m_itemModel); | 
| 230 |  | 
| 231 |     emit modelChanged(); | 
| 232 | } | 
| 233 |  | 
| 234 | /*! | 
| 235 |     \qmlproperty Component QtLocation::MapItemView::delegate | 
| 236 |  | 
| 237 |     This property holds the delegate which defines how each item in the | 
| 238 |     model should be displayed. The Component must contain exactly one | 
| 239 |     MapItem -derived object as the root object. | 
| 240 | */ | 
| 241 | QQmlComponent *QDeclarativeGeoMapItemView::delegate() const | 
| 242 | { | 
| 243 |     return m_delegate; | 
| 244 | } | 
| 245 |  | 
| 246 | void QDeclarativeGeoMapItemView::setDelegate(QQmlComponent *delegate) | 
| 247 | { | 
| 248 |     if (m_delegate == delegate) | 
| 249 |         return; | 
| 250 |  | 
| 251 |     m_delegate = delegate; | 
| 252 |     if (m_componentCompleted) | 
| 253 |         m_delegateModel->setDelegate(m_delegate); | 
| 254 |  | 
| 255 |     emit delegateChanged(); | 
| 256 | } | 
| 257 |  | 
| 258 | /*! | 
| 259 |     \qmlproperty Component QtLocation::MapItemView::autoFitViewport | 
| 260 |  | 
| 261 |     This property controls whether to automatically pan and zoom the viewport | 
| 262 |     to display all map items when items are added or removed. | 
| 263 |  | 
| 264 |     Defaults to false. | 
| 265 | */ | 
| 266 | bool QDeclarativeGeoMapItemView::autoFitViewport() const | 
| 267 | { | 
| 268 |     return m_fitViewport; | 
| 269 | } | 
| 270 |  | 
| 271 | void QDeclarativeGeoMapItemView::setAutoFitViewport(const bool &fit) | 
| 272 | { | 
| 273 |     if (fit == m_fitViewport) | 
| 274 |         return; | 
| 275 |     m_fitViewport = fit; | 
| 276 |     fitViewport(); | 
| 277 |     emit autoFitViewportChanged(); | 
| 278 | } | 
| 279 |  | 
| 280 | /*! | 
| 281 |     \internal | 
| 282 | */ | 
| 283 | void QDeclarativeGeoMapItemView::fitViewport() | 
| 284 | { | 
| 285 |  | 
| 286 |     if (!m_map || !m_map->mapReady() || !m_fitViewport) | 
| 287 |         return; | 
| 288 |  | 
| 289 |     if (m_map->mapItems().size() > 0) | 
| 290 |         m_map->fitViewportToMapItems(); | 
| 291 | } | 
| 292 |  | 
| 293 | /*! | 
| 294 |     \internal | 
| 295 | */ | 
| 296 | void QDeclarativeGeoMapItemView::setMap(QDeclarativeGeoMap *map) | 
| 297 | { | 
| 298 |     if (!map || m_map) // changing map on the fly not supported | 
| 299 |         return; | 
| 300 |     m_map = map; | 
| 301 |     instantiateAllItems(); | 
| 302 | } | 
| 303 |  | 
| 304 | /*! | 
| 305 |     \internal | 
| 306 | */ | 
| 307 | void QDeclarativeGeoMapItemView::removeInstantiatedItems(bool transition) | 
| 308 | { | 
| 309 |     if (!m_map) | 
| 310 |         return; | 
| 311 |  | 
| 312 |     // with transition = false removeInstantiatedItems aborts ongoing exit transitions //QTBUG-69195 | 
| 313 |     // Backward as removeItemFromMap modifies m_instantiatedItems | 
| 314 |     for (int i = m_instantiatedItems.size() -1; i >= 0 ; i--) | 
| 315 |         removeDelegateFromMap(index: i, transition); | 
| 316 | } | 
| 317 |  | 
| 318 | /*! | 
| 319 |     \internal | 
| 320 |  | 
| 321 |     Instantiates all items. | 
| 322 | */ | 
| 323 | void QDeclarativeGeoMapItemView::instantiateAllItems() | 
| 324 | { | 
| 325 |     // The assumption is that if m_instantiatedItems isn't empty, instantiated items have been already added | 
| 326 |     if (!m_componentCompleted || !m_map || !m_delegate || m_itemModel.isNull() || !m_instantiatedItems.isEmpty()) | 
| 327 |         return; | 
| 328 |  | 
| 329 |     // If here, m_delegateModel may contain data, but QQmlInstanceModel::object for each row hasn't been called yet. | 
| 330 |     QBoolBlocker createBlocker(m_creatingObject, true); | 
| 331 |     for (int i = 0; i < m_delegateModel->count(); i++) { | 
| 332 |         QObject *delegateInstance = m_delegateModel->object(index: i, incubationMode: m_incubationMode); | 
| 333 |         addDelegateToMap(object: qobject_cast<QQuickItem *>(object: delegateInstance), index: i); | 
| 334 |     } | 
| 335 |  | 
| 336 |     fitViewport(); | 
| 337 | } | 
| 338 |  | 
| 339 | void QDeclarativeGeoMapItemView::setIncubateDelegates(bool useIncubators) | 
| 340 | { | 
| 341 |     const QQmlIncubator::IncubationMode incubationMode = | 
| 342 |             (useIncubators) ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous; | 
| 343 |     if (m_incubationMode == incubationMode) | 
| 344 |         return; | 
| 345 |     m_incubationMode = incubationMode; | 
| 346 |     emit incubateDelegatesChanged(); | 
| 347 | } | 
| 348 |  | 
| 349 | bool QDeclarativeGeoMapItemView::incubateDelegates() const | 
| 350 | { | 
| 351 |     return m_incubationMode == QQmlIncubator::Asynchronous; | 
| 352 | } | 
| 353 |  | 
| 354 | QList<QQuickItem *> QDeclarativeGeoMapItemView::mapItems() | 
| 355 | { | 
| 356 |     return m_instantiatedItems; | 
| 357 | } | 
| 358 |  | 
| 359 | QQmlInstanceModel::ReleaseFlags QDeclarativeGeoMapItemView::disposeDelegate(QQuickItem *item) | 
| 360 | { | 
| 361 |     disconnect(sender: item, signal: 0, receiver: this, member: 0); | 
| 362 |     removeDelegateFromMap(o: item); | 
| 363 |     item->setParentItem(nullptr);   // Needed because | 
| 364 |     item->setParent(nullptr);       // m_delegateModel->release(item) does not destroy the item most of the times!! | 
| 365 |     QQmlInstanceModel::ReleaseFlags releaseStatus = m_delegateModel->release(object: item); | 
| 366 |     return releaseStatus; | 
| 367 | } | 
| 368 |  | 
| 369 | void QDeclarativeGeoMapItemView::removeDelegateFromMap(int index, bool transition) | 
| 370 | { | 
| 371 |     if (index >= 0 && index < m_instantiatedItems.size()) { | 
| 372 |         QQuickItem *item = m_instantiatedItems.takeAt(i: index); | 
| 373 |         if (!item) { // not yet incubated | 
| 374 |             // Don't cancel incubation explicitly when model rows are removed, as DelegateModel | 
| 375 |             // apparently takes care of incubating elements when the model remove those indices. | 
| 376 |             // Cancel them explicitly only when a MIV is removed from a map. | 
| 377 |             if (!transition) | 
| 378 |                 m_delegateModel->cancel(index); | 
| 379 |             return; | 
| 380 |         } | 
| 381 |         // item can be either a QDeclarativeGeoMapItemBase or a QDeclarativeGeoMapItemGroup (subclass) | 
| 382 |         if (m_exit && m_map && transition) { | 
| 383 |             transitionItemOut(o: item); | 
| 384 |         } else { | 
| 385 |             if (m_exit && m_map && !transition) { | 
| 386 |                 // check if the exit transition is still running, if so stop it. | 
| 387 |                 // This can happen when explicitly calling Map.removeMapItemView, soon after adding it. | 
| 388 |                 terminateExitTransition(o: item); | 
| 389 |             } | 
| 390 |             QQmlInstanceModel::ReleaseFlags releaseStatus = disposeDelegate(item); | 
| 391 | #ifdef QT_DEBUG | 
| 392 |             if (releaseStatus == QQmlInstanceModel::Referenced) | 
| 393 |                 qWarning() << "item " << index << "("  << item << ") still referenced" ; | 
| 394 | #else | 
| 395 |             Q_UNUSED(releaseStatus); | 
| 396 | #endif | 
| 397 |         } | 
| 398 |     } | 
| 399 | } | 
| 400 |  | 
| 401 | void QDeclarativeGeoMapItemView::removeDelegateFromMap(QQuickItem *o) | 
| 402 | { | 
| 403 |     if (!m_map) | 
| 404 |         return; | 
| 405 |  | 
| 406 |     QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object: o); | 
| 407 |     if (item) { | 
| 408 |         m_map->removeMapItem(item); | 
| 409 |         return; | 
| 410 |     } | 
| 411 |     QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(object: o); | 
| 412 |     if (view) { | 
| 413 |         m_map->removeMapItemView(itemView: view); | 
| 414 |         return; | 
| 415 |     } | 
| 416 |     QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object: o); | 
| 417 |     if (group) { | 
| 418 |         m_map->removeMapItemGroup(itemGroup: group); | 
| 419 |         return; | 
| 420 |     } | 
| 421 | } | 
| 422 |  | 
| 423 | void QDeclarativeGeoMapItemView::transitionItemOut(QQuickItem *o) | 
| 424 | { | 
| 425 |     QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object: o); | 
| 426 |     if (group) { | 
| 427 |         if (!group->m_transitionManager) { | 
| 428 |             QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(group)); | 
| 429 |             group->m_transitionManager.swap(other&: manager); | 
| 430 |             group->m_transitionManager->m_view = this; | 
| 431 |         } | 
| 432 |         connect(sender: group, SIGNAL(removeTransitionFinished()), | 
| 433 |                 receiver: this, SLOT(exitTransitionFinished())); | 
| 434 |  | 
| 435 |         group->m_transitionManager->transitionExit(); | 
| 436 |         return; | 
| 437 |     } | 
| 438 |     QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object: o); | 
| 439 |     if (item) { | 
| 440 |         if (!item->m_transitionManager) { | 
| 441 |             QScopedPointer<QDeclarativeGeoMapItemTransitionManager> manager(new QDeclarativeGeoMapItemTransitionManager(item)); | 
| 442 |             item->m_transitionManager.swap(other&: manager); | 
| 443 |             item->m_transitionManager->m_view = this; | 
| 444 |         } | 
| 445 |         connect(sender: item, SIGNAL(removeTransitionFinished()), | 
| 446 |                 receiver: this, SLOT(exitTransitionFinished()) ); | 
| 447 |  | 
| 448 |         item->m_transitionManager->transitionExit(); | 
| 449 |         return; | 
| 450 |     } | 
| 451 | } | 
| 452 |  | 
| 453 | void QDeclarativeGeoMapItemView::terminateExitTransition(QQuickItem *o) | 
| 454 | { | 
| 455 |     QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object: o); | 
| 456 |     if (group && group->m_transitionManager) { | 
| 457 |         group->m_transitionManager->cancel(); | 
| 458 |         return; | 
| 459 |     } | 
| 460 |     QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object: o); | 
| 461 |     if (item && item->m_transitionManager) { | 
| 462 |         item->m_transitionManager->cancel(); | 
| 463 |         return; | 
| 464 |     } | 
| 465 | } | 
| 466 |  | 
| 467 | void QDeclarativeGeoMapItemView::exitTransitionFinished() | 
| 468 | { | 
| 469 |     QQuickItem *item = qobject_cast<QQuickItem *>(object: sender()); | 
| 470 |     if (!item) | 
| 471 |         return; | 
| 472 |     QQmlInstanceModel::ReleaseFlags releaseStatus = disposeDelegate(item); | 
| 473 | #ifdef QT_DEBUG | 
| 474 |     if (releaseStatus == QQmlInstanceModel::Referenced) | 
| 475 |         qWarning() << "item " <<item<<" still referenced" ; | 
| 476 | #else | 
| 477 |     Q_UNUSED(releaseStatus); | 
| 478 | #endif | 
| 479 | } | 
| 480 |  | 
| 481 | void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item, int index, bool createdItem) | 
| 482 | { | 
| 483 |  | 
| 484 |     if (m_map && item->quickMap() == m_map) // test for *item done in the caller | 
| 485 |         return; | 
| 486 |  | 
| 487 |     if (m_map) { | 
| 488 |         insertInstantiatedItem(index, o: item, createdItem); | 
| 489 |         item->setParentItem(this); | 
| 490 |         m_map->addMapItem(item); | 
| 491 |         if (m_enter) { | 
| 492 |             if (!item->m_transitionManager) { | 
| 493 |                 QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(item)); | 
| 494 |                 item->m_transitionManager.swap(other&: manager); | 
| 495 |             } | 
| 496 |             item->m_transitionManager->m_view = this; | 
| 497 |             item->m_transitionManager->transitionEnter(); | 
| 498 |         } | 
| 499 |     } | 
| 500 | } | 
| 501 |  | 
| 502 | void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QQuickItem *o, bool createdItem) | 
| 503 | { | 
| 504 |     if (createdItem) | 
| 505 |         m_instantiatedItems.replace(i: index, t: o); | 
| 506 |     else | 
| 507 |         m_instantiatedItems.insert(i: index, t: o); | 
| 508 | } | 
| 509 |  | 
| 510 | void QDeclarativeGeoMapItemView::addItemViewToMap(QDeclarativeGeoMapItemView *item, int index, bool createdItem) | 
| 511 | { | 
| 512 |     if (m_map && item->quickMap() == m_map)  // test for *item done in the caller | 
| 513 |         return; | 
| 514 |  | 
| 515 |     if (m_map) { | 
| 516 |         insertInstantiatedItem(index, o: item, createdItem); | 
| 517 |         item->setParentItem(this); | 
| 518 |         m_map->addMapItemView(itemView: item); | 
| 519 |         if (m_enter) { | 
| 520 |             if (!item->m_transitionManager) { | 
| 521 |                 QScopedPointer<QDeclarativeGeoMapItemTransitionManager> manager(new QDeclarativeGeoMapItemTransitionManager(item)); | 
| 522 |                 item->m_transitionManager.swap(other&: manager); | 
| 523 |             } | 
| 524 |             item->m_transitionManager->m_view = this; | 
| 525 |             item->m_transitionManager->transitionEnter(); | 
| 526 |         } | 
| 527 |     } | 
| 528 | } | 
| 529 |  | 
| 530 | void QDeclarativeGeoMapItemView::addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index, bool createdItem) | 
| 531 | { | 
| 532 |     if (m_map && item->quickMap() == m_map) // test for *item done in the caller | 
| 533 |         return; | 
| 534 |  | 
| 535 |     if (m_map) { | 
| 536 |         insertInstantiatedItem(index, o: item, createdItem); | 
| 537 |         item->setParentItem(this); | 
| 538 |         m_map->addMapItemGroup(itemGroup: item); | 
| 539 |         if (m_enter) { | 
| 540 |             if (!item->m_transitionManager) { | 
| 541 |                 QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(item)); | 
| 542 |                 item->m_transitionManager.swap(other&: manager); | 
| 543 |             } | 
| 544 |             item->m_transitionManager->m_view = this; | 
| 545 |             item->m_transitionManager->transitionEnter(); | 
| 546 |         } | 
| 547 |     } | 
| 548 | } | 
| 549 |  | 
| 550 | void QDeclarativeGeoMapItemView::addDelegateToMap(QQuickItem *object, int index, bool createdItem) | 
| 551 | { | 
| 552 |     if (!object) { | 
| 553 |         if (!createdItem) | 
| 554 |             m_instantiatedItems.insert(i: index, t: nullptr); // insert placeholder | 
| 555 |         return; | 
| 556 |     } | 
| 557 |     QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object); | 
| 558 |     if (item) { // else createdItem will be emitted. | 
| 559 |         addItemToMap(item, index, createdItem); | 
| 560 |         return; | 
| 561 |     } | 
| 562 |     QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(object); | 
| 563 |     if (view) { | 
| 564 |         addItemViewToMap(item: view, index, createdItem); | 
| 565 |         return; | 
| 566 |     } | 
| 567 |     QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object); | 
| 568 |     if (group) { | 
| 569 |         addItemGroupToMap(item: group, index, createdItem); | 
| 570 |         return; | 
| 571 |     } | 
| 572 |     qWarning() << "addDelegateToMap called with a " << object->metaObject()->className(); | 
| 573 | } | 
| 574 |  | 
| 575 | QT_END_NAMESPACE | 
| 576 |  | 
| 577 |  | 
| 578 |  |