summaryrefslogtreecommitdiff
path: root/src/location/declarativemaps
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-11-27 03:01:30 +0100
committerQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2018-11-27 03:01:30 +0100
commit181f1d8eac0af6e508ed483cbffb28cd2066b961 (patch)
treece9ecf4878562ea35ddd6afd5efa040107d739af /src/location/declarativemaps
parent355a82e3d3aeb470b1d3d257afd2cce24f05b110 (diff)
parentfb23882d5bc697b2dfdd22c27d34c52d889d1200 (diff)
downloadqtlocation-181f1d8eac0af6e508ed483cbffb28cd2066b961.tar.gz
Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: I79898ba40dcce8054a105867ab2a88f1fba72c1f
Diffstat (limited to 'src/location/declarativemaps')
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview.cpp85
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview_p.h12
-rw-r--r--src/location/declarativemaps/qdeclarativepolylinemapitem.cpp137
3 files changed, 184 insertions, 50 deletions
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
index 4461d2e0..41ab3453 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
@@ -135,8 +135,8 @@ void QDeclarativeGeoMapItemView::classBegin()
connect(m_delegateModel, &QQmlInstanceModel::modelUpdated, this, &QDeclarativeGeoMapItemView::modelUpdated);
connect(m_delegateModel, &QQmlInstanceModel::createdItem, this, &QDeclarativeGeoMapItemView::createdItem);
- connect(m_delegateModel, &QQmlInstanceModel::destroyingItem, this, &QDeclarativeGeoMapItemView::destroyingItem);
- connect(m_delegateModel, &QQmlInstanceModel::initItem, this, &QDeclarativeGeoMapItemView::initItem);
+// connect(m_delegateModel, &QQmlInstanceModel::destroyingItem, this, &QDeclarativeGeoMapItemView::destroyingItem);
+// connect(m_delegateModel, &QQmlInstanceModel::initItem, this, &QDeclarativeGeoMapItemView::initItem);
}
void QDeclarativeGeoMapItemView::destroyingItem(QObject */*object*/)
@@ -156,16 +156,21 @@ void QDeclarativeGeoMapItemView::createdItem(int index, QObject */*object*/)
// createdItem is emitted on asynchronous creation. In which case, object has to be invoked again.
// See QQmlDelegateModel::object for further info.
- if (m_incubationMode == QQmlIncubator::Synchronous) {
- qWarning() << "createdItem invoked on Synchronous incubation";
+ // DelegateModel apparently triggers this method in any case, that is:
+ // 1. Synchronous incubation, delegate instantiated on the first object() call (during the object() call!)
+ // 2. Async incubation, delegate not instantiated on the first object() call
+ // 3. Async incubation, delegate present in the cache, and returned on the first object() call.
+ // createdItem also called during the object() call.
+ if (m_creatingObject) {
+ // Falling into case 1. or 3. Returning early to prevent double referencing the delegate instance.
return;
}
QQuickItem *item = qobject_cast<QQuickItem *>(m_delegateModel->object(index, m_incubationMode));
if (item)
- addDelegateToMap(item, index);
+ addDelegateToMap(item, index, true);
else
- qWarning() << "createdItem for " << index << " produced a null item";
+ qWarning() << "QQmlDelegateModel:: object called in createdItem for " << index << " produced a null item";
}
void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
@@ -189,9 +194,12 @@ void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bo
}
}
+ QBoolBlocker createBlocker(m_creatingObject, true);
for (const QQmlChangeSet::Change &c: changeSet.inserts()) {
- for (int idx = c.start(); idx < c.end(); idx++)
- addDelegateToMap(qobject_cast<QQuickItem *>(m_delegateModel->object(idx, m_incubationMode)), idx);
+ for (int idx = c.start(); idx < c.end(); idx++) {
+ QObject *delegateInstance = m_delegateModel->object(idx, m_incubationMode);
+ addDelegateToMap(qobject_cast<QQuickItem *>(delegateInstance), idx);
+ }
}
fitViewport();
@@ -316,8 +324,11 @@ 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++)
- addDelegateToMap(qobject_cast<QQuickItem *>(m_delegateModel->object(i, m_incubationMode)), i);
+ QBoolBlocker createBlocker(m_creatingObject, true);
+ for (int i = 0; i < m_delegateModel->count(); i++) {
+ QObject *delegateInstance = m_delegateModel->object(i, m_incubationMode);
+ addDelegateToMap(qobject_cast<QQuickItem *>(delegateInstance), i);
+ }
fitViewport();
}
@@ -346,15 +357,12 @@ void QDeclarativeGeoMapItemView::removeDelegateFromMap(int index, bool transitio
{
if (index >= 0 && index < m_instantiatedItems.size()) {
QQuickItem *item = m_instantiatedItems.takeAt(index);
- if (!item) {
- if (m_incubatingItems.contains(index)) {
- // cancel request
- m_delegateModel->cancel(index);
- m_incubatingItems.remove(index);
- }
+ if (!item) { // not yet incubated
+ // Don't cancel incubation explicitly, as DelegateModel apparently takes care of incubating elements when the model
+ // remove those indices.
return;
}
- // item can be either a QDeclarativeGeoMapItemBase or a QDeclarativeGeoMapItemGroup
+ // item can be either a QDeclarativeGeoMapItemBase or a QDeclarativeGeoMapItemGroup (subclass)
if (m_exit && m_map && transition) {
transitionItemOut(item);
} else {
@@ -443,16 +451,14 @@ void QDeclarativeGeoMapItemView::exitTransitionFinished()
#endif
}
-void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item, int index)
+void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item, int index, bool createdItem)
{
- if (m_map && item) { // belonging to another map??
- if (item->quickMap() == m_map)
- return;
- }
+ if (m_map && item->quickMap() == m_map) // test for *item done in the caller
+ return;
if (m_map) {
- insertInstantiatedItem(index, item);
+ insertInstantiatedItem(index, item, createdItem);
item->setParentItem(this);
m_map->addMapItem(item);
if (m_enter) {
@@ -466,23 +472,21 @@ void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item,
}
}
-void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QQuickItem *o)
+void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QQuickItem *o, bool createdItem)
{
- if (m_incubatingItems.contains(index)) {
- m_incubatingItems.remove(index);
+ if (createdItem)
m_instantiatedItems.replace(index, o);
- } else {
+ else
m_instantiatedItems.insert(index, o);
- }
}
-void QDeclarativeGeoMapItemView::addItemViewToMap(QDeclarativeGeoMapItemView *item, int index)
+void QDeclarativeGeoMapItemView::addItemViewToMap(QDeclarativeGeoMapItemView *item, int index, bool createdItem)
{
- if (!item || (m_map && item->quickMap() == m_map))
+ if (m_map && item->quickMap() == m_map) // test for *item done in the caller
return;
if (m_map) {
- insertInstantiatedItem(index, item);
+ insertInstantiatedItem(index, item, createdItem);
item->setParentItem(this);
m_map->addMapItemView(item);
if (m_enter) {
@@ -496,13 +500,13 @@ void QDeclarativeGeoMapItemView::addItemViewToMap(QDeclarativeGeoMapItemView *it
}
}
-void QDeclarativeGeoMapItemView::addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index)
+void QDeclarativeGeoMapItemView::addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index, bool createdItem)
{
- if (!item || (m_map && item->quickMap() == m_map))
+ if (m_map && item->quickMap() == m_map) // test for *item done in the caller
return;
if (m_map) {
- insertInstantiatedItem(index, item);
+ insertInstantiatedItem(index, item, createdItem);
item->setParentItem(this);
m_map->addMapItemGroup(item);
if (m_enter) {
@@ -516,28 +520,29 @@ void QDeclarativeGeoMapItemView::addItemGroupToMap(QDeclarativeGeoMapItemGroup *
}
}
-void QDeclarativeGeoMapItemView::addDelegateToMap(QQuickItem *object, int index)
+void QDeclarativeGeoMapItemView::addDelegateToMap(QQuickItem *object, int index, bool createdItem)
{
if (!object) {
- m_incubatingItems.insert(index);
- m_instantiatedItems.insert(index, nullptr);
+ if (!createdItem)
+ m_instantiatedItems.insert(index, nullptr); // insert placeholder
return;
}
QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object);
if (item) { // else createdItem will be emitted.
- addItemToMap(item, index);
+ addItemToMap(item, index, createdItem);
return;
}
QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(object);
if (view) {
- addItemViewToMap(view, index);
+ addItemViewToMap(view, index, createdItem);
return;
}
QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object);
if (group) {
- addItemGroupToMap(group, index);
+ addItemGroupToMap(group, index, createdItem);
return;
}
+ qWarning() << "addDelegateToMap called with a "<< object->metaObject()->className();
}
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
index 58ef2835..43ca685a 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
@@ -131,11 +131,11 @@ private:
void removeDelegateFromMap(QQuickItem *o);
void transitionItemOut(QQuickItem *o);
- void insertInstantiatedItem(int index, QQuickItem *o);
- void addItemToMap(QDeclarativeGeoMapItemBase *item, int index);
- void addItemViewToMap(QDeclarativeGeoMapItemView *item, int index);
- void addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index);
- void addDelegateToMap(QQuickItem *object, int index);
+ void insertInstantiatedItem(int index, QQuickItem *o, bool createdItem);
+ void addItemToMap(QDeclarativeGeoMapItemBase *item, int index, bool createdItem);
+ void addItemViewToMap(QDeclarativeGeoMapItemView *item, int index, bool createdItem);
+ void addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index, bool createdItem);
+ void addDelegateToMap(QQuickItem *object, int index, bool createdItem = false);
bool m_componentCompleted;
QQmlIncubator::IncubationMode m_incubationMode = QQmlIncubator::Asynchronous;
@@ -143,8 +143,8 @@ private:
QVariant m_itemModel;
QDeclarativeGeoMap *m_map;
QList<QQuickItem *> m_instantiatedItems;
- QSet<int> m_incubatingItems;
bool m_fitViewport;
+ bool m_creatingObject = false;
QQmlDelegateModel *m_delegateModel;
QQuickTransition *m_enter = nullptr;
QQuickTransition *m_exit = nullptr;
diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
index 70b4bc21..aeb7b718 100644
--- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
@@ -400,7 +400,7 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap &
// 2)
QList<QList<QDoubleVector2D> > clippedPaths;
- const QList<QDoubleVector2D> &visibleRegion = p.visibleGeometryExpanded();
+ const QList<QDoubleVector2D> &visibleRegion = p.projectableGeometry();
if (visibleRegion.size()) {
clippedPaths = clipLine(wrappedPath, visibleRegion);
@@ -507,6 +507,120 @@ void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map,
pathToScreen(map, clippedPaths, leftBoundWrapped);
}
+// *** SCREEN CLIPPING *** //
+
+enum ClipPointType {
+ InsidePoint = 0x00,
+ LeftPoint = 0x01,
+ RightPoint = 0x02,
+ BottomPoint = 0x04,
+ TopPoint = 0x08
+};
+
+static inline int clipPointType(qreal x, qreal y, const QRectF &rect)
+{
+ int type = InsidePoint;
+ if (x < rect.left())
+ type |= LeftPoint;
+ else if (x > rect.right())
+ type |= RightPoint;
+ if (y < rect.top())
+ type |= TopPoint;
+ else if (y > rect.bottom())
+ type |= BottomPoint;
+ return type;
+}
+
+static void clipSegmentToRect(qreal x0, qreal y0, qreal x1, qreal y1,
+ const QRectF &clipRect,
+ QVector<qreal> &outPoints,
+ QVector<QPainterPath::ElementType> &outTypes)
+{
+ int type0 = clipPointType(x0, y0, clipRect);
+ int type1 = clipPointType(x1, y1, clipRect);
+ bool accept = false;
+
+ while (true) {
+ if (!(type0 | type1)) {
+ accept = true;
+ break;
+ } else if (type0 & type1) {
+ break;
+ } else {
+ qreal x = 0.0;
+ qreal y = 0.0;
+ int outsideType = type0 ? type0 : type1;
+
+ if (outsideType & BottomPoint) {
+ x = x0 + (x1 - x0) * (clipRect.bottom() - y0) / (y1 - y0);
+ y = clipRect.bottom() - 0.1;
+ } else if (outsideType & TopPoint) {
+ x = x0 + (x1 - x0) * (clipRect.top() - y0) / (y1 - y0);
+ y = clipRect.top() + 0.1;
+ } else if (outsideType & RightPoint) {
+ y = y0 + (y1 - y0) * (clipRect.right() - x0) / (x1 - x0);
+ x = clipRect.right() - 0.1;
+ } else if (outsideType & LeftPoint) {
+ y = y0 + (y1 - y0) * (clipRect.left() - x0) / (x1 - x0);
+ x = clipRect.left() + 0.1;
+ }
+
+ if (outsideType == type0) {
+ x0 = x;
+ y0 = y;
+ type0 = clipPointType(x0, y0, clipRect);
+ } else {
+ x1 = x;
+ y1 = y;
+ type1 = clipPointType(x1, y1, clipRect);
+ }
+ }
+ }
+
+ if (accept) {
+ if (outPoints.size() >= 2) {
+ qreal lastX, lastY;
+ lastY = outPoints.at(outPoints.size() - 1);
+ lastX = outPoints.at(outPoints.size() - 2);
+
+ if (!qFuzzyCompare(lastY, y0) || !qFuzzyCompare(lastX, x0)) {
+ outTypes << QPainterPath::MoveToElement;
+ outPoints << x0 << y0;
+ }
+ } else {
+ outTypes << QPainterPath::MoveToElement;
+ outPoints << x0 << y0;
+ }
+
+ outTypes << QPainterPath::LineToElement;
+ outPoints << x1 << y1;
+ }
+}
+
+static void clipPathToRect(const QVector<qreal> &points,
+ const QVector<QPainterPath::ElementType> &types,
+ const QRectF &clipRect,
+ QVector<qreal> &outPoints,
+ QVector<QPainterPath::ElementType> &outTypes)
+{
+ outPoints.clear();
+ outPoints.reserve(points.size());
+ outTypes.clear();
+ outTypes.reserve(types.size());
+
+ qreal lastX = 0;
+ qreal lastY = 0; // or else used uninitialized
+ for (int i = 0; i < types.size(); ++i) {
+ if (i > 0 && types[i] != QPainterPath::MoveToElement) {
+ qreal x = points[i * 2], y = points[i * 2 + 1];
+ clipSegmentToRect(lastX, lastY, x, y, clipRect, outPoints, outTypes);
+ }
+
+ lastX = points[i * 2];
+ lastY = points[i * 2 + 1];
+ }
+}
+
////////////////////////////////////////////////////////////////////////////
/*!
@@ -526,9 +640,24 @@ void QGeoMapPolylineGeometry::updateScreenPoints(const QGeoMap &map,
return;
}
- // The geometry has already been clipped against the visible region projection in wrapped mercator space.
- QVector<qreal> points = srcPoints_;
- QVector<QPainterPath::ElementType> types = srcPointTypes_;
+ // Create the viewport rect in the same coordinate system
+ // as the actual points
+ QRectF viewport(0, 0, map.viewportWidth(), map.viewportHeight());
+ viewport.adjust(-strokeWidth, -strokeWidth, strokeWidth, strokeWidth);
+ viewport.translate(-1 * origin);
+
+ QVector<qreal> points;
+ QVector<QPainterPath::ElementType> types;
+
+ if (clipToViewport_) {
+ // Although the geometry has already been clipped against the visible region in wrapped mercator space.
+ // This is currently still needed to prevent a number of artifacts deriving from QTriangulatingStroker processing
+ // very large lines (that is, polylines that span many pixels in screen space)
+ clipPathToRect(srcPoints_, srcPointTypes_, viewport, points, types);
+ } else {
+ points = srcPoints_;
+ types = srcPointTypes_;
+ }
QVectorPath vp(points.data(), types.size(), types.data());
QTriangulatingStroker ts;