Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qquickspinbox.cpp
Go to the documentation of this file.
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
// Qt-Security score:significant reason:default
4
5
#
include
"qquickspinbox_p.h"
6
7
#
include
<
private
/
qquickcontrol_p_p
.
h
>
8
#
include
<
private
/
qquickindicatorbutton_p
.
h
>
9
#
include
<
private
/
qquicktextinput_p
.
h
>
10
11
#
include
<
private
/
qqmlengine_p
.
h
>
12
13
#
include
<
QtQml
/
qqmlinfo
.
h
>
14
15
QT_BEGIN_NAMESPACE
16
17
/*!
18
\qmltype SpinBox
19
\inherits Control
20
//! \nativetype QQuickSpinBox
21
\inqmlmodule QtQuick.Controls
22
\since 5.7
23
\ingroup qtquickcontrols-input
24
\ingroup qtquickcontrols-focusscopes
25
\brief Allows the user to select from a set of preset values.
26
27
\image qtquickcontrols-spinbox.png
28
{Spin box with numeric value and buttons}
29
30
SpinBox allows the user to choose an integer value by clicking the up
31
or down indicator buttons, or by pressing up or down on the keyboard.
32
Optionally, SpinBox can be also made \l editable, so the user can enter
33
a text value in the input field.
34
35
By default, SpinBox provides discrete values in the range of \c [0-99]
36
with a \l stepSize of \c 1.
37
38
\snippet qtquickcontrols-spinbox.qml 1
39
40
For floating point values, use \l DoubleSpinBox.
41
42
\section2 Custom Values
43
44
\image qtquickcontrols-spinbox-textual.png
45
{Spin box displaying textual values}
46
47
Even though SpinBox works on integer values, it can be customized to
48
accept arbitrary input values. The following snippet demonstrates how
49
\l validator, \l textFromValue and \l valueFromText can be used to
50
customize the default behavior.
51
52
\snippet qtquickcontrols-spinbox-textual.qml 1
53
54
A prefix and suffix can be added using regular expressions:
55
56
\snippet qtquickcontrols-spinbox-prefix.qml 1
57
58
\sa Tumbler, {Customizing SpinBox}, {Focus Management in Qt Quick Controls},
59
{DoubleSpinBox}
60
*/
61
62
/*!
63
\since QtQuick.Controls 2.2 (Qt 5.9)
64
\include qquickspinbox.qdocinc {valueModified} {SpinBox}
65
*/
66
67
class
QQuickSpinBoxPrivate
68
:
public
QQuickAbstractSpinBox
<
QQuickSpinBox
,
int
>::
QQuickAbstractSpinBoxPrivate
69
{
70
Q_DECLARE_PUBLIC(QQuickSpinBox)
71
72
public
:
73
QQuickSpinBoxPrivate
();
74
75
bool
setValue
(
int
newValue,
bool
wrap, ValueStatus modified)
override
;
76
77
void
updateValue
()
override
;
78
void
updateDisplayText
()
override
;
79
80
void
contentItemTextChanged
();
81
82
QString
evaluateTextFromValue
(
int
val)
const
;
83
int
evaluateValueFromText
(
const
QString &text)
const
;
84
85
bool
live
=
false
;
86
87
private
:
88
friend
class
QQuickAbstractSpinBox
<
QQuickSpinBox
,
int
>::
QQuickAbstractSpinBoxPrivate
;
89
};
90
91
QQuickSpinBoxPrivate
::QQuickSpinBoxPrivate()
92
: QQuickAbstractSpinBox<QQuickSpinBox,
int
>::QQuickAbstractSpinBoxPrivate()
93
{
94
from = 0;
95
to = 99;
96
}
97
98
// modified indicates if the value was modified by the user and not programatically
99
// this is then passed on to updateDisplayText to indicate that the user has modified
100
// the value so it may need to trigger an update of the contentItem's text too
101
102
bool
QQuickSpinBoxPrivate
::
setValue
(
int
newValue,
bool
allowWrap, ValueStatus modified)
103
{
104
Q_Q(QQuickSpinBox);
105
int
correctedValue = newValue;
106
if
(q->isComponentComplete())
107
correctedValue = boundValue(newValue, allowWrap);
108
109
if
(modified == ValueStatus::Unmodified && newValue == correctedValue && newValue == value)
110
return
false
;
111
112
const
bool
emitSignals = (value != correctedValue);
113
value = correctedValue;
114
115
updateDisplayText
(
)
;
116
updateUpEnabled();
117
updateDownEnabled();
118
119
// Only emit the signals if the corrected value is not the same as the
120
// original value to avoid unnecessary updates
121
if
(emitSignals) {
122
emit q->valueChanged();
123
if
(modified == ValueStatus::Modified)
124
emit q->valueModified();
125
}
126
return
true
;
127
}
128
129
void
QQuickSpinBoxPrivate
::
updateValue
()
130
{
131
if
(!contentItem)
132
return
;
133
134
const
QVariant text = contentItem->property(
"text"
);
135
if
(text.isValid())
136
setValue(evaluateValueFromText(text.toString()),
false
/* wrap */
, ValueStatus::Modified);
137
}
138
139
void
QQuickSpinBoxPrivate
::
updateDisplayText
()
140
{
141
setDisplayText(evaluateTextFromValue(value));
142
}
143
144
void
QQuickSpinBoxPrivate
::
contentItemTextChanged
()
145
{
146
Q_Q(QQuickSpinBox);
147
148
QQuickTextInput *inputTextItem = qobject_cast<QQuickTextInput *>(q->contentItem());
149
if
(!inputTextItem)
150
return
;
151
QString text = inputTextItem->text();
152
#
if
QT_CONFIG
(
validator
)
153
if
(validator && live)
154
validator->fixup(text);
155
#
endif
156
157
if
(
live
) {
158
const
int
enteredVal = evaluateValueFromText(text);
159
const
int
correctedValue = boundValue(enteredVal,
false
);
160
if
(correctedValue == enteredVal && correctedValue != value) {
161
// If live is true and the text is valid change the value
162
// setValue will set the displayText for us.
163
q->setValue(correctedValue);
164
return
;
165
}
166
}
167
// If live is false or the value is not valid, just set the displayText
168
setDisplayText(text);
169
}
170
171
QString
QQuickSpinBoxPrivate
::
evaluateTextFromValue
(
int
val)
const
172
{
173
Q_Q(
const
QQuickSpinBox);
174
175
QString text;
176
QQmlEngine *engine = qmlEngine(q);
177
if
(engine && textFromValue.isCallable()) {
178
QJSValue loc;
179
#
if
QT_CONFIG
(
qml_locale
)
180
loc = QJSValuePrivate::fromReturnedValue(
181
engine->handle()->fromData(QMetaType::fromType<QLocale>(), &locale));
182
#
endif
183
text = textFromValue.call(QJSValueList() << val << loc).toString();
184
}
else
{
185
text = locale.toString(val);
186
}
187
return
text;
188
}
189
190
int
QQuickSpinBoxPrivate
::
evaluateValueFromText
(
const
QString &text)
const
191
{
192
Q_Q(
const
QQuickSpinBox);
193
int
value;
194
QQmlEngine *engine = qmlEngine(q);
195
if
(engine && valueFromText.isCallable()) {
196
QJSValue loc;
197
#
if
QT_CONFIG
(
qml_locale
)
198
loc = QJSValuePrivate::fromReturnedValue(
199
engine->handle()->fromData(QMetaType::fromType<QLocale>(), &locale));
200
#
endif
201
value = valueFromText.call(QJSValueList() << text << loc).toInt();
202
}
else
{
203
value = locale.toInt(text);
204
}
205
return
value;
206
}
207
208
QQuickSpinBox::QQuickSpinBox(QQuickItem *parent)
209
: QQuickControl(*(
new
QQuickSpinBoxPrivate), parent),
210
QQuickAbstractSpinBox<QQuickSpinBox,
int
>()
211
{
212
}
213
214
QQuickSpinBox::~QQuickSpinBox()
215
{
216
217
}
218
219
/*!
220
\include qquickspinbox.qdocinc {from} {int} {SpinBox} {0}
221
*/
222
223
void
QQuickSpinBox::setFrom(
int
from)
224
{
225
Q_D(QQuickSpinBox);
226
if
(d->from == from)
227
return
;
228
229
d->from = from;
230
emit fromChanged();
231
if
(isComponentComplete()) {
232
if
(!d->setValue(d->value,
233
/* allowWrap = */
false
, QQuickSpinBoxPrivate::ValueStatus::Unmodified)) {
234
d->updateUpEnabled();
235
d->updateDownEnabled();
236
}
237
}
238
}
239
240
/*!
241
\include qquickspinbox.qdocinc {to} {int} {SpinBox} {99}
242
*/
243
244
void
QQuickSpinBox::setTo(
int
to)
245
{
246
Q_D(QQuickSpinBox);
247
if
(d->to == to)
248
return
;
249
250
d->to = to;
251
emit toChanged();
252
if
(isComponentComplete()) {
253
if
(!d->setValue(d->value,
254
/* allowWrap = */
false
, QQuickSpinBoxPrivate::ValueStatus::Unmodified)) {
255
d->updateUpEnabled();
256
d->updateDownEnabled();
257
}
258
}
259
}
260
261
/*!
262
\include qquickspinbox.qdocinc {value-prop} {int} {SpinBox} {0}
263
*/
264
265
void
QQuickSpinBox::setValue(
int
value)
266
{
267
Q_D(QQuickSpinBox);
268
d->setValue(value,
false
/* wrap */
, QQuickSpinBoxPrivate::ValueStatus::Unmodified);
269
}
270
271
/*!
272
\include qquickspinbox.qdocinc {stepSize} {int} {SpinBox} {1}
273
*/
274
275
void
QQuickSpinBox::setStepSize(
int
step)
276
{
277
Q_D(QQuickSpinBox);
278
if
(d->stepSize == step)
279
return
;
280
281
d->stepSize = step;
282
emit stepSizeChanged();
283
}
284
285
/*!
286
\include qquickspinbox.qdocinc {editable} {SpinBox}
287
*/
288
289
/*!
290
\qmlproperty bool QtQuick.Controls::SpinBox::live
291
\since 6.6
292
293
This property holds whether the \l value is updated when the user edits the
294
\l displayText. The default value is \c false. If this property is \c true and
295
the value entered by the user is valid and within the bounds of the spinbox
296
[\l from, \l to], the value of the SpinBox will be set. If this property is
297
\c false or the value entered by the user is outside the boundaries, the
298
value will not be updated until the enter or return keys are pressed, or the
299
input field loses focus.
300
301
\sa editable, displayText
302
*/
303
bool
QQuickSpinBox::isLive()
const
304
{
305
Q_D(
const
QQuickSpinBox);
306
return
d->live;
307
}
308
309
void
QQuickSpinBox::setLive(
bool
live)
310
{
311
Q_D(QQuickSpinBox);
312
if
(d->live == live)
313
return
;
314
315
d->live = live;
316
317
//make sure to update the value when changing to live
318
if
(live)
319
d->contentItemTextChanged();
320
321
emit liveChanged();
322
}
323
324
#
if
QT_CONFIG
(
validator
)
325
/*!
326
\qmlproperty Validator QtQuick.Controls::SpinBox::validator
327
328
This property holds the input text validator for editable spinboxes. By
329
default, SpinBox uses \l IntValidator to accept input of integer numbers.
330
331
\code
332
SpinBox {
333
id: control
334
validator: IntValidator {
335
locale: control.locale.name
336
bottom: Math.min(control.from, control.to)
337
top: Math.max(control.from, control.to)
338
}
339
}
340
\endcode
341
342
\sa editable, textFromValue, valueFromText, {Control::locale}{locale},
343
{Validating Input Text}
344
*/
345
#
endif
346
347
/*!
348
\qmlproperty function QtQuick.Controls::SpinBox::textFromValue
349
350
This property holds a callback function that is called whenever
351
an integer value needs to be converted to display text.
352
353
The default function can be overridden to display custom text for a given
354
value. This applies to both editable and non-editable spinboxes;
355
for example, when using the up and down buttons or a mouse wheel to
356
increment and decrement the value, the new value is converted to display
357
text using this function.
358
359
The callback function signature is \c {string function(value, locale)}.
360
The function can have one or two arguments, where the first argument
361
is the value to be converted, and the optional second argument is the
362
locale that should be used for the conversion, if applicable.
363
364
The default implementation does the conversion using
365
\l {string Number::toLocaleString(locale, format, precision)}{Number.toLocaleString}():
366
367
\code
368
textFromValue: function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }
369
\endcode
370
371
\note When applying a custom \c textFromValue implementation for editable
372
spinboxes, a matching \l valueFromText implementation must be provided
373
to be able to convert the custom text back to an integer value.
374
375
\sa valueFromText, validator, {Control::locale}{locale}
376
*/
377
QJSValue QQuickSpinBox::textFromValue()
const
378
{
379
Q_D(
const
QQuickSpinBox);
380
if
(!d->textFromValue.isCallable()) {
381
QQmlEngine *engine = qmlEngine(
this
);
382
if
(engine)
383
d->textFromValue = engine->evaluate(QStringLiteral(
"(function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); })"
));
384
}
385
return
d->textFromValue;
386
}
387
388
/*!
389
\qmlproperty function QtQuick.Controls::SpinBox::valueFromText
390
391
This property holds a callback function that is called whenever
392
input text needs to be converted to an integer value.
393
394
This function only needs to be overridden when \l textFromValue
395
is overridden for an editable spinbox.
396
397
The callback function signature is \c {int function(text, locale)}.
398
The function can have one or two arguments, where the first argument
399
is the text to be converted, and the optional second argument is the
400
locale that should be used for the conversion, if applicable.
401
402
The default implementation does the conversion using \l {QtQml::Locale}{Number.fromLocaleString()}:
403
404
\code
405
valueFromText: function(text, locale) { return Number.fromLocaleString(locale, text); }
406
\endcode
407
408
\note When applying a custom \l textFromValue implementation for editable
409
spinboxes, a matching \c valueFromText implementation must be provided
410
to be able to convert the custom text back to an integer value.
411
412
\sa textFromValue, validator, {Control::locale}{locale}
413
*/
414
QJSValue QQuickSpinBox::valueFromText()
const
415
{
416
Q_D(
const
QQuickSpinBox);
417
if
(!d->valueFromText.isCallable()) {
418
QQmlEngine *engine = qmlEngine(
this
);
419
if
(engine)
420
d->valueFromText = engine->evaluate(QStringLiteral(
"(function(text, locale) { return Number.fromLocaleString(locale, text); })"
));
421
}
422
return
d->valueFromText;
423
}
424
425
/*!
426
\include qquickindicatorbutton.qdocinc {properties} {SpinBox} {up}
427
428
\include qquickspinbox.qdocinc {indicator-enabled} {SpinBox} {up} {to}
429
430
The \c up.hovered property was introduced in \l{QtQuick.Controls} 2.1,
431
and the \c up.implicitIndicatorWidth and \c up.implicitIndicatorHeight
432
properties were introduced in \l{QtQuick.Controls} 2.5.
433
434
\sa increase()
435
*/
436
437
/*!
438
\include qquickindicatorbutton.qdocinc {properties} {SpinBox} {down}
439
440
\include qquickspinbox.qdocinc {indicator-enabled} {SpinBox} {down} {from}
441
442
The \c down.hovered property was introduced in \l{QtQuick.Controls} 2.1,
443
and the \c down.implicitIndicatorWidth and \c down.implicitIndicatorHeight
444
properties were introduced in \l{QtQuick.Controls} 2.5.
445
446
\sa decrease()
447
*/
448
449
/*!
450
\since QtQuick.Controls 2.2 (Qt 5.9)
451
\include qquickspinbox.qdocinc {inputMethodHints} {SpinBox}
452
*/
453
454
/*!
455
\since QtQuick.Controls 2.2 (Qt 5.9)
456
\include qquickspinbox.qdocinc {inputMethodComposing} {SpinBox}
457
*/
458
459
/*!
460
\since QtQuick.Controls 2.3 (Qt 5.10)
461
\include qquickspinbox.qdocinc {wrap} {SpinBox}
462
*/
463
464
void
QQuickSpinBox::setWrap(
bool
wrap)
465
{
466
Q_D(QQuickSpinBox);
467
if
(d->wrap == wrap)
468
return
;
469
470
d->wrap = wrap;
471
if
(d->value == d->from || d->value == d->to) {
472
d->updateUpEnabled();
473
d->updateDownEnabled();
474
}
475
emit wrapChanged();
476
}
477
478
/*!
479
\since QtQuick.Controls 2.4 (Qt 5.11)
480
\qmlproperty string QtQuick.Controls::SpinBox::displayText
481
\readonly
482
483
This property holds the textual value of the spinbox.
484
485
The value of the property is based on \l textFromValue and \l {Control::}
486
{locale}, and equal to:
487
\badcode
488
var text = spinBox.textFromValue(spinBox.value, spinBox.locale)
489
\endcode
490
491
\sa textFromValue
492
*/
493
494
/*!
495
\include qquickspinbox.qdocinc {increase} {SpinBox}
496
*/
497
498
void
QQuickSpinBox::increase()
499
{
500
QQuickAbstractSpinBox<QQuickSpinBox,
int
>::increase();
501
}
502
503
/*!
504
\include qquickspinbox.qdocinc {decrease} {SpinBox}
505
*/
506
507
void
QQuickSpinBox::decrease()
508
{
509
QQuickAbstractSpinBox<QQuickSpinBox,
int
>::decrease();
510
}
511
512
void
QQuickSpinBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
513
{
514
Q_D(QQuickSpinBox);
515
if
(QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem)) {
516
disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged,
this
, &QQuickSpinBox::inputMethodComposingChanged);
517
QObjectPrivate::disconnect(oldInput, &QQuickTextInput::textChanged, d, &QQuickSpinBoxPrivate::contentItemTextChanged);
518
}
519
520
if
(newItem) {
521
newItem->setActiveFocusOnTab(
true
);
522
if
(d->activeFocus)
523
newItem->forceActiveFocus(
static_cast
<Qt::FocusReason>(d->focusReason));
524
#
if
QT_CONFIG
(
cursor
)
525
if
(d->editable)
526
newItem->setCursor(Qt::IBeamCursor);
527
#
endif
528
529
if
(QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem)) {
530
connect(newInput, &QQuickTextInput::inputMethodComposingChanged,
this
, &QQuickSpinBox::inputMethodComposingChanged);
531
QObjectPrivate::connect(newInput, &QQuickTextInput::textChanged, d, &QQuickSpinBoxPrivate::contentItemTextChanged);
532
}
533
}
534
}
535
536
QQuickControlPrivate *QQuickSpinBox::d_base_func()
537
{
538
Q_D(QQuickSpinBox);
539
return
d;
540
}
541
const
QQuickControlPrivate *QQuickSpinBox::d_base_func()
const
542
{
543
Q_D(
const
QQuickSpinBox);
544
return
d;
545
}
546
547
QT_END_NAMESPACE
548
549
#
include
"moc_qquickspinbox_p.cpp"
QQuickSpinBoxPrivate
Allows the user to select from a set of preset values.
Definition
qquickspinbox.cpp:69
QQuickSpinBoxPrivate::contentItemTextChanged
void contentItemTextChanged()
Definition
qquickspinbox.cpp:144
QQuickSpinBoxPrivate::evaluateValueFromText
int evaluateValueFromText(const QString &text) const
Definition
qquickspinbox.cpp:190
QQuickSpinBoxPrivate::setValue
bool setValue(int newValue, bool wrap, ValueStatus modified) override
Definition
qquickspinbox.cpp:102
QQuickSpinBoxPrivate::live
bool live
Definition
qquickspinbox.cpp:85
QQuickSpinBoxPrivate::evaluateTextFromValue
QString evaluateTextFromValue(int val) const
Definition
qquickspinbox.cpp:171
QQuickSpinBoxPrivate::updateValue
void updateValue() override
Definition
qquickspinbox.cpp:129
QQuickSpinBoxPrivate::updateDisplayText
void updateDisplayText() override
Definition
qquickspinbox.cpp:139
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtdeclarative
src
quicktemplates
qquickspinbox.cpp
Generated on
for Qt by
1.18.0