diff options
-rw-r--r-- | src/imports/controls/qtquickcontrols2plugin.cpp | 1 | ||||
-rw-r--r-- | src/imports/templates/qtquicktemplates2plugin.cpp | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickbuttongroup.cpp | 50 | ||||
-rw-r--r-- | src/quicktemplates2/qquickbuttongroup_p.h | 5 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_buttongroup.qml | 62 |
5 files changed, 112 insertions, 7 deletions
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index aa4eb295..48d027dd 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -158,6 +158,7 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) // QtQuick.Controls 2.3 (new types in Qt 5.10) qmlRegisterType<QQuickAction>(uri, 2, 3, "Action"); qmlRegisterType<QQuickActionGroup>(uri, 2, 3, "ActionGroup"); + qmlRegisterType<QQuickButtonGroup, 3>(uri, 2, 3, "ButtonGroup"); qmlRegisterType<QQuickIcon>(); } diff --git a/src/imports/templates/qtquicktemplates2plugin.cpp b/src/imports/templates/qtquicktemplates2plugin.cpp index e16a0e45..32779b4a 100644 --- a/src/imports/templates/qtquicktemplates2plugin.cpp +++ b/src/imports/templates/qtquicktemplates2plugin.cpp @@ -260,6 +260,7 @@ void QtQuickTemplates2Plugin::registerTypes(const char *uri) qmlRegisterType<QQuickAbstractButton, 3>(uri, 2, 3, "AbstractButton"); qmlRegisterType<QQuickAction>(uri, 2, 3, "Action"); qmlRegisterType<QQuickActionGroup>(uri, 2, 3, "ActionGroup"); + qmlRegisterType<QQuickButtonGroup, 3>(uri, 2, 3, "ButtonGroup"); qmlRegisterType<QQuickIcon>(); qmlRegisterType<QQuickRangeSlider, 3>(uri, 2, 3, "RangeSlider"); qmlRegisterType<QQuickScrollBar, 3>(uri, 2, 3, "ScrollBar"); diff --git a/src/quicktemplates2/qquickbuttongroup.cpp b/src/quicktemplates2/qquickbuttongroup.cpp index a9c0d435..705224d6 100644 --- a/src/quicktemplates2/qquickbuttongroup.cpp +++ b/src/quicktemplates2/qquickbuttongroup.cpp @@ -154,7 +154,11 @@ class QQuickButtonGroupPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QQuickButtonGroup) public: - QQuickButtonGroupPrivate() : checkedButton(nullptr) { } + QQuickButtonGroupPrivate() + : exclusive(true), + checkedButton(nullptr) + { + } void clear(); void buttonClicked(); @@ -165,6 +169,7 @@ public: static QQuickAbstractButton *buttons_at(QQmlListProperty<QQuickAbstractButton> *prop, int index); static void buttons_clear(QQmlListProperty<QQuickAbstractButton> *prop); + bool exclusive; QQuickAbstractButton *checkedButton; QVector<QQuickAbstractButton*> buttons; }; @@ -190,6 +195,8 @@ void QQuickButtonGroupPrivate::buttonClicked() void QQuickButtonGroupPrivate::_q_updateCurrent() { Q_Q(QQuickButtonGroup); + if (!exclusive) + return; QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(q->sender()); if (button && button->isChecked()) q->setCheckedButton(button); @@ -246,9 +253,12 @@ QQuickButtonGroupAttached *QQuickButtonGroup::qmlAttachedProperties(QObject *obj /*! \qmlproperty AbstractButton QtQuick.Controls::ButtonGroup::checkedButton - This property holds the currently selected button, or \c null if there is none. + This property holds the currently selected button in an exclusive group, + or \c null if there is none or the group is non-exclusive. + + By default, it is the first checked button added to an exclusive button group. - By default, it is the first checked button added to the button group. + \sa exclusive */ QQuickAbstractButton *QQuickButtonGroup::checkedButton() const { @@ -308,6 +318,38 @@ QQmlListProperty<QQuickAbstractButton> QQuickButtonGroup::buttons() } /*! + \since QtQuick.Controls 2.3 + \qmlproperty bool QtQuick.Controls::ButtonGroup::exclusive + + This property holds whether the button group is exclusive. The default value is \c true. + + If this property is \c true, then only one button in the group can be checked at any given time. + The user can click on any button to check it, and that button will replace the existing one as + the checked button in the group. + + In an exclusive group, the user cannot uncheck the currently checked button by clicking on it; + instead, another button in the group must be clicked to set the new checked button for that group. + + In a non-exclusive group, checking and unchecking buttons does not affect the other buttons in + the group. Furthermore, the value of the \l checkedButton property is \c null. +*/ +bool QQuickButtonGroup::isExclusive() const +{ + Q_D(const QQuickButtonGroup); + return d->exclusive; +} + +void QQuickButtonGroup::setExclusive(bool exclusive) +{ + Q_D(QQuickButtonGroup); + if (d->exclusive == exclusive) + return; + + d->exclusive = exclusive; + emit exclusiveChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::ButtonGroup::addButton(AbstractButton button) Adds a \a button to the button group. @@ -328,7 +370,7 @@ void QQuickButtonGroup::addButton(QQuickAbstractButton *button) QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, d, &QQuickButtonGroupPrivate::buttonClicked); QObjectPrivate::connect(button, &QQuickAbstractButton::checkedChanged, d, &QQuickButtonGroupPrivate::_q_updateCurrent); - if (button->isChecked()) + if (d->exclusive && button->isChecked()) setCheckedButton(button); d->buttons.append(button); diff --git a/src/quicktemplates2/qquickbuttongroup_p.h b/src/quicktemplates2/qquickbuttongroup_p.h index 21deb035..5fe1858d 100644 --- a/src/quicktemplates2/qquickbuttongroup_p.h +++ b/src/quicktemplates2/qquickbuttongroup_p.h @@ -64,6 +64,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickButtonGroup : public QObject Q_OBJECT Q_PROPERTY(QQuickAbstractButton *checkedButton READ checkedButton WRITE setCheckedButton NOTIFY checkedButtonChanged) Q_PROPERTY(QQmlListProperty<QQuickAbstractButton> buttons READ buttons NOTIFY buttonsChanged FINAL) + Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive NOTIFY exclusiveChanged FINAL REVISION 3) public: explicit QQuickButtonGroup(QObject *parent = nullptr); @@ -76,6 +77,9 @@ public: QQmlListProperty<QQuickAbstractButton> buttons(); + bool isExclusive() const; + void setExclusive(bool exclusive); + public Q_SLOTS: void addButton(QQuickAbstractButton *button); void removeButton(QQuickAbstractButton *button); @@ -83,6 +87,7 @@ public Q_SLOTS: Q_SIGNALS: void checkedButtonChanged(); void buttonsChanged(); + Q_REVISION(3) void exclusiveChanged(); Q_REVISION(1) void clicked(QQuickAbstractButton *button); private: diff --git a/tests/auto/controls/data/tst_buttongroup.qml b/tests/auto/controls/data/tst_buttongroup.qml index bde655da..cbbaec5a 100644 --- a/tests/auto/controls/data/tst_buttongroup.qml +++ b/tests/auto/controls/data/tst_buttongroup.qml @@ -50,7 +50,7 @@ import QtQuick 2.2 import QtTest 1.0 -import QtQuick.Controls 2.2 +import QtQuick.Controls 2.3 TestCase { id: testCase @@ -66,6 +66,11 @@ TestCase { } Component { + id: nonExclusiveGroup + ButtonGroup { exclusive: false } + } + + Component { id: signalSpy SignalSpy { } } @@ -88,6 +93,14 @@ TestCase { QtObject { } } + function test_defaults() { + var group = createTemporaryObject(buttonGroup, testCase) + verify(group) + compare(group.buttons.length, 0) + compare(group.checkedButton, null) + compare(group.exclusive, true) + } + function test_current() { var group = createTemporaryObject(buttonGroup, testCase) verify(group) @@ -200,8 +213,15 @@ TestCase { compare(buttonsSpy.count, 5) } - function test_clicked() { - var group = createTemporaryObject(buttonGroup, testCase) + function test_clicked_data() { + return [ + {tag: "exclusive", exclusive: true}, + {tag: "non-exclusive", exclusive: false} + ] + } + + function test_clicked(data) { + var group = createTemporaryObject(buttonGroup, testCase, {exclusive: data.exclusive}) verify(group) var clickedSpy = createTemporaryObject(signalSpy, testCase, {target: group, signalName: "clicked"}) @@ -346,4 +366,40 @@ TestCase { verify(container.group.checkedButton) compare(container.group.checkedButton.objectName, "0") } + + function test_nonExclusive() { + var group = createTemporaryObject(nonExclusiveGroup, testCase) + verify(group) + + var button1 = createTemporaryObject(button, testCase, {checked: true}) + group.addButton(button1) + compare(button1.checked, true) + compare(group.checkedButton, null) + + var button2 = createTemporaryObject(button, testCase, {checked: true}) + group.addButton(button2) + compare(button1.checked, true) + compare(button2.checked, true) + compare(group.checkedButton, null) + + button1.checked = false + compare(button1.checked, false) + compare(button2.checked, true) + compare(group.checkedButton, null) + + button2.checked = false + compare(button1.checked, false) + compare(button2.checked, false) + compare(group.checkedButton, null) + + button1.checked = true + compare(button1.checked, true) + compare(button2.checked, false) + compare(group.checkedButton, null) + + button2.checked = true + compare(button1.checked, true) + compare(button2.checked, true) + compare(group.checkedButton, null) + } } |