aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/templates/qquickabstractbutton.cpp109
-rw-r--r--src/templates/qquickabstractbutton_p.h6
-rw-r--r--src/templates/qquickabstractbutton_p_p.h9
-rw-r--r--tests/auto/controls/data/tst_button.qml58
4 files changed, 177 insertions, 5 deletions
diff --git a/src/templates/qquickabstractbutton.cpp b/src/templates/qquickabstractbutton.cpp
index df5822fa..849d2340 100644
--- a/src/templates/qquickabstractbutton.cpp
+++ b/src/templates/qquickabstractbutton.cpp
@@ -37,10 +37,15 @@
#include "qquickabstractbutton_p.h"
#include "qquickabstractbutton_p_p.h"
+#include <QtGui/qguiapplication.h>
#include <QtQuick/private/qquickevents_p_p.h>
QT_BEGIN_NAMESPACE
+// copied from qabstractbutton.cpp
+static const int AUTO_REPEAT_DELAY = 300;
+static const int AUTO_REPEAT_INTERVAL = 100;
+
/*!
\qmltype AbstractButton
\inherits Control
@@ -95,9 +100,36 @@ QT_BEGIN_NAMESPACE
*/
QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() :
- pressed(false), checked(false), checkable(false), exclusive(false),
- label(Q_NULLPTR), indicator(Q_NULLPTR)
+ pressed(false), checked(false), checkable(false), exclusive(false), autoRepeat(false),
+ delayTimer(0), repeatTimer(0), repeatButton(Qt::NoButton), label(Q_NULLPTR), indicator(Q_NULLPTR)
+{
+}
+
+void QQuickAbstractButtonPrivate::startRepeatDelay()
{
+ Q_Q(QQuickAbstractButton);
+ stopPressRepeat();
+ delayTimer = q->startTimer(AUTO_REPEAT_DELAY);
+}
+
+void QQuickAbstractButtonPrivate::startPressRepeat()
+{
+ Q_Q(QQuickAbstractButton);
+ stopPressRepeat();
+ repeatTimer = q->startTimer(AUTO_REPEAT_INTERVAL);
+}
+
+void QQuickAbstractButtonPrivate::stopPressRepeat()
+{
+ Q_Q(QQuickAbstractButton);
+ if (delayTimer > 0) {
+ q->killTimer(delayTimer);
+ delayTimer = 0;
+ }
+ if (repeatTimer > 0) {
+ q->killTimer(repeatTimer);
+ repeatTimer = 0;
+ }
}
QQuickAbstractButton::QQuickAbstractButton(QQuickItem *parent) :
@@ -217,6 +249,30 @@ void QQuickAbstractButton::setExclusive(bool exclusive)
}
/*!
+ \qmlproperty bool Qt.labs.controls::AbstractButton::autoRepeat
+
+ This property holds whether the button repeats pressed(), released()
+ and clicked() signals while the button is pressed and held down.
+
+ The default value is \c false.
+*/
+bool QQuickAbstractButton::autoRepeat() const
+{
+ Q_D(const QQuickAbstractButton);
+ return d->autoRepeat;
+}
+
+void QQuickAbstractButton::setAutoRepeat(bool repeat)
+{
+ Q_D(QQuickAbstractButton);
+ if (d->autoRepeat != repeat) {
+ d->stopPressRepeat();
+ d->autoRepeat = repeat;
+ emit autoRepeatChanged();
+ }
+}
+
+/*!
\qmlproperty Item Qt.labs.controls::AbstractButton::indicator
This property holds the indicator item.
@@ -290,11 +346,18 @@ void QQuickAbstractButton::focusOutEvent(QFocusEvent *event)
void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
{
+ Q_D(QQuickAbstractButton);
QQuickControl::keyPressEvent(event);
if (event->key() == Qt::Key_Space) {
setPressed(true);
+ d->pressPoint = QPoint(qRound(width() / 2), qRound(height() / 2));
+
+ if (d->autoRepeat) {
+ d->startRepeatDelay();
+ d->repeatButton = Qt::NoButton;
+ }
- QQuickMouseEvent me(width() / 2, height() / 2, Qt::NoButton, Qt::NoButton, event->modifiers());
+ QQuickMouseEvent me(d->pressPoint.x(), d->pressPoint.y(), Qt::NoButton, QGuiApplication::mouseButtons(), event->modifiers());
emit pressed(&me);
event->setAccepted(me.isAccepted());
}
@@ -302,33 +365,48 @@ void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event)
{
+ Q_D(QQuickAbstractButton);
QQuickControl::keyReleaseEvent(event);
if (event->key() == Qt::Key_Space) {
setPressed(false);
- QQuickMouseEvent mre(width() / 2, height() / 2, Qt::NoButton, Qt::NoButton, event->modifiers());
+ QQuickMouseEvent mre(d->pressPoint.x(), d->pressPoint.y(), Qt::NoButton, QGuiApplication::mouseButtons(), event->modifiers());
emit released(&mre);
- QQuickMouseEvent mce(width() / 2, height() / 2, Qt::NoButton, Qt::NoButton, event->modifiers(), true /* isClick */);
+ QQuickMouseEvent mce(d->pressPoint.x(), d->pressPoint.y(), Qt::NoButton, QGuiApplication::mouseButtons(), event->modifiers(), true /* isClick */);
emit clicked(&mce);
nextCheckState();
event->setAccepted(mre.isAccepted() || mce.isAccepted());
+
+ if (d->autoRepeat)
+ d->stopPressRepeat();
}
}
void QQuickAbstractButton::mousePressEvent(QMouseEvent *event)
{
+ Q_D(QQuickAbstractButton);
QQuickControl::mousePressEvent(event);
setPressed(true);
+ d->pressPoint = event->pos();
QQuickMouseEvent me(event->x(), event->y(), event->button(), event->buttons(), event->modifiers());
emit pressed(&me);
event->setAccepted(me.isAccepted());
+
+ if (d->autoRepeat) {
+ d->startRepeatDelay();
+ d->repeatButton = event->button();
+ }
}
void QQuickAbstractButton::mouseMoveEvent(QMouseEvent *event)
{
+ Q_D(QQuickAbstractButton);
QQuickControl::mouseMoveEvent(event);
setPressed(contains(event->pos()));
+
+ if (d->autoRepeat)
+ d->stopPressRepeat();
}
void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event)
@@ -347,8 +425,12 @@ void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event)
} else {
emit canceled();
}
+
if (contains(event->pos()))
nextCheckState();
+
+ if (d->autoRepeat)
+ d->stopPressRepeat();
}
void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event)
@@ -366,10 +448,27 @@ void QQuickAbstractButton::mouseUngrabEvent()
QQuickControl::mouseUngrabEvent();
if (d->pressed) {
setPressed(false);
+ d->stopPressRepeat();
emit canceled();
}
}
+void QQuickAbstractButton::timerEvent(QTimerEvent *event)
+{
+ Q_D(QQuickAbstractButton);
+ QQuickControl::timerEvent(event);
+ if (event->timerId() == d->delayTimer) {
+ d->startPressRepeat();
+ } else if (event->timerId() == d->repeatTimer) {
+ QQuickMouseEvent mre(d->pressPoint.x(), d->pressPoint.y(), d->repeatButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
+ emit released(&mre);
+ QQuickMouseEvent mce(d->pressPoint.x(), d->pressPoint.y(), d->repeatButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers(), true /* isClick */);
+ emit clicked(&mce);
+ QQuickMouseEvent mpe(d->pressPoint.x(), d->pressPoint.y(), d->repeatButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
+ emit pressed(&mpe);
+ }
+}
+
void QQuickAbstractButton::checkStateSet()
{
}
diff --git a/src/templates/qquickabstractbutton_p.h b/src/templates/qquickabstractbutton_p.h
index ea1eacc8..5ab24a23 100644
--- a/src/templates/qquickabstractbutton_p.h
+++ b/src/templates/qquickabstractbutton_p.h
@@ -62,6 +62,7 @@ class Q_LABSTEMPLATES_EXPORT QQuickAbstractButton : public QQuickControl
Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(bool checked READ isChecked WRITE setChecked NOTIFY checkedChanged FINAL)
Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY checkableChanged FINAL)
+ Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY autoRepeatChanged FINAL)
Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL)
Q_PROPERTY(QQuickItem *label READ label WRITE setLabel NOTIFY labelChanged FINAL)
@@ -83,6 +84,9 @@ public:
bool isExclusive() const;
void setExclusive(bool exclusive);
+ bool autoRepeat() const;
+ void setAutoRepeat(bool repeat);
+
QQuickItem *indicator() const;
void setIndicator(QQuickItem *indicator);
@@ -102,6 +106,7 @@ Q_SIGNALS:
void pressedChanged();
void checkedChanged();
void checkableChanged();
+ void autoRepeatChanged();
void indicatorChanged();
void labelChanged();
@@ -116,6 +121,7 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
virtual void checkStateSet();
virtual void nextCheckState();
diff --git a/src/templates/qquickabstractbutton_p_p.h b/src/templates/qquickabstractbutton_p_p.h
index e8def77d..bfdadb19 100644
--- a/src/templates/qquickabstractbutton_p_p.h
+++ b/src/templates/qquickabstractbutton_p_p.h
@@ -59,11 +59,20 @@ class QQuickAbstractButtonPrivate : public QQuickControlPrivate
public:
QQuickAbstractButtonPrivate();
+ void startRepeatDelay();
+ void startPressRepeat();
+ void stopPressRepeat();
+
QString text;
bool pressed;
bool checked;
bool checkable;
bool exclusive;
+ bool autoRepeat;
+ int delayTimer;
+ int repeatTimer;
+ QPointF pressPoint;
+ Qt::MouseButton repeatButton;
QQuickItem *label;
QQuickItem *indicator;
};
diff --git a/tests/auto/controls/data/tst_button.qml b/tests/auto/controls/data/tst_button.qml
index 638a773c..76d45e03 100644
--- a/tests/auto/controls/data/tst_button.qml
+++ b/tests/auto/controls/data/tst_button.qml
@@ -232,4 +232,62 @@ TestCase {
control.destroy()
}
+
+ SignalSpy { id: clickSpy; signalName: "clicked" }
+
+ function test_autoRepeat() {
+ var control = button.createObject(testCase)
+ verify(control)
+
+ compare(control.autoRepeat, false)
+ control.autoRepeat = true
+ compare(control.autoRepeat, true)
+
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ clickSpy.target = control
+ verify(clickSpy.valid)
+
+ var repeatCount = 2
+ var repeatSequence = [["pressedChanged", { "pressed": true }],
+ "pressed",
+ "released",
+ "clicked",
+ "pressed",
+ "released",
+ "clicked",
+ "pressed"]
+
+ // auto-repeat a couple of mouse clicks
+ control.spy.expectedSequence = repeatSequence
+ mousePress(control)
+ compare(control.pressed, true)
+ tryCompare(clickSpy, "count", repeatCount)
+ verify(control.spy.success)
+
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": false }],
+ "released",
+ "clicked"]
+ mouseRelease(control)
+ compare(control.pressed, false)
+ verify(control.spy.success)
+
+ // auto-repeat a couple of key clicks
+ clickSpy.clear()
+ control.spy.expectedSequence = repeatSequence
+ keyPress(Qt.Key_Space)
+ compare(control.pressed, true)
+ tryCompare(clickSpy, "count", repeatCount)
+ verify(control.spy.success)
+
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": false }],
+ "released",
+ "clicked"]
+ keyRelease(Qt.Key_Space)
+ compare(control.pressed, false)
+ verify(control.spy.success)
+
+ control.destroy()
+ }
}