summaryrefslogtreecommitdiff
path: root/src/imports/location/qdeclarativepolygonmapitem.cpp
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@digia.com>2011-12-13 10:30:10 +0200
committerQt by Nokia <qt-info@nokia.com>2011-12-13 12:58:25 +0100
commit68e2fc8934756e299b04642682d1d8203e971399 (patch)
treee602d68bf4ddd87421e450be73bc8429108faeb2 /src/imports/location/qdeclarativepolygonmapitem.cpp
parentfc576c395676bb766e4a14f8fb38df7e7498ccbf (diff)
downloadqtlocation-68e2fc8934756e299b04642682d1d8203e971399.tar.gz
Reimplement mapitems
* fixes performance issue on high zoomLevels * fixes "pop" effect when zooming * fixes flickering when zooming circle * remove qquickpainteditem * adds map mapitem graphical representation as geometry node * add basic vertex drawing support * removes updateContent, mapChanged, contentLeftPoint Change-Id: Ic76b24c7e47f83c2a45a680607c46595e5a9a790 Reviewed-by: Michal Klocek <michal.klocek@digia.com> Reviewed-by: Juha Vuolle <juha.vuolle@nokia.com>
Diffstat (limited to 'src/imports/location/qdeclarativepolygonmapitem.cpp')
-rw-r--r--src/imports/location/qdeclarativepolygonmapitem.cpp294
1 files changed, 126 insertions, 168 deletions
diff --git a/src/imports/location/qdeclarativepolygonmapitem.cpp b/src/imports/location/qdeclarativepolygonmapitem.cpp
index 94ada8d4..2591eb22 100644
--- a/src/imports/location/qdeclarativepolygonmapitem.cpp
+++ b/src/imports/location/qdeclarativepolygonmapitem.cpp
@@ -43,10 +43,13 @@
#include <QDeclarativeInfo>
#include <QPainter>
-static QPolygonF createPolygon(const Map& map, const QList<QGeoCoordinate> &path, qreal& w,
- qreal& h)
+struct Vertex
+{
+ QVector2D position;
+};
+
+static void updatePolygon(QPolygonF& points,const Map& map, const QList<QGeoCoordinate> &path, qreal& w, qreal& h)
{
- QPolygonF polygon;
qreal minX, maxX, minY, maxY;
//TODO: dateline handling
@@ -65,297 +68,252 @@ static QPolygonF createPolygon(const Map& map, const QList<QGeoCoordinate> &path
maxX = point.x();
minY = point.y();
maxY = point.y();
- polygon.append(point);
} else {
minX = qMin(point.x(), minX);
maxX = qMax(point.x(), maxX);
minY = qMin(point.y(), minY);
maxY = qMax(point.y(), maxY);
}
-
- polygon.append(point);
+ points.append(point);
}
- polygon.translate(-minX, -minY);
+ points.translate(-minX, -minY);
w = maxX - minX;
h = maxY - minY;
-
- return polygon;
}
QDeclarativePolygonMapItem::QDeclarativePolygonMapItem(QQuickItem *parent) :
QDeclarativeGeoMapItemBase(parent),
- polygonItem_(new PolygonMapPaintedItem(this)),
- initialized_(false)
+ mapPolygonNode_(0),
+ zoomLevel_(0.0)
{
- polygonItem_->setParentItem(this);
+ setFlag(ItemHasContents, true);
}
QDeclarativePolygonMapItem::~QDeclarativePolygonMapItem()
{
}
-void QDeclarativePolygonMapItem::componentComplete()
+void QDeclarativePolygonMapItem::setMap(QDeclarativeGeoMap* quickMap, Map *map)
{
- initialized_ = true;
+ QDeclarativeGeoMapItemBase::setMap(quickMap,map);
+ if (map) QObject::connect(map, SIGNAL(cameraDataChanged(CameraData)), this, SLOT(handleCameraDataChanged(CameraData)));
}
QDeclarativeListProperty<QDeclarativeCoordinate> QDeclarativePolygonMapItem::declarativePath()
{
return QDeclarativeListProperty<QDeclarativeCoordinate>(this, 0, path_append, path_count,
- path_at, path_clear);
+ path_at, path_clear);
}
void QDeclarativePolygonMapItem::path_append(
- QDeclarativeListProperty<QDeclarativeCoordinate> *property, QDeclarativeCoordinate *coordinate)
+ QDeclarativeListProperty<QDeclarativeCoordinate> *property, QDeclarativeCoordinate *coordinate)
{
- QDeclarativePolygonMapItem* item = qobject_cast<QDeclarativePolygonMapItem*>(
- property->object);
- item->path_.append(coordinate);
- QList<QGeoCoordinate> p = item->polygonItem_->path();
- p.append(coordinate->coordinate());
- item->polygonItem_->setPath(p);
- if (item->initialized_)
- emit item->pathChanged();
- item->updateMapItem();
+ QDeclarativePolygonMapItem* item = qobject_cast<QDeclarativePolygonMapItem*>(property->object);
+ item->coordPath_.append(coordinate);
+ item->path_.append(coordinate->coordinate());
+ item->updateMapItem(true);
+ emit item->pathChanged();
}
int QDeclarativePolygonMapItem::path_count(
- QDeclarativeListProperty<QDeclarativeCoordinate> *property)
+ QDeclarativeListProperty<QDeclarativeCoordinate> *property)
{
- return qobject_cast<QDeclarativePolygonMapItem*>(property->object)->path_.count();
+ return qobject_cast<QDeclarativePolygonMapItem*>(property->object)->coordPath_.count();
}
QDeclarativeCoordinate* QDeclarativePolygonMapItem::path_at(
- QDeclarativeListProperty<QDeclarativeCoordinate> *property, int index)
+ QDeclarativeListProperty<QDeclarativeCoordinate> *property, int index)
{
- return qobject_cast<QDeclarativePolygonMapItem*>(property->object)->path_.at(index);
+ return qobject_cast<QDeclarativePolygonMapItem*>(property->object)->coordPath_.at(index);
}
void QDeclarativePolygonMapItem::path_clear(
- QDeclarativeListProperty<QDeclarativeCoordinate> *property)
+ QDeclarativeListProperty<QDeclarativeCoordinate> *property)
{
QDeclarativePolygonMapItem* item = qobject_cast<QDeclarativePolygonMapItem*>(
- property->object);
- qDeleteAll(item->path_);
+ property->object);
+ qDeleteAll(item->coordPath_);
+ item->coordPath_.clear();
item->path_.clear();
- item->polygonItem_->setPath(QList<QGeoCoordinate>());
- if (item->initialized_)
- emit item->pathChanged();
- item->updateMapItem();
+ item->updateMapItem(true);
+ emit item->pathChanged();
}
void QDeclarativePolygonMapItem::addCoordinate(QDeclarativeCoordinate* coordinate)
{
- path_.append(coordinate);
- QList<QGeoCoordinate> path = polygonItem_->path();
- path.append(coordinate->coordinate());
- polygonItem_->setPath(path);
- updateMapItem();
+ coordPath_.append(coordinate);
+ path_.append(coordinate->coordinate());
+ updateMapItem(true);
emit pathChanged();
}
void QDeclarativePolygonMapItem::removeCoordinate(QDeclarativeCoordinate* coordinate)
{
- int index = path_.lastIndexOf(coordinate);
+ int index = coordPath_.lastIndexOf(coordinate);
if (index == -1) {
qmlInfo(this) << tr("Coordinate does not belong to PolygonMapItem.");
return;
}
- QList<QGeoCoordinate> path = polygonItem_->path();
-
- if (path.count() < index + 1) {
+ if (path_.count() < index + 1) {
qmlInfo(this) << tr("Coordinate does not belong to PolygonMapItem.");
return;
}
- path.removeAt(index);
- polygonItem_->setPath(path);
+ coordPath_.removeAt(index);
path_.removeAt(index);
- updateMapItem();
+ updateMapItem(true);
emit pathChanged();
}
-void QDeclarativePolygonMapItem::updateContent()
+QColor QDeclarativePolygonMapItem::color() const
{
- polygonItem_->updateGeometry();
- setWidth(polygonItem_->width());
- setHeight(polygonItem_->height());
+ return color_;
}
-QPointF QDeclarativePolygonMapItem::contentTopLeftPoint()
+void QDeclarativePolygonMapItem::setColor(const QColor &color)
{
- return map_->coordinateToScreenPosition(
- polygonItem_->quickItemCoordinate(), false) - polygonItem_->quickItemAnchorPoint();
-}
+ if (color_ == color)
+ return;
-void QDeclarativePolygonMapItem::mapChanged()
+ color_ = color;
+ updateMapItem(false);
+ emit colorChanged(color_);
+}
+QSGNode* QDeclarativePolygonMapItem::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data)
{
- polygonItem_->setMap(map_);
- if (map_) {
- connect(map_, SIGNAL(cameraDataChanged(CameraData)), this, SLOT(handleCameraDataChanged(CameraData)));
- // initial update
- handleCameraDataChanged(map_->cameraData());
+ Q_UNUSED(data);
+
+ MapPolygonNode *node = static_cast<MapPolygonNode*>(oldNode);
+
+ if (!node) {
+ mapPolygonNode_ = new MapPolygonNode();
+ updateMapItem(true);
}
-}
-void QDeclarativePolygonMapItem::dragStarted()
-{
- qmlInfo(this) << "warning: mouse dragging is not currently supported with polygon.";
+ mapPolygonNode_->update();
+ return mapPolygonNode_;
}
-bool QDeclarativePolygonMapItem::contains(QPointF point)
+void
+QDeclarativePolygonMapItem::updateMapItem(bool dirtyGeometry)
{
- return polygonItem_->contains(point);
+ if (!map() || path_.count() == 0 || !mapPolygonNode_)
+ return;
+
+ mapPolygonNode_->setBrushColor(color_);
+
+ if (dirtyGeometry)
+ mapPolygonNode_->setGeometry(*map(), path_);
+
+ const QSizeF& size = mapPolygonNode_->size();
+
+ setWidth(size.width());
+ setHeight(size.height());
+
+ setPositionOnMap(path_.at(0), mapPolygonNode_->geometry().at(0));
+ update();
}
void QDeclarativePolygonMapItem::handleCameraDataChanged(const CameraData& cameraData)
{
- polygonItem_->setZoomLevel(cameraData.zoomFactor());
- updateMapItem();
+ if (cameraData.zoomFactor() != zoomLevel_) {
+ zoomLevel_ = cameraData.zoomFactor();
+ updateMapItem(true);
+ } else {
+ updateMapItem(false);
+ }
}
-QColor QDeclarativePolygonMapItem::color() const
+void QDeclarativePolygonMapItem::dragStarted()
{
- return color_;
+ qmlInfo(this) << "warning: mouse dragging is not currently supported with polygon.";
}
-void QDeclarativePolygonMapItem::setColor(const QColor &color)
+bool QDeclarativePolygonMapItem::contains(QPointF point)
{
- if (color_ == color)
- return;
-
- color_ = color;
- polygonItem_->setBrush(color);
- emit colorChanged(color_);
+ return mapPolygonNode_->contains(point);
}
//////////////////////////////////////////////////////////////////////
-PolygonMapPaintedItem::PolygonMapPaintedItem(QQuickItem *parent) :
- QQuickPaintedItem(parent), map_(0), zoomLevel_(-1), initialized_(false)
+MapPolygonNode::MapPolygonNode() :
+ fillColor_(Qt::black),
+ borderColor_(Qt::black),
+ geometry_(QSGGeometry::defaultAttributes_Point2D(), 0)
{
- setAntialiasing(true);
- connect(this, SIGNAL(xChanged()), this, SLOT(update()));
- connect(this, SIGNAL(yChanged()), this, SLOT(update()));
+ geometry_.setDrawingMode(GL_POLYGON);
+ QSGGeometryNode::setMaterial(&fill_material_);
+ QSGGeometryNode::setGeometry(&geometry_);
}
-PolygonMapPaintedItem::~PolygonMapPaintedItem()
+MapPolygonNode::~MapPolygonNode()
{
}
-void PolygonMapPaintedItem::setMap(Map* map)
+void MapPolygonNode::update()
{
- map_ = map;
-}
+ //TODO: optimize , perform calculation only if polygon has changed
+ if (polygon_.size()==0) return;
-Map* PolygonMapPaintedItem::map()
-{
- return map_;
-}
+ QSGGeometry *fill = QSGGeometryNode::geometry();
-void PolygonMapPaintedItem::setZoomLevel(qreal zoomLevel)
-{
- if (zoomLevel_ == zoomLevel)
- return;
+ Q_ASSERT(fill->sizeOfVertex() == sizeof(Vertex));
- zoomLevel_ = zoomLevel;
- dirtyGeometry_ = true;
-}
+ int fillVertexCount = 0;
+ //note this will not allocate new buffer if the size has not changed
+ fill->allocate(polygon_.size());
-qreal PolygonMapPaintedItem::zoomLevel() const
-{
- return zoomLevel_;
-}
+ Vertex *vertices = (Vertex *)fill->vertexData();
-bool PolygonMapPaintedItem::contains(QPointF point)
-{
- return polygon_.containsPoint(point, Qt::OddEvenFill);
-}
+ for (int i = 0; i < polygon_.size(); ++i) {
+ vertices[fillVertexCount++].position = QVector2D(polygon_.at(i));
+ }
-void PolygonMapPaintedItem::setPath(const QList<QGeoCoordinate>& path)
-{
- coordPath_ = path;
- dirtyGeometry_ = true;
-}
+ Q_ASSERT(fillVertexCount == fill->vertexCount());
-QList<QGeoCoordinate> PolygonMapPaintedItem::path() const
-{
- return coordPath_;
-}
+ markDirty(DirtyGeometry);
-QGeoCoordinate PolygonMapPaintedItem::quickItemCoordinate() const
-{
- return quickItemCoordinate_;
-}
+ if (fillColor_ != fill_material_.color()) {
+ fill_material_.setColor(fillColor_);
+ setMaterial(&fill_material_);
+ }
-QPointF PolygonMapPaintedItem::quickItemAnchorPoint() const
-{
- return quickItemAnchorPoint_;
+ //TODO: implement me : borders , gradient
}
-void PolygonMapPaintedItem::setBrush(const QBrush &brush)
+void MapPolygonNode::setBrushColor(const QColor &color)
{
- brush_ = brush;
+ fillColor_= color;
}
-QBrush PolygonMapPaintedItem::brush() const
+QColor MapPolygonNode::brushColor() const
{
- return brush_;
+ return fillColor_;
}
-void PolygonMapPaintedItem::setPen(const QPen &pen)
+void MapPolygonNode::setPenColor(const QColor &color)
{
- pen_ = pen;
+ borderColor_ = color;
}
-QPen PolygonMapPaintedItem::pen() const
+QColor MapPolygonNode::penColor() const
{
- return pen_;
+ return borderColor_;
}
-void PolygonMapPaintedItem::paint(QPainter *painter)
+bool MapPolygonNode::contains(QPointF point)
{
- if (!initialized_)
- return;
- painter->setPen(pen_);
- painter->setBrush(brush_);
- painter->drawConvexPolygon(polygon_);
+ return polygon_.containsPoint(point, Qt::OddEvenFill);
}
-void PolygonMapPaintedItem::updateGeometry()
+void MapPolygonNode::setGeometry(const Map& map, const QList<QGeoCoordinate> &path)
{
- if (!dirtyGeometry_)
- return;
- initialized_ = false;
-
- if (!map_)
- return;
-
- if (coordPath_.size() == 0)
- return;
-
- if (zoomLevel_ == -1)
- return;
-
- QPointF point = map_->coordinateToScreenPosition(coordPath_.at(0), false);
-
- qreal w = 0;
qreal h = 0;
-
- //TODO: optimize essential part
- polygon_ = createPolygon(*map_, coordPath_, w, h);
-
- setWidth(w);
- setHeight(h);
- setContentsSize(QSize(w, h));
-
- quickItemCoordinate_ = coordPath_.at(0);
- quickItemAnchorPoint_ = polygon_.first();
- initialized_ = true;
-
- dirtyGeometry_ = false;
- update(); // qquickpainteditem
+ qreal w = 0;
+ polygon_.clear();
+ updatePolygon(polygon_, map, path, w, h);
+ size_ = QSizeF(w, h);
}