1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickcheckdelegate_p.h"
5#include "qquickitemdelegate_p_p.h"
6
7#include <QtGui/qpa/qplatformtheme.h>
8#include <QtQml/qjsvalue.h>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \qmltype CheckDelegate
14 \inherits ItemDelegate
15//! \instantiates QQuickCheckDelegate
16 \inqmlmodule QtQuick.Controls
17 \since 5.7
18 \ingroup qtquickcontrols-delegates
19 \brief Item delegate with a check indicator that can be toggled on or off.
20
21 \image qtquickcontrols-checkdelegate.gif
22
23 CheckDelegate presents an item delegate that can be toggled on (checked) or
24 off (unchecked). Check delegates are typically used to select one or more
25 options from a set of options in a list. For smaller sets of options, or
26 for options that need to be uniquely identifiable, consider using
27 \l CheckBox instead.
28
29 CheckDelegate inherits its API from \l ItemDelegate, which is inherited
30 from AbstractButton. For instance, you can set \l {AbstractButton::text}{text},
31 and react to \l {AbstractButton::clicked}{clicks} using the AbstractButton
32 API. The state of the check delegate can be set with the
33 \l {AbstractButton::}{checked} property.
34
35 In addition to the checked and unchecked states, there is a third state:
36 partially checked. The partially checked state can be enabled using the
37 \l tristate property. This state indicates that the regular checked/unchecked
38 state can not be determined; generally because of other states that affect
39 the check delegate. This state is useful when several child nodes are selected
40 in a treeview, for example.
41
42 \code
43 ListView {
44 model: ["Option 1", "Option 2", "Option 3"]
45 delegate: CheckDelegate {
46 text: modelData
47 }
48 }
49 \endcode
50
51 \sa {Customizing CheckDelegate}, {Delegate Controls}, CheckBox
52*/
53
54class QQuickCheckDelegatePrivate : public QQuickItemDelegatePrivate
55{
56 Q_DECLARE_PUBLIC(QQuickCheckDelegate)
57
58public:
59 void setNextCheckState(const QJSValue &callback);
60
61 QPalette defaultPalette() const override { return QQuickTheme::palette(scope: QQuickTheme::ListView); }
62
63 bool tristate = false;
64 Qt::CheckState checkState = Qt::Unchecked;
65 QJSValue nextCheckState;
66};
67
68void QQuickCheckDelegatePrivate::setNextCheckState(const QJSValue &callback)
69{
70 Q_Q(QQuickCheckDelegate);
71 nextCheckState = callback;
72 emit q->nextCheckStateChanged();
73}
74
75QQuickCheckDelegate::QQuickCheckDelegate(QQuickItem *parent)
76 : QQuickItemDelegate(*(new QQuickCheckDelegatePrivate), parent)
77{
78 setCheckable(true);
79}
80
81/*!
82 \qmlproperty bool QtQuick.Controls::CheckDelegate::tristate
83
84 This property determines whether the check delegate has three states.
85
86 In the animation below, the first checkdelegate is tri-state:
87
88 \image qtquickcontrols-checkdelegate-tristate.gif
89
90 The default is \c false, i.e., the delegate has only two states.
91*/
92bool QQuickCheckDelegate::isTristate() const
93{
94 Q_D(const QQuickCheckDelegate);
95 return d->tristate;
96}
97
98void QQuickCheckDelegate::setTristate(bool tristate)
99{
100 Q_D(QQuickCheckDelegate);
101 if (d->tristate == tristate)
102 return;
103
104 d->tristate = tristate;
105 emit tristateChanged();
106}
107
108/*!
109 \qmlproperty enumeration QtQuick.Controls::CheckDelegate::checkState
110
111 This property determines the check state of the check delegate.
112
113 Available states:
114 \value Qt.Unchecked The delegate is unchecked.
115 \value Qt.PartiallyChecked The delegate is partially checked. This state is only used when \l tristate is enabled.
116 \value Qt.Checked The delegate is checked.
117
118 \sa tristate, {AbstractButton::checked}{checked}
119*/
120Qt::CheckState QQuickCheckDelegate::checkState() const
121{
122 Q_D(const QQuickCheckDelegate);
123 return d->checkState;
124}
125
126void QQuickCheckDelegate::setCheckState(Qt::CheckState state)
127{
128 Q_D(QQuickCheckDelegate);
129 if (d->checkState == state)
130 return;
131
132 bool wasChecked = isChecked();
133 d->checked = state == Qt::Checked;
134 d->checkState = state;
135 emit checkStateChanged();
136 if (d->checked != wasChecked)
137 emit checkedChanged();
138}
139
140QFont QQuickCheckDelegate::defaultFont() const
141{
142 return QQuickTheme::font(scope: QQuickTheme::ListView);
143}
144
145void QQuickCheckDelegate::buttonChange(ButtonChange change)
146{
147 if (change == ButtonCheckedChange)
148 setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
149 else
150 QQuickAbstractButton::buttonChange(change);
151}
152
153/*!
154 \since QtQuick.Controls 2.4 (Qt 5.11)
155 \qmlproperty function QtQuick.Controls::CheckDelegate::nextCheckState
156
157 This property holds a callback function that is called to determine
158 the next check state whenever the check delegate is interactively toggled
159 by the user via touch, mouse, or keyboard.
160
161 By default, a normal check delegate cycles between \c Qt.Unchecked and
162 \c Qt.Checked states, and a tri-state check delegate cycles between
163 \c Qt.Unchecked, \c Qt.PartiallyChecked, and \c Qt.Checked states.
164
165 The \c nextCheckState callback function can override the default behavior.
166 The following example implements a tri-state check delegate that can present
167 a partially checked state depending on external conditions, but never
168 cycles to the partially checked state when interactively toggled by
169 the user.
170
171 \code
172 CheckDelegate {
173 tristate: true
174 checkState: allChildrenChecked ? Qt.Checked :
175 anyChildChecked ? Qt.PartiallyChecked : Qt.Unchecked
176
177 nextCheckState: function() {
178 if (checkState === Qt.Checked)
179 return Qt.Unchecked
180 else
181 return Qt.Checked
182 }
183 }
184 \endcode
185*/
186void QQuickCheckDelegate::nextCheckState()
187{
188 Q_D(QQuickCheckDelegate);
189 if (d->nextCheckState.isCallable())
190 setCheckState(static_cast<Qt::CheckState>(d->nextCheckState.call().toInt()));
191 else if (d->tristate)
192 setCheckState(static_cast<Qt::CheckState>((d->checkState + 1) % 3));
193 else
194 QQuickItemDelegate::nextCheckState();
195}
196
197#if QT_CONFIG(accessibility)
198QAccessible::Role QQuickCheckDelegate::accessibleRole() const
199{
200 return QAccessible::CheckBox;
201}
202#endif
203
204QT_END_NAMESPACE
205
206#include "moc_qquickcheckdelegate_p.cpp"
207

source code of qtdeclarative/src/quicktemplates/qquickcheckdelegate.cpp