SpinBox: add validator, textFromValue and valueFromText
Change-Id: I45e01199453ac5fd64b7f98c165cc12eeb0ce8c3 Task-number: QTBUG-48989 Reviewed-by: Mitch Curtis <mitch.curtis@theqtcompany.com> Reviewed-by: Nikita Krupenko <krnekit@gmail.com>
This commit is contained in:
parent
e4721fa68c
commit
cf67efa1ea
|
@ -54,9 +54,17 @@ T.SpinBox {
|
|||
leftPadding: 6 + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0))
|
||||
rightPadding: 6 + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0))
|
||||
|
||||
//! [validator]
|
||||
validator: IntValidator {
|
||||
locale: control.locale.name
|
||||
bottom: Math.min(control.from, control.to)
|
||||
top: Math.max(control.from, control.to)
|
||||
}
|
||||
//! [validator]
|
||||
|
||||
//! [contentItem]
|
||||
contentItem: TextInput {
|
||||
text: Number(control.value).toLocaleString(control.locale, 'f', 0)
|
||||
text: control.textFromValue(control.value, control.locale)
|
||||
|
||||
font: control.font
|
||||
color: control.Theme.textColor
|
||||
|
@ -65,10 +73,7 @@ T.SpinBox {
|
|||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
|
||||
validator: IntValidator {
|
||||
bottom: Math.min(control.from, control.to)
|
||||
top: Math.max(control.from, control.to)
|
||||
}
|
||||
validator: control.validator
|
||||
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
||||
}
|
||||
//! [contentItem]
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -40,6 +40,10 @@
|
|||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qstylehints.h>
|
||||
|
||||
#include <QtQml/qqmlinfo.h>
|
||||
#include <QtQml/private/qqmllocale_p.h>
|
||||
#include <QtQml/private/qqmlengine_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// copied from qabstractbutton.cpp
|
||||
|
@ -65,6 +69,17 @@ static const int AUTO_REPEAT_INTERVAL = 100;
|
|||
|
||||
\snippet qtlabscontrols-spinbox.qml 1
|
||||
|
||||
\section2 Custom Values
|
||||
|
||||
\image qtlabscontrols-spinbox-textual.png
|
||||
|
||||
Even though SpinBox works on integer values, it can be customized to
|
||||
accept arbitrary input values. The following snippet demonstrates how
|
||||
\l validator, \l textFromValue and \l valueFromText can be used to
|
||||
customize the default behavior.
|
||||
|
||||
\snippet qtlabscontrols-spinbox-textual.qml 1
|
||||
|
||||
\sa Tumbler, {Customizing SpinBox}
|
||||
*/
|
||||
|
||||
|
@ -74,7 +89,7 @@ class QQuickSpinBoxPrivate : public QQuickControlPrivate
|
|||
|
||||
public:
|
||||
QQuickSpinBoxPrivate() : from(0), to(99), value(0), stepSize(1),
|
||||
delayTimer(0), repeatTimer(0), up(Q_NULLPTR), down(Q_NULLPTR) { }
|
||||
delayTimer(0), repeatTimer(0), up(Q_NULLPTR), down(Q_NULLPTR), validator(Q_NULLPTR) { }
|
||||
|
||||
int boundValue(int value) const;
|
||||
void updateValue();
|
||||
|
@ -99,6 +114,9 @@ public:
|
|||
QQuickSpinner *up;
|
||||
QQuickSpinner *down;
|
||||
QLocale locale;
|
||||
QValidator *validator;
|
||||
QJSValue textFromValue;
|
||||
QJSValue valueFromText;
|
||||
};
|
||||
|
||||
int QQuickSpinBoxPrivate::boundValue(int value) const
|
||||
|
@ -111,8 +129,12 @@ void QQuickSpinBoxPrivate::updateValue()
|
|||
Q_Q(QQuickSpinBox);
|
||||
if (contentItem) {
|
||||
QVariant text = contentItem->property("text");
|
||||
if (text.isValid())
|
||||
q->setValue(locale.toInt(text.toString()));
|
||||
if (text.isValid()) {
|
||||
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(qmlEngine(q));
|
||||
QJSValue loc(v4, QQmlLocale::wrap(v4, locale));
|
||||
QJSValue val = valueFromText.call(QJSValueList() << text.toString() << loc);
|
||||
q->setValue(val.toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,6 +356,103 @@ void QQuickSpinBox::setLocale(const QLocale &locale)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty Validator Qt.labs.controls::SpinBox::validator
|
||||
|
||||
This property holds the input text validator. By default, SpinBox uses
|
||||
\l IntValidator to accept input of integer numbers.
|
||||
|
||||
\snippet SpinBox.qml validator
|
||||
|
||||
\sa textFromValue, valueFromText, locale
|
||||
*/
|
||||
QValidator *QQuickSpinBox::validator() const
|
||||
{
|
||||
Q_D(const QQuickSpinBox);
|
||||
return d->validator;
|
||||
}
|
||||
|
||||
void QQuickSpinBox::setValidator(QValidator *validator)
|
||||
{
|
||||
Q_D(QQuickSpinBox);
|
||||
if (d->validator != validator) {
|
||||
d->validator = validator;
|
||||
emit validatorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty function Qt.labs.controls::SpinBox::textFromValue
|
||||
|
||||
This property holds a callback function that is called whenever
|
||||
an integer value needs to be converted to display text.
|
||||
|
||||
The callback function signature is \c {string function(value, locale)}.
|
||||
The function can have one or two arguments, where the first argument
|
||||
is the value to be converted, and the optional second argument is the
|
||||
locale that should be used for the conversion, if applicable.
|
||||
|
||||
The default implementation does the conversion using \l {QtQml::Locale}{Number.toLocaleString()}:
|
||||
|
||||
\code
|
||||
textFromValue: function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }
|
||||
\endcode
|
||||
|
||||
\sa valueFromText, validator, locale
|
||||
*/
|
||||
QJSValue QQuickSpinBox::textFromValue() const
|
||||
{
|
||||
Q_D(const QQuickSpinBox);
|
||||
return d->textFromValue;
|
||||
}
|
||||
|
||||
void QQuickSpinBox::setTextFromValue(const QJSValue &callback)
|
||||
{
|
||||
Q_D(QQuickSpinBox);
|
||||
if (!callback.isCallable()) {
|
||||
qmlInfo(this) << "textFromValue must be a callable function";
|
||||
return;
|
||||
}
|
||||
d->textFromValue = callback;
|
||||
emit textFromValueChanged();
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlproperty function Qt.labs.controls::SpinBox::valueFromText
|
||||
|
||||
This property holds a callback function that is called whenever
|
||||
input text needs to be converted to an integer value.
|
||||
|
||||
The callback function signature is \c {int function(text, locale)}.
|
||||
The function can have one or two arguments, where the first argument
|
||||
is the text to be converted, and the optional second argument is the
|
||||
locale that should be used for the conversion, if applicable.
|
||||
|
||||
The default implementation does the conversion using \l {QtQml::Locale}{Number.fromLocaleString()}:
|
||||
|
||||
\code
|
||||
valueFromText: function(text, locale) { return Number.fromLocaleString(locale, text); }
|
||||
\endcode
|
||||
|
||||
\sa textFromValue, validator, locale
|
||||
*/
|
||||
QJSValue QQuickSpinBox::valueFromText() const
|
||||
{
|
||||
Q_D(const QQuickSpinBox);
|
||||
return d->valueFromText;
|
||||
}
|
||||
|
||||
void QQuickSpinBox::setValueFromText(const QJSValue &callback)
|
||||
{
|
||||
Q_D(QQuickSpinBox);
|
||||
if (!callback.isCallable()) {
|
||||
qmlInfo(this) << "valueFromText must be a callable function";
|
||||
return;
|
||||
}
|
||||
d->valueFromText = callback;
|
||||
emit valueFromTextChanged();
|
||||
}
|
||||
|
||||
/*!
|
||||
\qmlpropertygroup Qt.labs.controls::SpinBox::up
|
||||
\qmlproperty bool Qt.labs.controls::SpinBox::up.pressed
|
||||
|
@ -459,6 +578,19 @@ void QQuickSpinBox::timerEvent(QTimerEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void QQuickSpinBox::componentComplete()
|
||||
{
|
||||
Q_D(QQuickSpinBox);
|
||||
QQuickControl::componentComplete();
|
||||
QQmlEngine *engine = qmlEngine(this);
|
||||
if (engine) {
|
||||
if (!d->textFromValue.isCallable())
|
||||
setTextFromValue(engine->evaluate(QStringLiteral("function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }")));
|
||||
if (!d->valueFromText.isCallable())
|
||||
setValueFromText(engine->evaluate(QStringLiteral("function(text, locale) { return Number.fromLocaleString(locale, text); }")));
|
||||
}
|
||||
}
|
||||
|
||||
void QQuickSpinBox::itemChange(ItemChange change, const ItemChangeData &value)
|
||||
{
|
||||
Q_D(QQuickSpinBox);
|
||||
|
|
|
@ -49,9 +49,11 @@
|
|||
//
|
||||
|
||||
#include <QtLabsTemplates/private/qquickcontrol_p.h>
|
||||
#include <QtQml/qjsvalue.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QValidator;
|
||||
class QQuickSpinner;
|
||||
class QQuickSpinnerPrivate;
|
||||
class QQuickSpinBoxPrivate;
|
||||
|
@ -64,6 +66,9 @@ class Q_LABSTEMPLATES_EXPORT QQuickSpinBox : public QQuickControl
|
|||
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged FINAL)
|
||||
Q_PROPERTY(int stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
|
||||
Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged FINAL)
|
||||
Q_PROPERTY(QValidator *validator READ validator WRITE setValidator NOTIFY validatorChanged FINAL)
|
||||
Q_PROPERTY(QJSValue textFromValue READ textFromValue WRITE setTextFromValue NOTIFY textFromValueChanged FINAL)
|
||||
Q_PROPERTY(QJSValue valueFromText READ valueFromText WRITE setValueFromText NOTIFY valueFromTextChanged FINAL)
|
||||
Q_PROPERTY(QQuickSpinner *up READ up CONSTANT FINAL)
|
||||
Q_PROPERTY(QQuickSpinner *down READ down CONSTANT FINAL)
|
||||
|
||||
|
@ -85,6 +90,15 @@ public:
|
|||
QLocale locale() const;
|
||||
void setLocale(const QLocale &locale);
|
||||
|
||||
QValidator *validator() const;
|
||||
void setValidator(QValidator *validator);
|
||||
|
||||
QJSValue textFromValue() const;
|
||||
void setTextFromValue(const QJSValue &callback);
|
||||
|
||||
QJSValue valueFromText() const;
|
||||
void setValueFromText(const QJSValue &callback);
|
||||
|
||||
QQuickSpinner *up() const;
|
||||
QQuickSpinner *down() const;
|
||||
|
||||
|
@ -98,6 +112,9 @@ Q_SIGNALS:
|
|||
void valueChanged();
|
||||
void stepSizeChanged();
|
||||
void localeChanged();
|
||||
void validatorChanged();
|
||||
void textFromValueChanged();
|
||||
void valueFromTextChanged();
|
||||
|
||||
protected:
|
||||
bool childMouseEventFilter(QQuickItem *child, QEvent *event) Q_DECL_OVERRIDE;
|
||||
|
@ -105,6 +122,7 @@ protected:
|
|||
void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
|
||||
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
void componentComplete() Q_DECL_OVERRIDE;
|
||||
void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
|
||||
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import QtQuick 2.0
|
||||
import Qt.labs.controls 1.0
|
||||
|
||||
//! [1]
|
||||
SpinBox {
|
||||
from: 0
|
||||
to: items.length - 1
|
||||
value: 1 // "Medium"
|
||||
|
||||
property var items: ["Small", "Medium", "Large"]
|
||||
|
||||
validator: RegExpValidator {
|
||||
regExp: new RegExp("(Small|Medium|Large)", "i")
|
||||
}
|
||||
|
||||
textFromValue: function(value) {
|
||||
return items[value];
|
||||
}
|
||||
|
||||
valueFromText: function(text) {
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
if (items[i].toLowerCase().indexOf(text.toLowerCase()) === 0)
|
||||
return i
|
||||
}
|
||||
return sb.value
|
||||
}
|
||||
}
|
||||
//! [1]
|
Loading…
Reference in New Issue