mapwidget.cpp Example File
mapviewer/mapwidget.cpp
#include "mapwidget.h"
#include <QTimer>
#include <cmath>
QTM_USE_NAMESPACE
#if defined(Q_OS_SYMBIAN) || defined(Q_OS_WINCE_WM) || defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6)
static const bool enableKineticPanning = true;
static const qreal kineticPanningHalflife = 200.0;
static const qreal panSpeedNormal = 0.3;
static const qreal panSpeedFast = 1.0;
static const qreal kineticPanSpeedThreshold = 0.02;
static const int kineticPanningResolution = 75;
static const int holdTimeThreshold = 200;
#else
static const bool enableKineticPanning = true;
static const qreal kineticPanningHalflife = 300.0;
static const qreal panSpeedNormal = 0.3;
static const qreal panSpeedFast = 1.0;
static const qreal kineticPanSpeedThreshold = 0.005;
static const int kineticPanningResolution = 30;
static const int holdTimeThreshold = 100;
#endif
MapWidget::MapWidget(QGeoMappingManager *manager) :
QGraphicsGeoMap(manager),
coordQueryState(false),
panActive(false),
kineticTimer(new QTimer),
lastCircle(0)
{
for (int i = 0; i < 5; ++i) mouseHistory.append(MouseHistoryEntry());
connect(kineticTimer, SIGNAL(timeout()), this, SLOT(kineticTimerEvent()));
kineticTimer->setInterval(kineticPanningResolution);
}
MapWidget::~MapWidget() {}
void MapWidget::setMouseClickCoordQuery(bool state)
{
coordQueryState = state;
}
void MapWidget::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
setFocus();
if (event->button() == Qt::LeftButton) {
if (event->modifiers() & Qt::ControlModifier) {
} else {
if (coordQueryState) {
emit coordQueryResult(screenPositionToCoordinate(event->lastPos()));
return;
}
panActive = true;
kineticTimer->stop();
kineticPanSpeed = QPointF();
lastMoveTime = QTime::currentTime();
}
}
event->accept();
}
void MapWidget::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (event->button() == Qt::LeftButton) {
if (panActive) {
panActive = false;
if (!enableKineticPanning || lastMoveTime.msecsTo(QTime::currentTime()) > holdTimeThreshold) {
return;
}
kineticPanSpeed = QPointF();
int entries_considered = 0;
QTime currentTime = QTime::currentTime();
foreach(MouseHistoryEntry entry, mouseHistory) {
int deltaTime = entry.second.msecsTo(currentTime);
if (deltaTime < holdTimeThreshold) {
kineticPanSpeed += entry.first;
entries_considered++;
}
}
if (entries_considered > 0) kineticPanSpeed /= entries_considered;
lastMoveTime = currentTime;
kineticTimer->start();
panDecellerate = true;
}
}
event->accept();
}
void MapWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
if (event->modifiers() & Qt::ControlModifier) {
if (lastCircle)
lastCircle->setCenter(this->screenPositionToCoordinate(event->pos()));
} else if (panActive) {
QTime currentTime = QTime::currentTime();
int deltaTime = lastMoveTime.msecsTo(currentTime);
lastMoveTime = currentTime;
QPointF delta = event->lastPos() - event->pos();
if (deltaTime > 0) {
kineticPanSpeed = delta / deltaTime;
mouseHistory.push_back(MouseHistoryEntry(kineticPanSpeed, currentTime));
mouseHistory.pop_front();
}
panFloatWrapper(delta);
}
event->accept();
}
void MapWidget::kineticTimerEvent()
{
QTime currentTime = QTime::currentTime();
int deltaTime = lastMoveTime.msecsTo(currentTime);
lastMoveTime = currentTime;
if (panDecellerate)
kineticPanSpeed *= pow(qreal(0.5), qreal(deltaTime / kineticPanningHalflife));
QPointF scaledSpeed = kineticPanSpeed * deltaTime;
if (kineticPanSpeed.manhattanLength() < kineticPanSpeedThreshold) {
kineticTimer->stop();
return;
}
panFloatWrapper(scaledSpeed);
}
void MapWidget::panFloatWrapper(const QPointF& delta)
{
remainingPan += delta;
QPoint move = remainingPan.toPoint();
pan(move.x(), move.y());
remainingPan -= move;
}
void MapWidget::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
setFocus();
pan(event->lastPos().x() - size().width() / 2.0, event->lastPos().y() - size().height() / 2.0);
if (zoomLevel() < maximumZoomLevel())
setZoomLevel(zoomLevel() + 1);
event->accept();
}
void MapWidget::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Minus:
#ifdef Q_OS_SYMBIAN
case Qt::Key_VolumeDown:
#endif
if (zoomLevel() > minimumZoomLevel()) {
setZoomLevel(zoomLevel() - 1);
}
break;
case Qt::Key_Plus:
#ifdef Q_OS_SYMBIAN
case Qt::Key_VolumeUp:
#endif
if (zoomLevel() < maximumZoomLevel()) {
setZoomLevel(zoomLevel() + 1);
}
break;
case Qt::Key_T:
if (mapType() == QGraphicsGeoMap::StreetMap)
setMapType(QGraphicsGeoMap::SatelliteMapDay);
else if (mapType() == QGraphicsGeoMap::SatelliteMapDay)
setMapType(QGraphicsGeoMap::StreetMap);
break;
case Qt::Key_Shift:
if (panDir.manhattanLength() == 0) break;
case Qt::Key_Left:
case Qt::Key_Right:
case Qt::Key_Up:
case Qt::Key_Down:
if (!event->isAutoRepeat()) {
switch (event->key()) {
case Qt::Key_Left:
panDir.setX(-1);
break;
case Qt::Key_Right:
panDir.setX(1);
break;
case Qt::Key_Up:
panDir.setY(-1);
break;
case Qt::Key_Down:
panDir.setY(1);
break;
}
lastMoveTime = QTime::currentTime();
kineticTimer->start();
panDecellerate = false;
applyPan(event->modifiers());
}
break;
}
event->accept();
}
void MapWidget::keyReleaseEvent(QKeyEvent* event)
{
event->accept();
if (event->isAutoRepeat()) return;
switch (event->key()) {
case Qt::Key_Left:
case Qt::Key_Right:
panDir.setX(0);
break;
case Qt::Key_Up:
case Qt::Key_Down:
panDir.setY(0);
break;
case Qt::Key_Shift:
if (panDir.manhattanLength() == 0) return;
break;
default:
return;
}
applyPan(event->modifiers());
}
void MapWidget::applyPan(const Qt::KeyboardModifiers& modifiers)
{
Q_ASSERT(panDir.manhattanLength() <= 2);
if (panDir.manhattanLength() == 0) {
panDecellerate = true;
} else {
qreal panspeed = (modifiers & Qt::ShiftModifier) ? panSpeedFast : panSpeedNormal;
if (panDir.manhattanLength() == 2) {
panspeed *= sqrt(0.5);
}
kineticPanSpeed = QPointF(panDir) * panspeed;
}
}
void MapWidget::wheelEvent(QGraphicsSceneWheelEvent* event)
{
qreal panx = event->pos().x() - size().width() / 2.0;
qreal pany = event->pos().y() - size().height() / 2.0;
pan(panx, pany);
if (event->delta() > 0) {
if (zoomLevel() < maximumZoomLevel()) {
setZoomLevel(zoomLevel() + 1);
}
} else {
if (zoomLevel() > minimumZoomLevel()) {
setZoomLevel(zoomLevel() - 1);
}
}
pan(-panx, -pany);
event->accept();
}
[+] Documentation Feedback