diff options
author | juhvu <qt-info@nokia.com> | 2011-09-21 16:17:30 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-09-26 03:28:10 +0200 |
commit | cf89ceb0f5ef41866e23a35ebf8abfa3584f9626 (patch) | |
tree | 3bd9900e9261547f4af7731f333072dd6e41aa1a /src/imports/location/qdeclarativegeomapmousearea.cpp | |
parent | 33a7f66bf3c1fca16fab6303cbc104d5141e7321 (diff) | |
download | qtlocation-cf89ceb0f5ef41866e23a35ebf8abfa3584f9626.tar.gz |
Added MapMouseArea support (still needs a commit to declarative).
Change-Id: I04cdb018b7d8702f281e25a8cbd53e4af4f3cfca
Reviewed-on: http://codereview.qt-project.org/5284
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Aaron McCarthy <aaron.mccarthy@nokia.com>
Diffstat (limited to 'src/imports/location/qdeclarativegeomapmousearea.cpp')
-rw-r--r-- | src/imports/location/qdeclarativegeomapmousearea.cpp | 442 |
1 files changed, 271 insertions, 171 deletions
diff --git a/src/imports/location/qdeclarativegeomapmousearea.cpp b/src/imports/location/qdeclarativegeomapmousearea.cpp index c307844d..1c968c3a 100644 --- a/src/imports/location/qdeclarativegeomapmousearea.cpp +++ b/src/imports/location/qdeclarativegeomapmousearea.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -40,12 +40,22 @@ ****************************************************************************/ #include "qdeclarativegeomapmousearea_p.h" +#include <QtDeclarative/qdeclarativeinfo.h> +#include <QtDeclarative/QSGCanvas> + +#ifndef QSGMOUSEAREA_AVAILABLE + +#else + +#include <qsgevents_p_p.h> +#include "qsgmousearea_p.h" + #include <QDebug> QT_BEGIN_NAMESPACE /*! - \qmlclass MapMouseArea QDeclarativeGeoMapMouseArea + \qmlclass MapMouseArea \brief The MapMouseArea item enables simple mouse handling. @@ -69,108 +79,222 @@ QT_BEGIN_NAMESPACE used involved handling mouse presses and clicks: onClicked, onDoubleClicked, onPressed and onReleased. - MapMouseArea items only report mouse clicks and not changes to the - position of the mouse cursor. + MapMouseArea does not intend to be generic mouse area that supports every + possible usage, rather it focuses on catering for the major use-cases. Hence there + are some implementation limitations: + \list + \i The mouse event is guaranteed only to be valid for the + duration of the signal handler (e.g. onPositionChanged, onClicked). Consequently + the mouse event itself should not be stored. The main reason for this is to + optimize memory usage; we do not want to allocate heap memory every time the mouse + moves. + \i Nested mouse areas are not supported (MapMouseArea { MapMouseArea {} } + \i Using normal QML MouseArea in MapItem or Map has no effect + \i If mouse areas of map overlap, the declaration order is significant (not e.g. 'z' value) + \i Only one MapMouseArea per MapItem is supported, and it always fills the whole MapItem + \endlist \sa MapMouseEvent */ QDeclarativeGeoMapMouseArea::QDeclarativeGeoMapMouseArea(QSGItem *parent) : QSGItem(parent), - enabled_(true), - hoverEnabled_(false) {} + mouseEvent_(0), + map_(0), + mouseArea_(0), + componentCompleted_(false) +{ + mouseEvent_ = new QDeclarativeGeoMapMouseEvent(this); + mouseArea_ = new QSGMouseArea(this); + // prevents mouseArea automagically intercepting mouse events: + mouseArea_->setVisible(false); + setVisible(false); + setAcceptedMouseButtons(Qt::LeftButton | Qt::MidButton | Qt::RightButton); + setAcceptHoverEvents(false); + // connect to signals so we can intercept them and convert to map + // mouse events (and e.g. to amend with geo coordinate). + // the signals that were present on mobility + connect(mouseArea_, SIGNAL(pressed(QSGMouseEvent*)), this, SLOT(pressedHandler(QSGMouseEvent*))); + connect(mouseArea_, SIGNAL(clicked(QSGMouseEvent*)), this, SLOT(clickedHandler(QSGMouseEvent*))); + connect(mouseArea_, SIGNAL(doubleClicked(QSGMouseEvent*)), this, SLOT(doubleClickedHandler(QSGMouseEvent*))); + connect(mouseArea_, SIGNAL(released(QSGMouseEvent*)), this, SLOT(releasedHandler(QSGMouseEvent*))); + connect(mouseArea_, SIGNAL(pressedChanged()), this, SLOT(pressedChangedHandler())); + connect(mouseArea_, SIGNAL(enabledChanged()), this, SLOT(enabledChangedHandler())); + connect(mouseArea_, SIGNAL(acceptedButtonsChanged()), this, SLOT(acceptedButtonsChangedHandler())); + //connect(mouseArea_, SIGNAL(hoverEnabledChanged()), this, SLOT(hoverEnabledChangedHandler())); + // new signals from qt5 -> + connect(mouseArea_, SIGNAL(hoveredChanged()), this, SLOT(hoveredChangedHandler())); + connect(mouseArea_, SIGNAL(positionChanged(QSGMouseEvent*)), this, SLOT(positionChangedHandler(QSGMouseEvent*))); + connect(mouseArea_, SIGNAL(entered()), this, SLOT(enteredHandler())); + connect(mouseArea_, SIGNAL(exited()), this, SLOT(exitedHandler())); + connect(mouseArea_, SIGNAL(pressAndHold(QSGMouseEvent*)), this, SLOT(pressAndHoldHandler(QSGMouseEvent*))); +} QDeclarativeGeoMapMouseArea::~QDeclarativeGeoMapMouseArea() { + delete mouseEvent_; + delete mouseArea_; } -void QDeclarativeGeoMapMouseArea::setMap(QDeclarative3DGraphicsGeoMap *map) +void QDeclarativeGeoMapMouseArea::componentComplete() { - map_ = map; + mouseArea_->setWidth(this->width()); + mouseArea_->setHeight(this->height()); + mouseArea_->setX(this->x()); + mouseArea_->setY(this->y()); + componentCompleted_ = true; + QSGItem::componentComplete(); } -QDeclarative3DGraphicsGeoMap* QDeclarativeGeoMapMouseArea::map() const +void QDeclarativeGeoMapMouseArea::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { - return map_; + if (!componentCompleted_) + return; + mouseArea_->setWidth(this->width()); + mouseArea_->setHeight(this->height()); + mouseArea_->setX(this->x()); + mouseArea_->setY(this->y()); + QSGItem::geometryChanged(newGeometry, oldGeometry); } -/*! - \qmlproperty qreal MapMouseArea::mouseX - \qmlproperty qreal MapMouseArea::mouseY - - These properties hold the screen coordinates of the mouse cursor. +void QDeclarativeGeoMapMouseArea::hoveredChangedHandler() +{ + emit hoveredChanged(mouseArea_->hovered()); +} - These properties will only be valid while a button is pressed, and will - remain valid as long as the button is held down even if the mouse is moved - outside the area. +void QDeclarativeGeoMapMouseArea::pressAndHoldHandler(QSGMouseEvent* event) +{ + mapMouseEvent(event); + emit pressAndHold(mouseEvent_); +} - The screen coordinates are relative to the MouseArea. +/* hovering not supported at the moment +void QDeclarativeGeoMapMouseArea::hoverEnabledChangedHandler() +{ + emit hoverEnabledChanged(mouseArea_->hoverEnabled()); +} */ -qreal QDeclarativeGeoMapMouseArea::mouseX() const +void QDeclarativeGeoMapMouseArea::acceptedButtonsChangedHandler() { - return mouseX_; + emit acceptedButtonsChanged(mouseArea_->acceptedButtons()); } -qreal QDeclarativeGeoMapMouseArea::mouseY() const +void QDeclarativeGeoMapMouseArea::enabledChangedHandler() { - return mouseY_; + emit enabledChanged(mouseArea_->isEnabled()); } -bool QDeclarativeGeoMapMouseArea::hovered() const +void QDeclarativeGeoMapMouseArea::pressedHandler(QSGMouseEvent* event) { - return hovered_; + mapMouseEvent(event); + emit pressed(mouseEvent_); } -void QDeclarativeGeoMapMouseArea::setHovered(bool hovered) +void QDeclarativeGeoMapMouseArea::pressedChangedHandler() { - if (hovered_ == hovered) - return; + emit pressedChanged(mouseArea_->pressed()); +} + +void QDeclarativeGeoMapMouseArea::enteredHandler() +{ + emit entered(); +} + +void QDeclarativeGeoMapMouseArea::exitedHandler() +{ + emit exited(); +} + +void QDeclarativeGeoMapMouseArea::positionChangedHandler(QSGMouseEvent* event) +{ + mapMouseEvent(event); + emit positionChanged(mouseEvent_); +} + +void QDeclarativeGeoMapMouseArea::mapMouseEvent(QSGMouseEvent* event) +{ + // we could probably access these directly, + // wouldn't worsen the private header dependency much + mouseEvent_->setAccepted(event->property("accepted").toBool()); + mouseEvent_->setButton(event->property("button").toInt()); + mouseEvent_->setButtons(event->property("buttons").toInt()); + mouseEvent_->setModifiers(event->property("modifiers").toInt()); + mouseEvent_->setWasHeld(event->property("wasHeld").toBool()); + mouseEvent_->setX(event->property("x").toInt()); + mouseEvent_->setY(event->property("y").toInt()); + if (map_) + mouseEvent_->setCoordinate( + map_->map()->screenPositionToCoordinate(QPointF(mouseEvent_->x(), mouseEvent_->y()))); +} + +void QDeclarativeGeoMapMouseArea::releasedHandler(QSGMouseEvent* event) +{ + mapMouseEvent(event); + emit released(mouseEvent_); +} - hovered_ = hovered; +void QDeclarativeGeoMapMouseArea::clickedHandler(QSGMouseEvent* event) +{ + mapMouseEvent(event); + emit clicked(mouseEvent_); +} - emit hoveredChanged(hovered_); +void QDeclarativeGeoMapMouseArea::doubleClickedHandler(QSGMouseEvent* event) +{ + mapMouseEvent(event); + emit doubleClicked(mouseEvent_); +} - if (hovered_) - emit entered(); - else - emit exited(); +void QDeclarativeGeoMapMouseArea::setMap(QDeclarative3DGraphicsGeoMap *map) +{ + Q_ASSERT(map); + map_ = map; } /*! - \qmlproperty bool MapMouseArea::pressed - This property holds whether the mouse area is currently pressed. + \qmlproperty real MapMouseArea::mouseX + \qmlproperty real MapMouseArea::mouseY + + These properties hold the screen coordinates of the mouse cursor. + + These properties will only be valid while a button is pressed, and will remain + valid as long as the button is held down even if the mouse is moved outside the area. + + The screen coordinates are relative to the MapMouseArea. */ -bool QDeclarativeGeoMapMouseArea::pressed() const +qreal QDeclarativeGeoMapMouseArea::mouseX() const { - return pressed_; + return mouseArea_->mouseX(); } -bool QDeclarativeGeoMapMouseArea::setPressed(bool pressed, QDeclarativeGeoMapMouseEvent *event) +qreal QDeclarativeGeoMapMouseArea::mouseY() const { - if (pressed_ == pressed) - return false; - - bool isClick = pressed_ && !pressed;// && hovered_; + return mouseArea_->mouseY(); +} - pressed_ = pressed; +/*! + \qmlproperty bool MapMouseArea::containsMouse + This property holds whether the mouse is currently inside the mouse area. - if (pressed_) { - if (!doubleClick_) - emit QDeclarativeGeoMapMouseArea::pressed(event); - } else { - emit released(event); - // TODO set saved position in event? - if (isClick && !longPress_ && !doubleClick_) { - emit clicked(event); + \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change. + In addition, containsMouse will only be valid when the mouse is pressed. +*/ - } - } +bool QDeclarativeGeoMapMouseArea::hovered() const +{ + return mouseArea_->hovered(); +} - emit pressedChanged(pressed_); +/*! + \qmlproperty bool MapMouseArea::pressed + This property holds whether the mouse area is currently pressed. +*/ - return event->accepted(); +bool QDeclarativeGeoMapMouseArea::pressed() const +{ + return mouseArea_->pressed(); } /*! @@ -182,24 +306,19 @@ bool QDeclarativeGeoMapMouseArea::setPressed(bool pressed, QDeclarativeGeoMapMou bool QDeclarativeGeoMapMouseArea::isEnabled() const { - return enabled_; + return mouseArea_->isEnabled(); } void QDeclarativeGeoMapMouseArea::setEnabled(bool enabled) { - if (enabled_ == enabled) - return; - - enabled_ = enabled; - - emit enabledChanged(enabled_); + mouseArea_->setEnabled(enabled); } /*! - \qmlproperty MouseButton MapMouseArea::pressedButton - This property holds the mouse button currently pressed. + \qmlproperty MouseButton MapMouseArea::pressedButtons + This property holds the mouse buttons currently pressed. - It is one of: + It contains a bitwise combination of: \list \o Qt.LeftButton \o Qt.RightButton @@ -209,12 +328,11 @@ void QDeclarativeGeoMapMouseArea::setEnabled(bool enabled) \sa acceptedButtons */ -Qt::MouseButton QDeclarativeGeoMapMouseArea::pressedButton() const +Qt::MouseButtons QDeclarativeGeoMapMouseArea::pressedButtons() const { - return pressedButton_; + return static_cast<Qt::MouseButtons>(mouseEvent_->button()); } - /*! \qmlproperty Qt::MouseButtons MapMouseArea::acceptedButtons This property holds the mouse buttons that the mouse area reacts to. @@ -238,129 +356,65 @@ Qt::MouseButton QDeclarativeGeoMapMouseArea::pressedButton() const void QDeclarativeGeoMapMouseArea::setAcceptedButtons(Qt::MouseButtons acceptedButtons) { - if (acceptedButtons_ == acceptedButtons) - return; - - acceptedButtons_ = acceptedButtons; - - emit acceptedButtonsChanged(acceptedButtons_); + mouseArea_->setAcceptedButtons(acceptedButtons); + setAcceptedMouseButtons(acceptedButtons); } Qt::MouseButtons QDeclarativeGeoMapMouseArea::acceptedButtons() const { - return acceptedButtons_; -} - -bool QDeclarativeGeoMapMouseArea::hoverEnabled() const -{ - return hoverEnabled_; + return mouseArea_->acceptedButtons(); } -void QDeclarativeGeoMapMouseArea::setHoverEnabled(bool hoverEnabled) -{ - if (hoverEnabled == hoverEnabled_) - return; +/* hover is currently not supported + \qmlproperty bool MapMouseArea::hoverEnabled + This property holds whether hover events are handled. - hoverEnabled_ = hoverEnabled; - //setAcceptsHoverEvents(hoverEnabled_); - setAcceptHoverEvents(hoverEnabled_); - setAcceptedMouseButtons(Qt::LeftButton); - emit hoverEnabledChanged(hoverEnabled_); - // TODO update hovered property -} + By default, mouse events are only handled in response to a button event, or when a button is + pressed. Hover enables handling of all mouse events even when no mouse button is + pressed. + This property affects the \l containsMouse property and the \l onEntered, \l onExited and + \l onPositionChanged signals. - - - - -void QDeclarativeGeoMapMouseArea::doubleClickEvent(QDeclarativeGeoMapMouseEvent *event) +bool QDeclarativeGeoMapMouseArea::hoverEnabled() const { - if (!enabled_) { - //TODO QSGItem::mouseDoubleClickEvent(convert event to regular event here) - return; - } - // TODO check this properly - bool doubleClickConnected = true; - - if (doubleClickConnected) - doubleClick_ = true; - // TODO save event - event->setAccepted(doubleClickConnected); - emit doubleClicked(event); - // TODO QSGItem::mouseDoubleClickEvent(convert event to regular event here) - - map_->setActiveMouseArea(0); + return mouseArea_->hoverEnabled(); } -void QDeclarativeGeoMapMouseArea::pressEvent(QDeclarativeGeoMapMouseEvent *event) +void QDeclarativeGeoMapMouseArea::setHoverEnabled(bool hoverEnabled) { - if (!enabled_) { - //TODO QSGItem::mousePressEvent(convert event to regular event here) - return; - } - - event->setAccepted(true); - - longPress_ = false; - // TODO save event - mouseX_ = event->x(); - mouseY_ = event->y(); - pressedButton_ = Qt::MouseButton(event->button()); - modifiers_ = Qt::KeyboardModifiers(event->modifiers()); - - //setHovered(true); - // TODO setup long press timer - event->setAccepted(setPressed(true, event)); - - if (event->accepted()) - map_->setActiveMouseArea(this); + mouseArea_->setHoverEnabled(hoverEnabled); } -void QDeclarativeGeoMapMouseArea::releaseEvent(QDeclarativeGeoMapMouseEvent *event) +bool QDeclarativeGeoMapMouseArea::hoverEvent(QHoverEvent *event) { - if (!enabled_) { - //TODO QSGItem::mouseReleaseEvent(convert event to regular event here) - return; + if (!map_ || !map_->canvas()) { + qmlInfo(this) << "Warning: no qsgcanvas available, cannot dispatch the mouse event"; + return false; } - - // save event - setPressed(false, event); - pressedButton_ = Qt::NoButton; - modifiers_ = Qt::NoModifier; - doubleClick_ = false; -} - -void QDeclarativeGeoMapMouseArea::enterEvent() -{ - if (!enabled_ || !hoverEnabled()) - return; - - setHovered(true); - - emit entered(); -} - -void QDeclarativeGeoMapMouseArea::exitEvent() -{ - if (!enabled_ || !hoverEnabled()) - return; - - setHovered(false); - - emit exited(); + // we need to filter hover events to mimic regular MouseArea's behavior + if (!mouseArea_->hoverEnabled()) { + return false; + } + map_->canvas()->sendEvent(mouseArea_, event); + return true; } +*/ -void QDeclarativeGeoMapMouseArea::moveEvent(QDeclarativeGeoMapMouseEvent *event) +bool QDeclarativeGeoMapMouseArea::mouseEvent(QMouseEvent *event) { - if (!enabled_) - return; - - event->setButton(pressedButton_); - event->setModifiers(modifiers_); - - emit positionChanged(event); + if (!map_ || !map_->canvas()) { + qmlInfo(this) << "Warning: no qsgcanvas available, cannot dispatch the mouse event"; + return false; + } + if (!mouseArea_->isEnabled()) { + QLOC_TRACE2("mouse area not enabled.", objectName()); + event->ignore(); + return false; + } + map_->canvas()->sendEvent(mouseArea_, event); + return event->isAccepted(); // hmm.. } /*! @@ -420,6 +474,52 @@ void QDeclarativeGeoMapMouseArea::moveEvent(QDeclarativeGeoMapMouseEvent *event) The accepted property defaults to true. */ +/*! + \qmlsignal MapMouseArea::onEntered() + + This handler is called when the mouse enters the mouse area. + + The onEntered handler is only called while a button is + pressed. + + \sa onExited() +*/ + +/*! + \qmlsignal MapMouseArea::onPositionChanged(MapMouseEvent mouse) + + This handler is called when the mouse position changes. + + The \l {MapMouseEvent}{mouse} parameter provides information about the mouse, including the x and y + position, and any buttons currently pressed. + + The \e accepted property of the MapMouseEvent parameter is ignored in this handler. + + The onPositionChanged handler is only called while a button is pressed. +*/ + +/*! + \qmlsignal MapMouseArea::onPressAndHold(MapMouseEvent mouse) + + This handler is called when there is a long press (currently 800ms). + The \l {MapMouseEvent}{mouse} parameter provides information about the press, including the x and y + position of the press, and which button is pressed. + + The \e accepted property of the MapMouseEvent parameter is ignored in this handler. +*/ + +/*! + \qmlsignal MapMouseArea::onExited() + + This handler is called when the mouse exits the mouse area. + + The onExited handler is only called while a button is pressed. + + \sa onEntered() +*/ + +#endif // QSGMOUSEAREA_AVAILABLE + #include "moc_qdeclarativegeomapmousearea_p.cpp" QT_END_NAMESPACE |