From 06b31b60fe3210d55d978205b1fa302feda5d819 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 12 Jun 2018 12:08:12 +0200 Subject: TextArea, TextField: use the control's renderType in placeholder text The placeholder text's renderType should cohere to the renderType of the control. This is already the case for font, and sometimes color too. This solution avoids the need to expose a new property. Task-number: QTBUG-68769 Change-Id: I6711aea83b7b8ee27f56b9c905aa4870465e3fd9 Reviewed-by: Richard Moe Gustavsen --- src/imports/controls/TextArea.qml | 1 + src/imports/controls/TextField.qml | 1 + src/imports/controls/fusion/TextArea.qml | 1 + src/imports/controls/fusion/TextField.qml | 1 + src/imports/controls/imagine/TextArea.qml | 1 + src/imports/controls/imagine/TextField.qml | 1 + src/imports/controls/material/TextArea.qml | 1 + src/imports/controls/material/TextField.qml | 2 +- src/imports/controls/universal/TextArea.qml | 1 + src/imports/controls/universal/TextField.qml | 1 + 10 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/imports/controls/TextArea.qml b/src/imports/controls/TextArea.qml index 04a44eae..86dc7cbf 100644 --- a/src/imports/controls/TextArea.qml +++ b/src/imports/controls/TextArea.qml @@ -70,5 +70,6 @@ T.TextArea { verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight + renderType: control.renderType } } diff --git a/src/imports/controls/TextField.qml b/src/imports/controls/TextField.qml index 4b80d8be..d9b0046d 100644 --- a/src/imports/controls/TextField.qml +++ b/src/imports/controls/TextField.qml @@ -71,6 +71,7 @@ T.TextField { verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight + renderType: control.renderType } background: Rectangle { diff --git a/src/imports/controls/fusion/TextArea.qml b/src/imports/controls/fusion/TextArea.qml index 36d9db04..9165116c 100644 --- a/src/imports/controls/fusion/TextArea.qml +++ b/src/imports/controls/fusion/TextArea.qml @@ -72,5 +72,6 @@ T.TextArea { verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight + renderType: control.renderType } } diff --git a/src/imports/controls/fusion/TextField.qml b/src/imports/controls/fusion/TextField.qml index 2ea5c967..7b8984d2 100644 --- a/src/imports/controls/fusion/TextField.qml +++ b/src/imports/controls/fusion/TextField.qml @@ -72,6 +72,7 @@ T.TextField { verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight + renderType: control.renderType } background: Rectangle { diff --git a/src/imports/controls/imagine/TextArea.qml b/src/imports/controls/imagine/TextArea.qml index 9867a0bd..1e351ab8 100644 --- a/src/imports/controls/imagine/TextArea.qml +++ b/src/imports/controls/imagine/TextArea.qml @@ -74,6 +74,7 @@ T.TextArea { verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight + renderType: control.renderType opacity: 0.5 } diff --git a/src/imports/controls/imagine/TextField.qml b/src/imports/controls/imagine/TextField.qml index 17827b95..1782c1e2 100644 --- a/src/imports/controls/imagine/TextField.qml +++ b/src/imports/controls/imagine/TextField.qml @@ -74,6 +74,7 @@ T.TextField { verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight + renderType: control.renderType opacity: 0.5 } diff --git a/src/imports/controls/material/TextArea.qml b/src/imports/controls/material/TextArea.qml index 2dc64570..207d12c5 100644 --- a/src/imports/controls/material/TextArea.qml +++ b/src/imports/controls/material/TextArea.qml @@ -71,6 +71,7 @@ T.TextArea { color: control.Material.hintTextColor verticalAlignment: control.verticalAlignment elide: Text.ElideRight + renderType: control.renderType visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) } diff --git a/src/imports/controls/material/TextField.qml b/src/imports/controls/material/TextField.qml index 6ce905af..e8af67d4 100644 --- a/src/imports/controls/material/TextField.qml +++ b/src/imports/controls/material/TextField.qml @@ -72,8 +72,8 @@ T.TextField { color: control.Material.hintTextColor verticalAlignment: control.verticalAlignment elide: Text.ElideRight + renderType: control.renderType visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) - } background: Rectangle { diff --git a/src/imports/controls/universal/TextArea.qml b/src/imports/controls/universal/TextArea.qml index 5dc78c80..3e407160 100644 --- a/src/imports/controls/universal/TextArea.qml +++ b/src/imports/controls/universal/TextArea.qml @@ -76,6 +76,7 @@ T.TextArea { visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) verticalAlignment: control.verticalAlignment elide: Text.ElideRight + renderType: control.renderType } background: Rectangle { diff --git a/src/imports/controls/universal/TextField.qml b/src/imports/controls/universal/TextField.qml index f4164fed..0f3084ce 100644 --- a/src/imports/controls/universal/TextField.qml +++ b/src/imports/controls/universal/TextField.qml @@ -77,6 +77,7 @@ T.TextField { visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) verticalAlignment: control.verticalAlignment elide: Text.ElideRight + renderType: control.renderType } background: Rectangle { -- cgit v1.2.3 From 8551dab69a0f4c8248c4eedd7ab650e15a8969f8 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 13 Jun 2018 11:23:09 +0200 Subject: Document which modules are required when building from source There is currently no indication (in the form of build output) that the user is missing a required module when building from source. QTBUG-68826 suggests that such a feature be added, but until then, we need a way to inform users how to build from source. Task-number: QTBUG-68618 Change-Id: Ic17565aeaaff6aaa9907552d3b0c2646b407b425 Reviewed-by: Richard Moe Gustavsen --- src/imports/controls/doc/src/qtquickcontrols2-index.qdoc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc index 9b737939..87b170c2 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-index.qdoc @@ -65,6 +65,15 @@ For more details, see \l {Getting Started with Qt Quick Controls 2}. + \section2 Building From Source + + When building from source, ensure that the \l {Qt Graphical Effects} module + is also built, as Qt Quick Controls 2 requires it. + + The \l {Qt Image Formats} module is recommended, but not + required. It provides support for the \c {.webp} format used by the + \l {Animated Images}{Imagine style}. + \section1 Versions Qt Quick Controls 2.0 was introduced in Qt 5.7. Subsequent minor Qt releases -- cgit v1.2.3 From 4624ec51b2f1672b109dfec536230f3920bdbd36 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Mon, 11 Jun 2018 13:16:12 +0200 Subject: Fix Tumbler not respecting currentIndex changes in onModelChanged The use case in the referenced bug report looks something like this: Tumbler { model: 4 // ... onModelChanged: { currentIndex = model - 2; } } The problem was that setting currentIndex in onModelChanged would cause the wrap to change to true, which in turn caused the internal view to change to PathView. This would cause the currentIndex to be set to 0 on successive model changes (i.e ++model). By keeping track of whether or not the user set the currentIndex during a model change, we can ignore changes in the internal view's currentIndex and restore the user's currentIndex afterwards. Task-number: QTBUG-68737 Change-Id: I25738f36cf58a331d1b8e50b5029b4aa1dd27db5 Reviewed-by: Richard Moe Gustavsen --- src/quickcontrols2/qquicktumblerview.cpp | 6 +- src/quicktemplates2/qquicktumbler.cpp | 149 ++++++++++++++++++------------- src/quicktemplates2/qquicktumbler_p_p.h | 13 ++- 3 files changed, 100 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/quickcontrols2/qquicktumblerview.cpp b/src/quickcontrols2/qquicktumblerview.cpp index 59d05211..a510a1fe 100644 --- a/src/quickcontrols2/qquicktumblerview.cpp +++ b/src/quickcontrols2/qquicktumblerview.cpp @@ -221,9 +221,9 @@ void QQuickTumblerView::updateModel() // Since QQuickTumbler can't know about QQuickTumblerView, we use its private API to // inform it that it should delay setting wrap. QQuickTumblerPrivate *tumblerPrivate = QQuickTumblerPrivate::get(m_tumbler); - tumblerPrivate->lockWrap(); + tumblerPrivate->beginSetModel(); m_pathView->setModel(m_model); - tumblerPrivate->unlockWrap(); + tumblerPrivate->endSetModel(); // The count-depends-on-wrap behavior could cause wrap to change after // the call above, so we must check that we're still using a PathView. @@ -234,7 +234,7 @@ void QQuickTumblerView::updateModel() QQuickTumblerPrivate *tumblerPrivate = QQuickTumblerPrivate::get(m_tumbler); // setModel() causes QQuickTumblerPrivate::_q_onViewCountChanged() to - // be called called, which calls QQuickTumbler::setCurrentIndex(), + // be called, which calls QQuickTumbler::setCurrentIndex(), // which results in QQuickItemViewPrivate::createHighlightItem() being // called. When the highlight item is created, // QQuickTumblerPrivate::itemChildAdded() is notified and diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp index cc32a4e3..f6dbddbe 100644 --- a/src/quicktemplates2/qquicktumbler.cpp +++ b/src/quicktemplates2/qquicktumbler.cpp @@ -185,12 +185,17 @@ void QQuickTumblerPrivate::_q_updateItemWidths() void QQuickTumblerPrivate::_q_onViewCurrentIndexChanged() { Q_Q(QQuickTumbler); - if (view && !ignoreCurrentIndexChanges) { - const int oldCurrentIndex = currentIndex; - currentIndex = view->property("currentIndex").toInt(); - if (oldCurrentIndex != currentIndex) - emit q->currentIndexChanged(); + if (!view || ignoreCurrentIndexChanges || currentIndexSetDuringModelChange) { + // If the user set currentIndex in the onModelChanged handler, + // we have to respect that currentIndex by ignoring changes in the view + // until the model has finished being set. + return; } + + const int oldCurrentIndex = currentIndex; + currentIndex = view->property("currentIndex").toInt(); + if (oldCurrentIndex != currentIndex) + emit q->currentIndexChanged(); } void QQuickTumblerPrivate::_q_onViewCountChanged() @@ -205,7 +210,7 @@ void QQuickTumblerPrivate::_q_onViewCountChanged() if (pendingCurrentIndex != -1) { // If there was an attempt to set currentIndex at creation, try to finish that attempt now. // componentComplete() is too early, because the count might only be known sometime after completion. - q->setCurrentIndex(pendingCurrentIndex); + setCurrentIndex(pendingCurrentIndex); // If we could successfully set the currentIndex, consider it done. // Otherwise, we'll try again later in updatePolish(). if (currentIndex == pendingCurrentIndex) @@ -215,10 +220,10 @@ void QQuickTumblerPrivate::_q_onViewCountChanged() } else if (currentIndex == -1) { // If new items were added and our currentIndex was -1, we must // enforce our rule of a non-negative currentIndex when count > 0. - q->setCurrentIndex(0); + setCurrentIndex(0); } } else { - q->setCurrentIndex(-1); + setCurrentIndex(-1); } } @@ -297,17 +302,19 @@ void QQuickTumbler::setModel(const QVariant &model) if (model == d->model) return; - d->lockWrap(); + d->beginSetModel(); d->model = model; emit modelChanged(); - d->unlockWrap(); + d->endSetModel(); + + d->currentIndexSetDuringModelChange = false; // Don't try to correct the currentIndex if count() isn't known yet. // We can check in setupViewData() instead. if (isComponentComplete() && d->view && count() == 0) - setCurrentIndex(-1); + d->setCurrentIndex(-1); } /*! @@ -339,49 +346,9 @@ int QQuickTumbler::currentIndex() const void QQuickTumbler::setCurrentIndex(int currentIndex) { Q_D(QQuickTumbler); - if (currentIndex == d->currentIndex || currentIndex < -1) - return; - - if (!isComponentComplete()) { - // Views can't set currentIndex until they're ready. - d->pendingCurrentIndex = currentIndex; - return; - } - - // -1 doesn't make sense for a non-empty Tumbler, because unlike - // e.g. ListView, there's always one item selected. - // Wait until the component has finished before enforcing this rule, though, - // because the count might not be known yet. - if ((d->count > 0 && currentIndex == -1) || (currentIndex >= d->count)) { - return; - } - - // The view might not have been created yet, as is the case - // if you create a Tumbler component and pass e.g. { currentIndex: 2 } - // to createObject(). - if (d->view) { - // Only actually set our currentIndex if the view was able to set theirs. - bool couldSet = false; - if (d->count == 0 && currentIndex == -1) { - // PathView insists on using 0 as the currentIndex when there are no items. - couldSet = true; - } else { - d->ignoreCurrentIndexChanges = true; - d->ignoreSignals = true; - d->view->setProperty("currentIndex", currentIndex); - d->ignoreSignals = false; - d->ignoreCurrentIndexChanges = false; - - couldSet = d->view->property("currentIndex").toInt() == currentIndex; - } - - if (couldSet) { - // The view's currentIndex might not have actually changed, but ours has, - // and that's what user code sees. - d->currentIndex = currentIndex; - emit currentIndexChanged(); - } - } + if (d->modelBeingSet) + d->currentIndexSetDuringModelChange = true; + d->setCurrentIndex(currentIndex, QQuickTumblerPrivate::UserChange); } /*! @@ -643,6 +610,64 @@ void QQuickTumblerPrivate::syncCurrentIndex() q->polish(); } +void QQuickTumblerPrivate::setCurrentIndex(int newCurrentIndex, + QQuickTumblerPrivate::PropertyChangeReason changeReason) +{ + Q_Q(QQuickTumbler); + if (newCurrentIndex == currentIndex || newCurrentIndex < -1) + return; + + if (!q->isComponentComplete()) { + // Views can't set currentIndex until they're ready. + pendingCurrentIndex = newCurrentIndex; + return; + } + + if (modelBeingSet && changeReason == UserChange) { + // If modelBeingSet is true and the user set the currentIndex, + // the model is in the process of being set and the user has set + // the currentIndex in onModelChanged. We have to queue the currentIndex + // change until we're ready. + pendingCurrentIndex = newCurrentIndex; + return; + } + + // -1 doesn't make sense for a non-empty Tumbler, because unlike + // e.g. ListView, there's always one item selected. + // Wait until the component has finished before enforcing this rule, though, + // because the count might not be known yet. + if ((count > 0 && newCurrentIndex == -1) || (newCurrentIndex >= count)) { + return; + } + + // The view might not have been created yet, as is the case + // if you create a Tumbler component and pass e.g. { currentIndex: 2 } + // to createObject(). + if (view) { + // Only actually set our currentIndex if the view was able to set theirs. + bool couldSet = false; + if (count == 0 && newCurrentIndex == -1) { + // PathView insists on using 0 as the currentIndex when there are no items. + couldSet = true; + } else { + ignoreCurrentIndexChanges = true; + ignoreSignals = true; + view->setProperty("currentIndex", newCurrentIndex); + ignoreSignals = false; + ignoreCurrentIndexChanges = false; + + couldSet = view->property("currentIndex").toInt() == newCurrentIndex; + } + + if (couldSet) { + // The view's currentIndex might not have actually changed, but ours has, + // and that's what user code sees. + currentIndex = newCurrentIndex; + emit q->currentIndexChanged(); + } + } +} + void QQuickTumblerPrivate::setCount(int newCount) { if (newCount == count) @@ -658,7 +683,7 @@ void QQuickTumblerPrivate::setCount(int newCount) void QQuickTumblerPrivate::setWrapBasedOnCount() { - if (count == 0 || explicitWrap || ignoreWrapChanges) + if (count == 0 || explicitWrap || modelBeingSet) return; setWrap(count >= visibleItemCount, false); @@ -703,17 +728,17 @@ void QQuickTumblerPrivate::setWrap(bool shouldWrap, bool isExplicit) if (q->isComponentComplete() || contentItem) setupViewData(contentItem); - q->setCurrentIndex(oldCurrentIndex); + setCurrentIndex(oldCurrentIndex); } -void QQuickTumblerPrivate::lockWrap() +void QQuickTumblerPrivate::beginSetModel() { - ignoreWrapChanges = true; + modelBeingSet = true; } -void QQuickTumblerPrivate::unlockWrap() +void QQuickTumblerPrivate::endSetModel() { - ignoreWrapChanges = false; + modelBeingSet = false; setWrapBasedOnCount(); } @@ -749,12 +774,12 @@ void QQuickTumbler::updatePolish() // If there is a pending currentIndex at this stage, it means that // the view wouldn't set our currentIndex in _q_onViewCountChanged // because it wasn't ready. Try one last time here. - setCurrentIndex(d->pendingCurrentIndex); + d->setCurrentIndex(d->pendingCurrentIndex); if (d->currentIndex != d->pendingCurrentIndex && d->currentIndex == -1) { // If we *still* couldn't set it, it's probably invalid. // See if we can at least enforce our rule of "non-negative currentIndex when count > 0" instead. - setCurrentIndex(0); + d->setCurrentIndex(0); } d->pendingCurrentIndex = -1; diff --git a/src/quicktemplates2/qquicktumbler_p_p.h b/src/quicktemplates2/qquicktumbler_p_p.h index 7f824482..a7e5f2ac 100644 --- a/src/quicktemplates2/qquicktumbler_p_p.h +++ b/src/quicktemplates2/qquicktumbler_p_p.h @@ -77,7 +77,8 @@ public: int visibleItemCount = 5; bool wrap = true; bool explicitWrap = false; - bool ignoreWrapChanges = false; + bool modelBeingSet = false; + bool currentIndexSetDuringModelChange = false; QQuickItem *view = nullptr; QQuickItem *viewContentItem = nullptr; ContentItemType viewContentItemType = UnsupportedContentItemType; @@ -104,11 +105,17 @@ public: void setupViewData(QQuickItem *newControlContentItem); void syncCurrentIndex(); + enum PropertyChangeReason { + UserChange, + InternalChange + }; + + void setCurrentIndex(int newCurrentIndex, PropertyChangeReason changeReason = InternalChange); void setCount(int newCount); void setWrapBasedOnCount(); void setWrap(bool shouldWrap, bool isExplicit); - void lockWrap(); - void unlockWrap(); + void beginSetModel(); + void endSetModel(); void itemChildAdded(QQuickItem *, QQuickItem *) override; void itemChildRemoved(QQuickItem *, QQuickItem *) override; -- cgit v1.2.3 From 8b23ea3a5aeb3d8f36825047a313c20a1d54737e Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 8 Jun 2018 10:05:55 +0200 Subject: Imagine: document how to export 9-patch images Task-number: QTBUG-66834 Change-Id: I8a07e114d230361f21dfbf1458210729b3607d92 Reviewed-by: Venugopal Shivashankar --- .../controls/doc/src/qtquickcontrols2-imagine.qdoc | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'src') diff --git a/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc index 8fb5e3b6..7954bf68 100644 --- a/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc +++ b/src/imports/controls/doc/src/qtquickcontrols2-imagine.qdoc @@ -2358,6 +2358,60 @@ \image qtquickcontrols2-imagine-9-patch-inset-boundaries.png + \section3 Exporting 9-Patch Images + + Various vector and bitmap editors can be used to create 9-patch images + suitable for use with the Imagine style. The following sections briefly + explain the export process for each editor, and the last section explains + how to ensure the exported images are 9-patch-conformant. + + \section4 Illustrator + + See Adobe's + \l {https://helpx.adobe.com/in/illustrator/using/collect-assets-export-for-screens.html#panel} + {Asset Export panel} documentation. + + \section4 Inkscape + + The \l {https://github.com/mitchcurtis/inkscape-9-patch-export} + {Inkscape 9-Patch Export Extension} can be used to export assets with + Inkscape. + + \section4 Photoshop + + See Adobe's + \l {https://helpx.adobe.com/photoshop/using/generate-assets-layers.html} + {Generate image assets from layers} documentation. + + \section4 Sketch + + See Sketch's \l {https://sketchapp.com/docs/exporting/}{Exporting} documentation. + + Qt Quick Controls 2 also provides a + \l {http://code.qt.io/cgit/qt/qtquickcontrols2.git/tree/src/imports/controls/imagine/design} + {plugin} for Sketch that automatically fixes the thickness of the 9-patch lines + after the assets are exported. To install this file, double-click on it. + Once Sketch has confirmed that the 9-patch export plugin has been installed, + the plugin will automatically process images when they are exported. + + \section4 Fixing 9-Patch Lines + + When exporting 9-patch images in several DPI variants (\c {@2x}, \c {@3x}, + etc.), the 9-patch lines will typically be scaled up along with the image. + There are several ways to fix this, but perhaps the simplest approach is + to use \l {https://www.imagemagick.org/script/mogrify.php}{ImageMagick's mogrify} + tool. The tool has a \c -shave feature that can be used to crop the image + to reduce the thickness of the 9-patch lines: + + \badcode + mogrify -shave 1x1 -path path/to/images *@2x.9.png + mogrify -shave 2x2 -path path/to/images *@3x.9.png + mogrify -shave 3x3 -path path/to/images *@4x.9.png + \endcode + + Regular DPI images (those without the \c @Nx prefix) are not affected, so it + is only necessary to run the command on images intended for high DPI displays. + \section2 Animated Images The \l {https://developers.google.com/speed/webp/}{WebP} and GIF animated -- cgit v1.2.3 From d5fbbddd7794265f24d392d33c4874ac756cb9c9 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Thu, 21 Jun 2018 09:30:54 +0200 Subject: QQuickSpinBox: Fix "function expressions as statements" warning Surround the function with parentheses as suggested: QWARN : tst_Snippets::verify(qtquickcontrols2-spinbox-custom) Warning: Using function expressions as statements in scripts is not compliant with the ECMAScript specification: "function(value, locale) { return Number(value).toLocaleString(locale, ..." This will throw a syntax error in Qt 5.12. If you want a function expression, surround it by parentheses. Change-Id: I39df9af9b3dc62ffaf6fcba071c04c8933698c07 Reviewed-by: Simon Hausmann --- src/quicktemplates2/qquickspinbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp index 08c59cca..f1361330 100644 --- a/src/quicktemplates2/qquickspinbox.cpp +++ b/src/quicktemplates2/qquickspinbox.cpp @@ -619,7 +619,7 @@ QJSValue QQuickSpinBox::textFromValue() const if (!d->textFromValue.isCallable()) { QQmlEngine *engine = qmlEngine(this); if (engine) - d->textFromValue = engine->evaluate(QStringLiteral("function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }")); + d->textFromValue = engine->evaluate(QStringLiteral("(function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); })")); } return d->textFromValue; } -- cgit v1.2.3