Expose QQuickCheckBox::nextCheckState() to QML

[ChangeLog][Controls][CheckBox] Made it possible to implement
nextCheckState() in QML.

Task-number: QTBUG-63238
Change-Id: I9ca27409efcaf546f557b974563ba598658fe694
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
This commit is contained in:
J-P Nurmi 2017-10-25 20:13:09 +02:00
parent a44d4b5f22
commit 043e3d24f9
3 changed files with 98 additions and 1 deletions

View File

@ -38,6 +38,7 @@
#include "qquickabstractbutton_p_p.h"
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qjsvalue.h>
QT_BEGIN_NAMESPACE
@ -107,10 +108,20 @@ public:
{
}
void setNextCheckState(const QJSValue &callback);
bool tristate;
Qt::CheckState checkState;
QJSValue nextCheckState;
};
void QQuickCheckBoxPrivate::setNextCheckState(const QJSValue &callback)
{
Q_Q(QQuickCheckBox);
nextCheckState = callback;
emit q->nextCheckStateChanged();
}
QQuickCheckBox::QQuickCheckBox(QQuickItem *parent)
: QQuickAbstractButton(*(new QQuickCheckBoxPrivate), parent)
{
@ -194,10 +205,45 @@ void QQuickCheckBox::buttonChange(ButtonChange change)
QQuickAbstractButton::buttonChange(change);
}
/*!
\since QtQuick.Controls 2.4 (Qt 5.11)
\qmlproperty function QtQuick.Controls::CheckBox::nextCheckState
This property holds a callback function that is called to determine
the next check state whenever the checkbox is interactively toggled
by the user via touch, mouse, or keyboard.
By default, a normal checkbox cycles between \c Qt.Unchecked and
\c Qt.Checked states, and a tri-state checkbox cycles between
\c Qt.Unchecked, \c Qt.PartiallyChecked, and \c Qt.Checked states.
The \c nextCheckState callback function can override the default behavior.
The following example implements a tri-state checkbox that can present
a partially checked state depending on external conditions, but never
cycles to the partially checked state when interactively toggled by
the user.
\code
CheckBox {
tristate: true
checkState: allChildrenChecked ? Qt.Checked :
anyChildChecked ? Qt.PartiallyChecked : Qt.Unchecked
nextCheckState: function() {
if (checkState === Qt.Checked)
return Qt.Unchecked
else
return Qt.Checked
}
}
\endcode
*/
void QQuickCheckBox::nextCheckState()
{
Q_D(QQuickCheckBox);
if (d->tristate)
if (d->nextCheckState.isCallable())
setCheckState(static_cast<Qt::CheckState>(d->nextCheckState.call().toInt()));
else if (d->tristate)
setCheckState(static_cast<Qt::CheckState>((d->checkState + 1) % 3));
else
QQuickAbstractButton::nextCheckState();
@ -211,3 +257,5 @@ QAccessible::Role QQuickCheckBox::accessibleRole() const
#endif
QT_END_NAMESPACE
#include "moc_qquickcheckbox_p.cpp"

View File

@ -59,6 +59,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickCheckBox : public QQuickAbstractBut
Q_OBJECT
Q_PROPERTY(bool tristate READ isTristate WRITE setTristate NOTIFY tristateChanged FINAL)
Q_PROPERTY(Qt::CheckState checkState READ checkState WRITE setCheckState NOTIFY checkStateChanged FINAL)
Q_PRIVATE_PROPERTY(QQuickCheckBox::d_func(), QJSValue nextCheckState MEMBER nextCheckState WRITE setNextCheckState NOTIFY nextCheckStateChanged FINAL REVISION 4)
public:
explicit QQuickCheckBox(QQuickItem *parent = nullptr);
@ -72,6 +73,7 @@ public:
Q_SIGNALS:
void tristateChanged();
void checkStateChanged();
Q_REVISION(4) void nextCheckStateChanged();
protected:
QFont defaultFont() const override;

View File

@ -494,4 +494,51 @@ TestCase {
verify(control)
compare(control.baselineOffset, control.contentItem.y + control.contentItem.baselineOffset)
}
Component {
id: nextCheckStateBox
CheckBox {
tristate: true
nextCheckState: function() {
if (checkState === Qt.Checked)
return Qt.Unchecked
else
return Qt.Checked
}
}
}
function test_nextCheckState_data() {
return [
{ tag: "unchecked", checkState: Qt.Unchecked, expectedState: Qt.Checked },
{ tag: "partially-checked", checkState: Qt.PartiallyChecked, expectedState: Qt.Checked },
{ tag: "checked", checkState: Qt.Checked, expectedState: Qt.Unchecked }
]
}
function test_nextCheckState(data) {
var control = createTemporaryObject(nextCheckStateBox, testCase)
verify(control)
// mouse
control.checkState = data.checkState
compare(control.checkState, data.checkState)
mouseClick(control)
compare(control.checkState, data.expectedState)
// touch
control.checkState = data.checkState
compare(control.checkState, data.checkState)
var touch = touchEvent(control)
touch.press(0, control).commit().release(0, control).commit()
compare(control.checkState, data.expectedState)
// keyboard
control.forceActiveFocus()
tryCompare(control, "activeFocus", true)
control.checkState = data.checkState
compare(control.checkState, data.checkState)
keyClick(Qt.Key_Space)
compare(control.checkState, data.expectedState)
}
}