aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/controls/CheckBox.qml1
-rw-r--r--src/templates/qquickabstractbutton.cpp20
-rw-r--r--src/templates/qquickabstractbutton_p.h3
-rw-r--r--src/templates/qquickcheckbox.cpp83
-rw-r--r--src/templates/qquickcheckbox_p.h22
-rw-r--r--tests/auto/controls/data/tst_checkbox.qml231
6 files changed, 333 insertions, 27 deletions
diff --git a/src/imports/controls/CheckBox.qml b/src/imports/controls/CheckBox.qml
index a24e73ae..565187a4 100644
--- a/src/imports/controls/CheckBox.qml
+++ b/src/imports/controls/CheckBox.qml
@@ -69,6 +69,7 @@ T.CheckBox {
y: (parent.height - height) / 2
width: 12
height: 12
+ opacity: control.tristate && control.checkState === Qt.PartiallyChecked ? 0.5 : 1.0
color: Qt.tint(control.checked && !control.enabled ? control.Theme.disabledColor :
control.checked && control.activeFocus ? control.Theme.focusColor :
control.checked ? control.Theme.accentColor : control.Theme.baseColor,
diff --git a/src/templates/qquickabstractbutton.cpp b/src/templates/qquickabstractbutton.cpp
index 8f3e8af8..ec3bff83 100644
--- a/src/templates/qquickabstractbutton.cpp
+++ b/src/templates/qquickabstractbutton.cpp
@@ -180,6 +180,7 @@ void QQuickAbstractButton::setChecked(bool checked)
if (d->checked != checked) {
d->checked = checked;
setAccessibleProperty("checked", checked);
+ checkStateSet();
emit checkedChanged();
}
}
@@ -303,7 +304,6 @@ void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event)
{
- Q_D(QQuickAbstractButton);
QQuickControl::keyReleaseEvent(event);
if (event->key() == Qt::Key_Space) {
setPressed(false);
@@ -312,8 +312,7 @@ void QQuickAbstractButton::keyReleaseEvent(QKeyEvent *event)
emit released(&mre);
QQuickMouseEvent mce(width() / 2, height() / 2, Qt::NoButton, Qt::NoButton, event->modifiers(), true /* isClick */);
emit clicked(&mce);
- if (d->checkable)
- setChecked(d->exclusive || !d->checked);
+ nextCheckState();
event->setAccepted(mre.isAccepted() || mce.isAccepted());
}
}
@@ -350,8 +349,8 @@ void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event)
} else {
emit canceled();
}
- if (d->checkable && contains(event->pos()))
- setChecked(d->exclusive || !d->checked);
+ if (contains(event->pos()))
+ nextCheckState();
}
void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event)
@@ -373,4 +372,15 @@ void QQuickAbstractButton::mouseUngrabEvent()
}
}
+void QQuickAbstractButton::checkStateSet()
+{
+}
+
+void QQuickAbstractButton::nextCheckState()
+{
+ Q_D(QQuickAbstractButton);
+ if (d->checkable)
+ setChecked(d->exclusive || !d->checked);
+}
+
QT_END_NAMESPACE
diff --git a/src/templates/qquickabstractbutton_p.h b/src/templates/qquickabstractbutton_p.h
index 80d8be4f..949117ae 100644
--- a/src/templates/qquickabstractbutton_p.h
+++ b/src/templates/qquickabstractbutton_p.h
@@ -117,6 +117,9 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ virtual void checkStateSet();
+ virtual void nextCheckState();
+
private:
Q_DISABLE_COPY(QQuickAbstractButton)
Q_DECLARE_PRIVATE(QQuickAbstractButton)
diff --git a/src/templates/qquickcheckbox.cpp b/src/templates/qquickcheckbox.cpp
index 1ced357a..2f70be3e 100644
--- a/src/templates/qquickcheckbox.cpp
+++ b/src/templates/qquickcheckbox.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include "qquickcheckbox_p.h"
+#include "qquickabstractbutton_p_p.h"
QT_BEGIN_NAMESPACE
@@ -80,11 +81,91 @@ QT_BEGIN_NAMESPACE
\sa {Customizing CheckBox}
*/
+class QQuickCheckBoxPrivate : public QQuickAbstractButtonPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickCheckBox)
+
+public:
+ QQuickCheckBoxPrivate() : tristate(false), checkState(Qt::Unchecked) { }
+
+ bool tristate;
+ Qt::CheckState checkState;
+};
+
QQuickCheckBox::QQuickCheckBox(QQuickItem *parent) :
- QQuickAbstractButton(parent)
+ QQuickAbstractButton(*(new QQuickCheckBoxPrivate), parent)
{
setCheckable(true);
setAccessibleRole(0x0000002C); //QAccessible::CheckBox
}
+/*!
+ \qmlproperty bool Qt.labs.controls::CheckBox::tristate
+
+ This property holds whether the checkbox is a tri-state checkbox.
+
+ The default is \c false, i.e., the checkbox has only two states.
+*/
+bool QQuickCheckBox::isTristate() const
+{
+ Q_D(const QQuickCheckBox);
+ return d->tristate;
+}
+
+void QQuickCheckBox::setTristate(bool tristate)
+{
+ Q_D(QQuickCheckBox);
+ if (d->tristate != tristate) {
+ d->tristate = tristate;
+ emit tristateChanged();
+ }
+}
+
+/*!
+ \qmlproperty enumeration Qt.labs.controls::CheckBox::checkState
+
+ This property holds the check state of the checkbox.
+
+ Available states:
+ \value Qt.Unchecked The checkbox is unchecked.
+ \value Qt.PartiallyChecked The checkbox is partially checked. This state is only used when \l tristate is enabled.
+ \value Qt.Checked The checkbox is checked.
+
+ \sa tristate, {AbstractButton::checked}{checked}
+*/
+Qt::CheckState QQuickCheckBox::checkState() const
+{
+ Q_D(const QQuickCheckBox);
+ return d->checkState;
+}
+
+void QQuickCheckBox::setCheckState(Qt::CheckState state)
+{
+ Q_D(QQuickCheckBox);
+ if (!d->tristate && state == Qt::PartiallyChecked)
+ setTristate(true);
+ if (d->checkState != state) {
+ bool wasChecked = isChecked();
+ d->checked = state != Qt::Unchecked;
+ d->checkState = state;
+ emit checkStateChanged();
+ if (d->checked != wasChecked)
+ emit checkedChanged();
+ }
+}
+
+void QQuickCheckBox::checkStateSet()
+{
+ setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+}
+
+void QQuickCheckBox::nextCheckState()
+{
+ Q_D(QQuickCheckBox);
+ if (d->tristate)
+ setCheckState(static_cast<Qt::CheckState>((d->checkState + 1) % 3));
+ else
+ QQuickAbstractButton::nextCheckState();
+}
+
QT_END_NAMESPACE
diff --git a/src/templates/qquickcheckbox_p.h b/src/templates/qquickcheckbox_p.h
index c0ff4c44..b2f98e92 100644
--- a/src/templates/qquickcheckbox_p.h
+++ b/src/templates/qquickcheckbox_p.h
@@ -52,12 +52,34 @@
QT_BEGIN_NAMESPACE
+class QQuickCheckBoxPrivate;
+
class Q_LABSTEMPLATES_EXPORT QQuickCheckBox : public QQuickAbstractButton
{
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)
public:
explicit QQuickCheckBox(QQuickItem *parent = Q_NULLPTR);
+
+ bool isTristate() const;
+ void setTristate(bool tristate);
+
+ Qt::CheckState checkState() const;
+ void setCheckState(Qt::CheckState state);
+
+Q_SIGNALS:
+ void tristateChanged();
+ void checkStateChanged();
+
+protected:
+ void checkStateSet() Q_DECL_OVERRIDE;
+ void nextCheckState() Q_DECL_OVERRIDE;
+
+private:
+ Q_DISABLE_COPY(QQuickCheckBox)
+ Q_DECLARE_PRIVATE(QQuickCheckBox)
};
Q_DECLARE_TYPEINFO(QQuickCheckBox, Q_COMPLEX_TYPE);
diff --git a/tests/auto/controls/data/tst_checkbox.qml b/tests/auto/controls/data/tst_checkbox.qml
index caf6658b..c61cab38 100644
--- a/tests/auto/controls/data/tst_checkbox.qml
+++ b/tests/auto/controls/data/tst_checkbox.qml
@@ -57,7 +57,7 @@ TestCase {
property ControlSpy spy: ControlSpy {
target: control
- signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged"]
+ signals: ["pressed", "released", "canceled", "clicked", "pressedChanged", "checkedChanged", "checkStateChanged"]
}
}
}
@@ -81,16 +81,47 @@ TestCase {
control.spy.expectedSequence = []
compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
verify(control.spy.success)
- control.spy.expectedSequence = [["checkedChanged", { "checked": true }]]
+ control.spy.expectedSequence = [["checkStateChanged", { "checked": true, "checkState": Qt.Checked }],
+ ["checkedChanged", { "checked": true, "checkState": Qt.Checked }]]
control.checked = true
compare(control.checked, true)
+ compare(control.checkState, Qt.Checked)
verify(control.spy.success)
- control.spy.expectedSequence = [["checkedChanged", { "checked": false }]]
+ control.spy.expectedSequence = [["checkStateChanged", { "checked": false, "checkState": Qt.Unchecked }],
+ ["checkedChanged", { "checked": false, "checkState": Qt.Unchecked }]]
control.checked = false
compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
+ verify(control.spy.success)
+
+ control.destroy()
+ }
+
+ function test_checkState() {
+ var control = checkBox.createObject(testCase)
+ verify(control)
+
+ control.spy.expectedSequence = []
+ compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
+ verify(control.spy.success)
+
+ control.spy.expectedSequence = [["checkStateChanged", { "checked": true, "checkState": Qt.Checked }],
+ ["checkedChanged", { "checked": true, "checkState": Qt.Checked }]]
+ control.checkState = Qt.Checked
+ compare(control.checked, true)
+ compare(control.checkState, Qt.Checked)
+ verify(control.spy.success)
+
+ control.spy.expectedSequence = [["checkStateChanged", { "checked": false, "checkState": Qt.Unchecked }],
+ ["checkedChanged", { "checked": false, "checkState": Qt.Unchecked }]]
+ control.checkState = Qt.Unchecked
+ compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
verify(control.spy.success)
control.destroy()
@@ -101,49 +132,54 @@ TestCase {
verify(control)
// check
- control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
"pressed"]
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.pressed, true)
verify(control.spy.success)
- control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
"released",
"clicked",
- ["checkedChanged", { "pressed": false, "checked": true }]]
+ ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
+ ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }]]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.checked, true)
+ compare(control.checkState, Qt.Checked)
compare(control.pressed, false)
verify(control.spy.success)
// uncheck
- control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }],
"pressed"]
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.pressed, true)
verify(control.spy.success)
- control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
"released",
"clicked",
- ["checkedChanged", { "pressed": false, "checked": false }]]
+ ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ ["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]]
mouseRelease(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
compare(control.pressed, false)
verify(control.spy.success)
// release outside
- control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
"pressed"]
mousePress(control, control.width / 2, control.height / 2, Qt.LeftButton)
compare(control.pressed, true)
verify(control.spy.success)
- control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }]]
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]]
mouseMove(control, control.width * 2, control.height * 2, 0, Qt.LeftButton)
compare(control.pressed, false)
verify(control.spy.success)
- control.spy.expectedSequence = [["canceled", { "pressed": false, "checked": false }]]
+ control.spy.expectedSequence = [["canceled", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]]
mouseRelease(control, control.width * 2, control.height * 2, Qt.LeftButton)
compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
compare(control.pressed, false)
verify(control.spy.success)
@@ -153,6 +189,7 @@ TestCase {
compare(control.pressed, false)
mouseRelease(control, control.width / 2, control.height / 2, Qt.RightButton)
compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
compare(control.pressed, false)
verify(control.spy.success)
@@ -169,25 +206,29 @@ TestCase {
verify(control.spy.success)
// check
- control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
"pressed",
- ["pressedChanged", { "pressed": false, "checked": false }],
+ ["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
"released",
"clicked",
- ["checkedChanged", { "pressed": false, "checked": true }]]
+ ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
+ ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }]]
keyClick(Qt.Key_Space)
compare(control.checked, true)
+ compare(control.checkState, Qt.Checked)
verify(control.spy.success)
// uncheck
- control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }],
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }],
"pressed",
- ["pressedChanged", { "pressed": false, "checked": true }],
+ ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
"released",
"clicked",
- ["checkedChanged", { "pressed": false, "checked": false }]]
+ ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ ["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]]
keyClick(Qt.Key_Space)
compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
verify(control.spy.success)
// no change
@@ -204,28 +245,176 @@ TestCase {
}
Component {
- id: twoCheckBoxes
+ id: checkedBoundBoxes
Item {
property CheckBox cb1: CheckBox { id: cb1 }
property CheckBox cb2: CheckBox { id: cb2; checked: cb1.checked; enabled: false }
}
}
- function test_binding() {
- var container = twoCheckBoxes.createObject(testCase)
+ function test_checked_binding() {
+ var container = checkedBoundBoxes.createObject(testCase)
verify(container)
compare(container.cb1.checked, false)
+ compare(container.cb1.checkState, Qt.Unchecked)
compare(container.cb2.checked, false)
+ compare(container.cb2.checkState, Qt.Unchecked)
container.cb1.checked = true
compare(container.cb1.checked, true)
+ compare(container.cb1.checkState, Qt.Checked)
compare(container.cb2.checked, true)
+ compare(container.cb2.checkState, Qt.Checked)
container.cb1.checked = false
compare(container.cb1.checked, false)
+ compare(container.cb1.checkState, Qt.Unchecked)
compare(container.cb2.checked, false)
+ compare(container.cb2.checkState, Qt.Unchecked)
container.destroy()
}
+
+ Component {
+ id: checkStateBoundBoxes
+ Item {
+ property CheckBox cb1: CheckBox { id: cb1 }
+ property CheckBox cb2: CheckBox { id: cb2; checkState: cb1.checkState; enabled: false }
+ }
+ }
+
+ function test_checkState_binding() {
+ var container = checkStateBoundBoxes.createObject(testCase)
+ verify(container)
+
+ compare(container.cb1.checked, false)
+ compare(container.cb1.checkState, Qt.Unchecked)
+ compare(container.cb2.checked, false)
+ compare(container.cb2.checkState, Qt.Unchecked)
+
+ container.cb1.checkState = Qt.Checked
+ compare(container.cb1.checked, true)
+ compare(container.cb1.checkState, Qt.Checked)
+ compare(container.cb2.checked, true)
+ compare(container.cb2.checkState, Qt.Checked)
+
+ container.cb1.checkState = Qt.Unchecked
+ compare(container.cb1.checked, false)
+ compare(container.cb1.checkState, Qt.Unchecked)
+ compare(container.cb2.checked, false)
+ compare(container.cb2.checkState, Qt.Unchecked)
+
+ compare(container.cb1.tristate, false)
+ compare(container.cb2.tristate, false)
+
+ container.cb1.checkState = Qt.PartiallyChecked
+ compare(container.cb1.checked, true)
+ compare(container.cb1.checkState, Qt.PartiallyChecked)
+ compare(container.cb2.checked, true)
+ compare(container.cb2.checkState, Qt.PartiallyChecked)
+
+ compare(container.cb1.tristate, true)
+ compare(container.cb2.tristate, true)
+
+ container.destroy()
+ }
+
+ function test_tristate() {
+ var control = checkBox.createObject(testCase)
+
+ control.spy.expectedSequence = []
+ control.forceActiveFocus()
+ verify(control.activeFocus)
+
+ compare(control.tristate, false)
+ compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
+
+ control.spy.expectedSequence = [["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }],
+ ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }]]
+ control.checkState = Qt.PartiallyChecked
+ compare(control.tristate, true)
+ compare(control.checked, true)
+ compare(control.checkState, Qt.PartiallyChecked)
+ verify(control.spy.success)
+
+ // key: partial -> checked
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.PartiallyChecked }],
+ "pressed",
+ ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }],
+ "released",
+ "clicked",
+ ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }]]
+ keyClick(Qt.Key_Space)
+ compare(control.checked, true)
+ compare(control.checkState, Qt.Checked)
+ verify(control.spy.success)
+
+ // key: checked -> unchecked
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }],
+ "pressed",
+ ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
+ "released",
+ "clicked",
+ ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ ["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]]
+ keyClick(Qt.Key_Space)
+ compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
+ verify(control.spy.success)
+
+ // key: unchecked -> partial
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
+ "pressed",
+ ["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ "released",
+ "clicked",
+ ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }],
+ ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }]]
+ keyClick(Qt.Key_Space)
+ compare(control.checked, true)
+ compare(control.checkState, Qt.PartiallyChecked)
+ verify(control.spy.success)
+
+ // mouse: partial -> checked
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.PartiallyChecked }],
+ "pressed",
+ ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }],
+ "released",
+ "clicked",
+ ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }]]
+ mouseClick(control)
+ compare(control.checked, true)
+ compare(control.checkState, Qt.Checked)
+ verify(control.spy.success)
+
+ // mouse: checked -> unchecked
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true, "checkState": Qt.Checked }],
+ "pressed",
+ ["pressedChanged", { "pressed": false, "checked": true, "checkState": Qt.Checked }],
+ "released",
+ "clicked",
+ ["checkStateChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ ["checkedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }]]
+ mouseClick(control)
+ compare(control.checked, false)
+ compare(control.checkState, Qt.Unchecked)
+ verify(control.spy.success)
+
+ // mouse: unchecked -> partial
+ control.spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false, "checkState": Qt.Unchecked }],
+ "pressed",
+ ["pressedChanged", { "pressed": false, "checked": false, "checkState": Qt.Unchecked }],
+ "released",
+ "clicked",
+ ["checkStateChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }],
+ ["checkedChanged", { "pressed": false, "checked": true, "checkState": Qt.PartiallyChecked }]]
+ mouseClick(control)
+ compare(control.checked, true)
+ compare(control.checkState, Qt.PartiallyChecked)
+ verify(control.spy.success)
+
+ control.destroy()
+ }
}