summaryrefslogtreecommitdiff
path: root/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
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 /src/location/declarativemaps/qdeclarativegeomapitemview.cpp
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>
Diffstat (limited to 'src/location/declarativemaps/qdeclarativegeomapitemview.cpp')
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview.cpp226
1 files changed, 184 insertions, 42 deletions
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