Add containsPress property to MouseArea

It is very common to use pressed and containsMouse properties
together to highlight a pressed item, e.g.

    property bool highlighted: pressed && containsMouse

The containsPress property allows simplification and optimization of
user code.

[ChangeLog][QtQuick] Add containsPress property to MouseArea

Task-number: QTBUG-40130
Change-Id: Ie286d431154eb37a99e57e4cf881d68d7cbbe31d
Reviewed-by: Martin Jones <martin.jones@jollamobile.com>
This commit is contained in:
Martin Jones 2014-07-11 14:10:49 +10:00
parent 427bee6cb6
commit 112efda64b
7 changed files with 123 additions and 4 deletions

View File

@ -40,7 +40,9 @@
\section1 MouseArea Behavior \section1 MouseArea Behavior
When you click inside the red square, the \l Text type will list several When you click inside the red square, the \l Text type will list several
properties of that click which are available to QML. properties of that click which are available to QML. The opacity of the
red square will be reduced while the mouse is pressed and remains inside
the MouseArea.
Signals are emitted by the MouseArea when clicks or other discrete Signals are emitted by the MouseArea when clicks or other discrete
operations occur within it. operations occur within it.

View File

@ -38,7 +38,7 @@
** **
****************************************************************************/ ****************************************************************************/
import QtQuick 2.0 import QtQuick 2.4
Rectangle { Rectangle {
id: box id: box
@ -49,10 +49,12 @@ Rectangle {
width: 120; height: 120 width: 120; height: 120
anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10 anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10
color: "red" color: "red"
opacity: redSquareMouseArea.containsPress ? 0.6 : 1.0
Text { text: "Click"; font.pixelSize: 16; anchors.centerIn: parent } Text { text: "Click"; font.pixelSize: 16; anchors.centerIn: parent }
MouseArea { MouseArea {
id: redSquareMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
property string buttonID property string buttonID

View File

@ -270,6 +270,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickImage, 1>(uri, 2, 3,"Image"); qmlRegisterType<QQuickImage, 1>(uri, 2, 3,"Image");
qmlRegisterType<QQuickItem, 2>(uri, 2, 4, "Item"); qmlRegisterType<QQuickItem, 2>(uri, 2, 4, "Item");
qmlRegisterType<QQuickMouseArea, 1>(uri, 2, 4, "MouseArea");
} }
static void initResources() static void initResources()

View File

@ -860,6 +860,7 @@ void QQuickMouseArea::ungrabMouse()
emit canceled(); emit canceled();
emit pressedChanged(); emit pressedChanged();
emit containsPressChanged();
emit pressedButtonsChanged(); emit pressedButtonsChanged();
if (d->hovered && !isUnderMouse()) { if (d->hovered && !isUnderMouse()) {
@ -917,6 +918,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
ungrabMouse(); ungrabMouse();
emit canceled(); emit canceled();
emit pressedChanged(); emit pressedChanged();
emit containsPressChanged();
if (d->hovered) { if (d->hovered) {
d->hovered = false; d->hovered = false;
emit hoveredChanged(); emit hoveredChanged();
@ -1062,6 +1064,24 @@ bool QQuickMouseArea::pressed() const
return d->pressed; return d->pressed;
} }
/*!
\qmlproperty bool QtQuick::MouseArea::containsPress
\since 5.4
This is a convenience property equivalent to \c {pressed && containsMouse},
i.e. it holds whether any of the \l acceptedButtons are currently pressed
and the mouse is currently within the MouseArea.
This property is particularly useful for highlighting an item while the mouse
is pressed within its bounds.
\sa pressed, containsMouse
*/
bool QQuickMouseArea::containsPress() const
{
Q_D(const QQuickMouseArea);
return d->pressed && d->hovered;
}
void QQuickMouseArea::setHovered(bool h) void QQuickMouseArea::setHovered(bool h)
{ {
Q_D(QQuickMouseArea); Q_D(QQuickMouseArea);
@ -1069,6 +1089,8 @@ void QQuickMouseArea::setHovered(bool h)
d->hovered = h; d->hovered = h;
emit hoveredChanged(); emit hoveredChanged();
d->hovered ? emit entered() : emit exited(); d->hovered ? emit entered() : emit exited();
if (d->pressed)
emit containsPressChanged();
} }
} }
@ -1128,15 +1150,19 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p)
emit mouseXChanged(&me); emit mouseXChanged(&me);
me.setPosition(d->lastPos); me.setPosition(d->lastPos);
emit mouseYChanged(&me); emit mouseYChanged(&me);
if (!oldPressed) if (!oldPressed) {
emit pressedChanged(); emit pressedChanged();
emit containsPressChanged();
}
emit pressedButtonsChanged(); emit pressedButtonsChanged();
} else { } else {
d->pressed &= ~button; d->pressed &= ~button;
emit released(&me); emit released(&me);
me.setPosition(d->lastPos); me.setPosition(d->lastPos);
if (!d->pressed) if (!d->pressed) {
emit pressedChanged(); emit pressedChanged();
emit containsPressChanged();
}
emit pressedButtonsChanged(); emit pressedButtonsChanged();
if (isclick && !d->longPress && !d->doubleClick){ if (isclick && !d->longPress && !d->doubleClick){
me.setAccepted(d->isClickConnected()); me.setAccepted(d->isClickConnected());

View File

@ -73,6 +73,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseArea : public QQuickItem
#ifndef QT_NO_CURSOR #ifndef QT_NO_CURSOR
Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged) Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET unsetCursor NOTIFY cursorShapeChanged)
#endif #endif
Q_PROPERTY(bool containsPress READ containsPress NOTIFY containsPressChanged REVISION 1)
public: public:
QQuickMouseArea(QQuickItem *parent=0); QQuickMouseArea(QQuickItem *parent=0);
@ -86,6 +87,7 @@ public:
bool hovered() const; bool hovered() const;
bool pressed() const; bool pressed() const;
bool containsPress() const;
Qt::MouseButtons pressedButtons() const; Qt::MouseButtons pressedButtons() const;
@ -135,6 +137,7 @@ Q_SIGNALS:
void entered(); void entered();
void exited(); void exited();
void canceled(); void canceled();
Q_REVISION(1) void containsPressChanged();
protected: protected:
void setHovered(bool); void setHovered(bool);

View File

@ -0,0 +1,20 @@
import QtQuick 2.4
Item {
width: 500
height: 500
Rectangle {
width: 300
height: 300
color: mouseArea.containsPress ? "red" : "grey"
x: 100
y: 100
MouseArea {
id: mouseArea
objectName: "mouseArea"
anchors.fill: parent
}
}
}

View File

@ -123,6 +123,8 @@ private slots:
void moveAndReleaseWithoutPress(); void moveAndReleaseWithoutPress();
void nestedStopAtBounds(); void nestedStopAtBounds();
void nestedStopAtBounds_data(); void nestedStopAtBounds_data();
void containsPress_data();
void containsPress();
private: private:
void acceptedButton_data(); void acceptedButton_data();
@ -1684,6 +1686,69 @@ void tst_QQuickMouseArea::nestedStopAtBounds()
QTest::mouseRelease(&view, Qt::LeftButton, 0, position); QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
} }
void tst_QQuickMouseArea::containsPress_data()
{
QTest::addColumn<bool>("hoverEnabled");
QTest::newRow("hover enabled") << true;
QTest::newRow("hover disaabled") << false;
}
void tst_QQuickMouseArea::containsPress()
{
QFETCH(bool, hoverEnabled);
QQuickView window;
QByteArray errorMessage;
QVERIFY2(initView(window, testFileUrl("containsPress.qml"), true, &errorMessage), errorMessage.constData());
window.show();
window.requestActivate();
QVERIFY(QTest::qWaitForWindowExposed(&window));
QQuickItem *root = window.rootObject();
QVERIFY(root != 0);
QQuickMouseArea *mouseArea = window.rootObject()->findChild<QQuickMouseArea*>("mouseArea");
QVERIFY(mouseArea != 0);
QSignalSpy containsPressSpy(mouseArea, SIGNAL(containsPressChanged()));
mouseArea->setHoverEnabled(hoverEnabled);
QTest::mouseMove(&window, QPoint(22,33));
QCOMPARE(mouseArea->hovered(), false);
QCOMPARE(mouseArea->pressed(), false);
QCOMPARE(mouseArea->containsPress(), false);
QTest::mouseMove(&window, QPoint(200,200));
QCOMPARE(mouseArea->hovered(), hoverEnabled);
QCOMPARE(mouseArea->pressed(), false);
QCOMPARE(mouseArea->containsPress(), false);
QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(200,200));
QCOMPARE(mouseArea->hovered(), true);
QTRY_COMPARE(mouseArea->pressed(), true);
QCOMPARE(mouseArea->containsPress(), true);
QCOMPARE(containsPressSpy.count(), 1);
QTest::mouseMove(&window, QPoint(22,33));
QCOMPARE(mouseArea->hovered(), false);
QCOMPARE(mouseArea->pressed(), true);
QCOMPARE(mouseArea->containsPress(), false);
QCOMPARE(containsPressSpy.count(), 2);
QTest::mouseMove(&window, QPoint(200,200));
QCOMPARE(mouseArea->hovered(), true);
QCOMPARE(mouseArea->pressed(), true);
QCOMPARE(mouseArea->containsPress(), true);
QCOMPARE(containsPressSpy.count(), 3);
QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(200,200));
QCOMPARE(mouseArea->hovered(), hoverEnabled);
QCOMPARE(mouseArea->pressed(), false);
QCOMPARE(mouseArea->containsPress(), false);
QCOMPARE(containsPressSpy.count(), 4);
}
QTEST_MAIN(tst_QQuickMouseArea) QTEST_MAIN(tst_QQuickMouseArea)
#include "tst_qquickmousearea.moc" #include "tst_qquickmousearea.moc"