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 | |
10 | QT_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 | |
54 | class QQuickCheckDelegatePrivate : public QQuickItemDelegatePrivate |
55 | { |
56 | Q_DECLARE_PUBLIC(QQuickCheckDelegate) |
57 | |
58 | public: |
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 | |
68 | void QQuickCheckDelegatePrivate::setNextCheckState(const QJSValue &callback) |
69 | { |
70 | Q_Q(QQuickCheckDelegate); |
71 | nextCheckState = callback; |
72 | emit q->nextCheckStateChanged(); |
73 | } |
74 | |
75 | QQuickCheckDelegate::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 | */ |
92 | bool QQuickCheckDelegate::isTristate() const |
93 | { |
94 | Q_D(const QQuickCheckDelegate); |
95 | return d->tristate; |
96 | } |
97 | |
98 | void 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 | */ |
120 | Qt::CheckState QQuickCheckDelegate::checkState() const |
121 | { |
122 | Q_D(const QQuickCheckDelegate); |
123 | return d->checkState; |
124 | } |
125 | |
126 | void 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 | |
140 | QFont QQuickCheckDelegate::defaultFont() const |
141 | { |
142 | return QQuickTheme::font(scope: QQuickTheme::ListView); |
143 | } |
144 | |
145 | void 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 | */ |
186 | void 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) |
198 | QAccessible::Role QQuickCheckDelegate::accessibleRole() const |
199 | { |
200 | return QAccessible::CheckBox; |
201 | } |
202 | #endif |
203 | |
204 | QT_END_NAMESPACE |
205 | |
206 | #include "moc_qquickcheckdelegate_p.cpp" |
207 | |