aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-06-27 16:16:19 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-07-10 04:33:05 +0000
commit1771d298f33543a3fe47decfe0fff10609b01ab1 (patch)
tree2f19e74f00c458a7a31afa6fe9ce21abba20f61a
parentffbf089addcaab3e132f5dbb0685c1a46bd6d1ab (diff)
Teach Rectangle's gradient property to accept QGradient::Preset
Change-Id: Id640b596c1d8d52221f2f2be8807d6e245971bdc Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml12
-rw-r--r--src/quick/items/qquickrectangle.cpp87
-rw-r--r--src/quick/items/qquickrectangle_p.h7
-rw-r--r--src/quick/items/qquickrectangle_p_p.h2
-rw-r--r--tests/auto/quick/qquickdesignersupport/data/test.qml4
-rw-r--r--tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp8
-rw-r--r--tests/auto/quick/qquickrectangle/data/gradient-preset.qml16
-rw-r--r--tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp28
8 files changed, 136 insertions, 28 deletions
diff --git a/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml b/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml
index 031bee960d..e52a0ce0ef 100644
--- a/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml
+++ b/src/quick/doc/snippets/qml/rectangle/rectangle-gradient.qml
@@ -80,5 +80,17 @@ Rectangle {
}
}
//! [rectangles]
+
+//! [presets]
+Rectangle {
+ y: 0; width: 80; height: 80
+ gradient: Gradient.NightFade
+}
+
+Rectangle {
+ y: 0; width: 80; height: 80
+ gradient: "NightFade"
+}
+//! [presets]
}
}
diff --git a/src/quick/items/qquickrectangle.cpp b/src/quick/items/qquickrectangle.cpp
index ab8203d0a8..5e217dcd0c 100644
--- a/src/quick/items/qquickrectangle.cpp
+++ b/src/quick/items/qquickrectangle.cpp
@@ -40,9 +40,13 @@
#include "qquickrectangle_p.h"
#include "qquickrectangle_p_p.h"
+#include <QtQml/qqmlinfo.h>
+
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qsgadaptationlayer_p.h>
+#include <private/qqmlmetatype_p.h>
+
#include <QtGui/qpixmapcache.h>
#include <QtCore/qmath.h>
#include <QtCore/qmetaobject.h>
@@ -393,7 +397,7 @@ QQuickPen *QQuickRectangle::border()
}
/*!
- \qmlproperty Gradient QtQuick::Rectangle::gradient
+ \qmlproperty any QtQuick::Rectangle::gradient
The gradient to use to fill the rectangle.
@@ -407,37 +411,66 @@ QQuickPen *QQuickRectangle::border()
\snippet qml/rectangle/rectangle-gradient.qml rectangles
\clearfloat
+ The property also accepts gradient presets from QGradient::Preset. Note however
+ that due to Rectangle only supporting simple vertical or horizontal gradients,
+ any preset with an unsupported angle will revert to the closest representation.
+
+ \snippet qml/rectangle/rectangle-gradient.qml presets
+ \clearfloat
+
If both a gradient and a color are specified, the gradient will be used.
\sa Gradient, color
*/
-QQuickGradient *QQuickRectangle::gradient() const
+QJSValue QQuickRectangle::gradient() const
{
Q_D(const QQuickRectangle);
return d->gradient;
}
-void QQuickRectangle::setGradient(QQuickGradient *gradient)
+void QQuickRectangle::setGradient(const QJSValue &gradient)
{
Q_D(QQuickRectangle);
- if (d->gradient == gradient)
+ if (d->gradient.equals(gradient))
return;
- static int updatedSignalIdx = -1;
- if (updatedSignalIdx < 0)
- updatedSignalIdx = QMetaMethod::fromSignal(&QQuickGradient::updated).methodIndex();
+
+ static int updatedSignalIdx = QMetaMethod::fromSignal(&QQuickGradient::updated).methodIndex();
if (d->doUpdateSlotIdx < 0)
d->doUpdateSlotIdx = QQuickRectangle::staticMetaObject.indexOfSlot("doUpdate()");
- if (d->gradient)
- QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
- d->gradient = gradient;
- if (d->gradient)
- QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+
+ if (auto oldGradient = qobject_cast<QQuickGradient*>(d->gradient.toQObject()))
+ QMetaObject::disconnect(oldGradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+
+ if (gradient.isQObject()) {
+ if (auto newGradient = qobject_cast<QQuickGradient*>(gradient.toQObject())) {
+ d->gradient = gradient;
+ QMetaObject::connect(newGradient, updatedSignalIdx, this, d->doUpdateSlotIdx);
+ } else {
+ qmlWarning(this) << "Can't assign "
+ << QQmlMetaType::prettyTypeName(gradient.toQObject()) << " to gradient property";
+ d->gradient = QJSValue();
+ }
+ } else if (gradient.isNumber() || gradient.isString()) {
+ QGradient preset(gradient.toVariant().value<QGradient::Preset>());
+ if (preset.type() != QGradient::NoGradient) {
+ d->gradient = gradient;
+ } else {
+ qmlWarning(this) << "No such gradient preset '" << gradient.toString() << "'";
+ d->gradient = QJSValue();
+ }
+ } else if (gradient.isNull() || gradient.isUndefined()) {
+ d->gradient = gradient;
+ } else {
+ qmlWarning(this) << "Unknown gradient type. Expected int, string, or Gradient";
+ d->gradient = QJSValue();
+ }
+
update();
}
void QQuickRectangle::resetGradient()
{
- setGradient(nullptr);
+ setGradient(QJSValue());
}
/*!
@@ -534,9 +567,31 @@ QSGNode *QQuickRectangle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
QGradientStops stops;
bool vertical = true;
- if (d->gradient) {
- stops = d->gradient->gradientStops();
- vertical = d->gradient->orientation() == QQuickGradient::Vertical;
+ if (d->gradient.isQObject()) {
+ auto gradient = qobject_cast<QQuickGradient*>(d->gradient.toQObject());
+ Q_ASSERT(gradient);
+ stops = gradient->gradientStops();
+ vertical = gradient->orientation() == QQuickGradient::Vertical;
+ } else if (d->gradient.isNumber() || d->gradient.isString()) {
+ QGradient preset(d->gradient.toVariant().value<QGradient::Preset>());
+ if (preset.type() == QGradient::LinearGradient) {
+ auto linearGradient = static_cast<QLinearGradient&>(preset);
+ const QPointF start = linearGradient.start();
+ const QPointF end = linearGradient.finalStop();
+ vertical = qAbs(start.y() - end.y()) >= qAbs(start.x() - end.x());
+ stops = linearGradient.stops();
+ if ((vertical && start.y() > end.y()) || (!vertical && start.x() > end.x())) {
+ // QSGInternalRectangleNode doesn't support stops in the wrong order,
+ // so we need to manually reverse them here.
+ QGradientStops reverseStops;
+ for (auto it = stops.rbegin(); it != stops.rend(); ++it) {
+ auto stop = *it;
+ stop.first = 1 - stop.first;
+ reverseStops.append(stop);
+ }
+ stops = reverseStops;
+ }
+ }
}
rectangle->setGradientStops(stops);
rectangle->setGradientVertical(vertical);
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index ddafaafb28..d56a03d22d 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -122,6 +122,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickGradient : public QObject
Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged REVISION 12)
Q_CLASSINFO("DefaultProperty", "stops")
+ Q_ENUMS(QGradient::Preset)
public:
QQuickGradient(QObject *parent=nullptr);
~QQuickGradient() override;
@@ -157,7 +158,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRectangle : public QQuickItem
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QQuickGradient *gradient READ gradient WRITE setGradient RESET resetGradient)
+ Q_PROPERTY(QJSValue gradient READ gradient WRITE setGradient RESET resetGradient)
Q_PROPERTY(QQuickPen * border READ border CONSTANT)
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
public:
@@ -168,8 +169,8 @@ public:
QQuickPen *border();
- QQuickGradient *gradient() const;
- void setGradient(QQuickGradient *gradient);
+ QJSValue gradient() const;
+ void setGradient(const QJSValue &gradient);
void resetGradient();
qreal radius() const;
diff --git a/src/quick/items/qquickrectangle_p_p.h b/src/quick/items/qquickrectangle_p_p.h
index 3c1aaf7661..c7c5293f9b 100644
--- a/src/quick/items/qquickrectangle_p_p.h
+++ b/src/quick/items/qquickrectangle_p_p.h
@@ -73,7 +73,7 @@ public:
}
QColor color;
- QQuickGradient *gradient;
+ QJSValue gradient;
QQuickPen *pen;
qreal radius;
static int doUpdateSlotIdx;
diff --git a/tests/auto/quick/qquickdesignersupport/data/test.qml b/tests/auto/quick/qquickdesignersupport/data/test.qml
index 1d43cb3b7e..6c89f15257 100644
--- a/tests/auto/quick/qquickdesignersupport/data/test.qml
+++ b/tests/auto/quick/qquickdesignersupport/data/test.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick 2.11
Rectangle {
objectName: "rootItem"
@@ -13,7 +13,7 @@ Rectangle {
Rectangle {
objectName: "rectangleItem"
- gradient: Gradient {
+ containmentMask: Item {
}
}
diff --git a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
index 96a11e16e9..3e0765552a 100644
--- a/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
+++ b/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp
@@ -209,15 +209,15 @@ void tst_qquickdesignersupport::objectProperties()
//Read gradient property as QObject
- int propertyIndex = rectangleItem->metaObject()->indexOfProperty("gradient");
+ int propertyIndex = rectangleItem->metaObject()->indexOfProperty("containmentMask");
QVERIFY(propertyIndex > 0);
QMetaProperty metaProperty = rectangleItem->metaObject()->property(propertyIndex);
QVERIFY(metaProperty.isValid());
QVERIFY(QQuickDesignerSupportProperties::isPropertyQObject(metaProperty));
- QObject*gradient = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
- QVERIFY(gradient);
+ QObject *containmentItem = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, rectangleItem);
+ QVERIFY(containmentItem);
//The width property is not a QObject
@@ -450,7 +450,7 @@ void tst_qquickdesignersupport::testNotifyPropertyChangeCallBack()
QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(notifyPropertyChangeCallBackPointer);
- rectangle->setProperty("gradient", QVariant::fromValue<QQuickGradient *>(gradient));
+ rectangle->setProperty("gradient", QVariant::fromValue<QJSValue>(view->engine()->newQObject(gradient)));
QVERIFY(s_object);
QCOMPARE(s_object, rootItem);
diff --git a/tests/auto/quick/qquickrectangle/data/gradient-preset.qml b/tests/auto/quick/qquickrectangle/data/gradient-preset.qml
new file mode 100644
index 0000000000..b740bdd610
--- /dev/null
+++ b/tests/auto/quick/qquickrectangle/data/gradient-preset.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+Item {
+ Rectangle {
+ objectName: "enum"
+ gradient: Gradient.NightFade
+ }
+ Rectangle {
+ objectName: "string"
+ gradient: "NightFade"
+ }
+ Rectangle {
+ objectName: "invalid"
+ gradient: -1
+ }
+}
diff --git a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
index 2aaad867bf..f6ca999cf5 100644
--- a/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
+++ b/tests/auto/quick/qquickrectangle/tst_qquickrectangle.cpp
@@ -49,6 +49,7 @@ private slots:
void gradient_border();
void gradient_separate();
void gradient_multiple();
+ void gradient_preset();
void antialiasing();
private:
@@ -84,7 +85,7 @@ void tst_qquickrectangle::gradient()
QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(component.create());
QVERIFY(rect);
- QQuickGradient *grad = rect->gradient();
+ QQuickGradient *grad = qobject_cast<QQuickGradient *>(rect->gradient().toQObject());
QVERIFY(grad);
QQmlListProperty<QQuickGradientStop> stops = grad->stops();
@@ -103,7 +104,7 @@ void tst_qquickrectangle::gradient()
QMetaObject::invokeMethod(rect, "resetGradient");
- grad = rect->gradient();
+ grad = qobject_cast<QQuickGradient *>(rect->gradient().toQObject());
QVERIFY(!grad);
delete rect;
@@ -174,6 +175,29 @@ void tst_qquickrectangle::gradient_multiple()
QVERIFY(secondIsDirty);
}
+void tst_qquickrectangle::gradient_preset()
+{
+ QQuickView view;
+ view.setSource(testFileUrl("gradient-preset.qml"));
+ view.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+ QQuickRectangle *enumRect = view.rootObject()->findChild<QQuickRectangle *>("enum");
+ QVERIFY(enumRect);
+ QVERIFY(enumRect->gradient().isNumber());
+ QCOMPARE(enumRect->gradient().toUInt(), QGradient::NightFade);
+
+ QQuickRectangle *stringRect = view.rootObject()->findChild<QQuickRectangle *>("string");
+ QVERIFY(stringRect);
+ QVERIFY(stringRect->gradient().isString());
+ QCOMPARE(stringRect->gradient().toString(), QLatin1String("NightFade"));
+
+ QQuickRectangle *invalidRect = view.rootObject()->findChild<QQuickRectangle *>("invalid");
+ QVERIFY(invalidRect);
+ QVERIFY(invalidRect->gradient().isUndefined());
+}
+
void tst_qquickrectangle::antialiasing()
{
QQmlComponent component(&engine);