aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2011-09-12 08:12:58 +0200
committerGunnar Sletta <gunnar.sletta@nokia.com>2011-09-12 08:12:58 +0200
commitd77218522eb480c8d528de18049cd7b604cdeb2a (patch)
treea6433a8e9205a95006eae10b53285a0e3487423d /src/declarative/items
parent589c8445e2623ef8e0b8294d7c558a2948b2a5e3 (diff)
parentd5686fa2ac2248d5a31237573fa08697f18f035f (diff)
Merge branch 'master' into refactor
Conflicts: examples/declarative/cppextensions/qwidgets/qwidgets.pro examples/declarative/minehunt/main.cpp examples/declarative/minehunt/minehunt.pro src/declarative/items/context2d/qsgcontext2d.cpp src/declarative/items/qsgflickable.cpp src/declarative/items/qsgtextedit.cpp src/declarative/items/qsgtextinput.cpp src/declarative/particles/qsgangleddirection.cpp src/declarative/particles/qsgcumulativedirection.cpp src/declarative/particles/qsgcumulativedirection_p.h src/declarative/particles/qsgfollowemitter.cpp src/declarative/particles/qsgmodelparticle.cpp src/declarative/particles/qsgparticlesystem.cpp src/qtquick1/util/qdeclarativeview.h tests/auto/declarative/examples/examples.pro tests/auto/declarative/qsgfocusscope/tst_qsgfocusscope.cpp Change-Id: Ib4be2a5e742dee1a399d73da97161736f77448e5
Diffstat (limited to 'src/declarative/items')
-rw-r--r--src/declarative/items/context2d/qsgcontext2d.cpp587
-rw-r--r--src/declarative/items/qsganimation.cpp228
-rw-r--r--src/declarative/items/qsganimation_p.h62
-rw-r--r--src/declarative/items/qsganimation_p_p.h41
-rw-r--r--src/declarative/items/qsgcanvas.cpp2
-rw-r--r--src/declarative/items/qsgflickable.cpp21
-rw-r--r--src/declarative/items/qsgflickable_p.h6
-rw-r--r--src/declarative/items/qsgflickable_p_p.h1
-rw-r--r--src/declarative/items/qsggridview.cpp386
-rw-r--r--src/declarative/items/qsggridview_p.h5
-rw-r--r--src/declarative/items/qsgimagebase.cpp6
-rw-r--r--src/declarative/items/qsgimagebase_p.h2
-rw-r--r--src/declarative/items/qsgitem.cpp24
-rw-r--r--src/declarative/items/qsgitem.h6
-rw-r--r--src/declarative/items/qsgitem_p.h2
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp10
-rw-r--r--src/declarative/items/qsgitemview.cpp376
-rw-r--r--src/declarative/items/qsgitemview_p.h6
-rw-r--r--src/declarative/items/qsgitemview_p_p.h42
-rw-r--r--src/declarative/items/qsglistview.cpp423
-rw-r--r--src/declarative/items/qsglistview_p.h5
-rw-r--r--src/declarative/items/qsgshadereffect.cpp72
-rw-r--r--src/declarative/items/qsgshadereffect_p.h2
-rw-r--r--src/declarative/items/qsgshadereffectmesh.cpp42
-rw-r--r--src/declarative/items/qsgshadereffectmesh_p.h2
-rw-r--r--src/declarative/items/qsgtext.cpp13
-rw-r--r--src/declarative/items/qsgtextedit.cpp1
-rw-r--r--src/declarative/items/qsgtextinput.cpp3
-rw-r--r--src/declarative/items/qsgview.h3
29 files changed, 1035 insertions, 1344 deletions
diff --git a/src/declarative/items/context2d/qsgcontext2d.cpp b/src/declarative/items/context2d/qsgcontext2d.cpp
index 7a8465a4bc..e5f2eca6b1 100644
--- a/src/declarative/items/context2d/qsgcontext2d.cpp
+++ b/src/declarative/items/context2d/qsgcontext2d.cpp
@@ -46,6 +46,7 @@
#include <QtGui/qopenglframebufferobject.h>
#include <QtCore/qdebug.h>
#include "private/qsgcontext_p.h"
+#include "private/qdeclarativesvgparser_p.h"
#include <QtGui/qguiapplication.h>
#include <qdeclarativeinfo.h>
@@ -77,6 +78,7 @@ void copy_vector(QVector<T>* dst, const QVector<T>& src)
}
static bool parsePathDataFast(const QString &dataStr, QPainterPath &path);
+
#define DEGREES(t) ((t) * 180.0 / Q_PI)
#define qClamp(val, min, max) qMin(qMax(val, min), max)
@@ -2310,7 +2312,7 @@ void QSGContext2D::setPath(QSGCanvasPath* path)
QSGCanvasPath* QSGContext2D::createPath(const QString& pathString)
{
QPainterPath path;
- if (parsePathDataFast(pathString, path)) {
+ if (QDeclarativeSvgParser::parsePathDataFast(pathString, path)) {
return new QSGCanvasPath(path, this);
}
return 0;
@@ -2571,592 +2573,11 @@ bool QSGContext2D::isPointInPath(qreal x, qreal y) const
return d->path.contains(QPointF(x, y));
}
-//copied from QtSvg (qsvghandler.cpp).
-Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-// '0' is 0x30 and '9' is 0x39
-static inline bool isDigit(ushort ch)
-{
- static quint16 magic = 0x3ff;
- return ((ch >> 4) == 3) && (magic >> (ch & 15));
-}
-
-static qreal toDouble(const QChar *&str)
-{
- const int maxLen = 255;//technically doubles can go til 308+ but whatever
- char temp[maxLen+1];
- int pos = 0;
-
- if (*str == QLatin1Char('-')) {
- temp[pos++] = '-';
- ++str;
- } else if (*str == QLatin1Char('+')) {
- ++str;
- }
- while (isDigit(str->unicode()) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- if (*str == QLatin1Char('.') && pos < maxLen) {
- temp[pos++] = '.';
- ++str;
- }
- while (isDigit(str->unicode()) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- bool exponent = false;
- if ((*str == QLatin1Char('e') || *str == QLatin1Char('E')) && pos < maxLen) {
- exponent = true;
- temp[pos++] = 'e';
- ++str;
- if ((*str == QLatin1Char('-') || *str == QLatin1Char('+')) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- while (isDigit(str->unicode()) && pos < maxLen) {
- temp[pos++] = str->toLatin1();
- ++str;
- }
- }
-
- temp[pos] = '\0';
-
- qreal val;
- if (!exponent && pos < 10) {
- int ival = 0;
- const char *t = temp;
- bool neg = false;
- if(*t == '-') {
- neg = true;
- ++t;
- }
- while(*t && *t != '.') {
- ival *= 10;
- ival += (*t) - '0';
- ++t;
- }
- if(*t == '.') {
- ++t;
- int div = 1;
- while(*t) {
- ival *= 10;
- ival += (*t) - '0';
- div *= 10;
- ++t;
- }
- val = ((qreal)ival)/((qreal)div);
- } else {
- val = ival;
- }
- if (neg)
- val = -val;
- } else {
-#if defined(Q_WS_QWS) && !defined(Q_OS_VXWORKS)
- if(sizeof(qreal) == sizeof(float))
- val = strtof(temp, 0);
- else
-#endif
- {
- bool ok = false;
- val = qstrtod(temp, 0, &ok);
- }
- }
- return val;
-
-}
-static qreal toDouble(const QString &str, bool *ok = NULL)
-{
- const QChar *c = str.constData();
- qreal res = toDouble(c);
- if (ok) {
- *ok = ((*c) == QLatin1Char('\0'));
- }
- return res;
-}
-
-static qreal toDouble(const QStringRef &str, bool *ok = NULL)
-{
- const QChar *c = str.constData();
- qreal res = toDouble(c);
- if (ok) {
- *ok = (c == (str.constData() + str.length()));
- }
- return res;
-}
-static inline void parseNumbersArray(const QChar *&str, QVarLengthArray<qreal, 8> &points)
-{
- while (str->isSpace())
- ++str;
- while (isDigit(str->unicode()) ||
- *str == QLatin1Char('-') || *str == QLatin1Char('+') ||
- *str == QLatin1Char('.')) {
-
- points.append(toDouble(str));
-
- while (str->isSpace())
- ++str;
- if (*str == QLatin1Char(','))
- ++str;
-
- //eat the rest of space
- while (str->isSpace())
- ++str;
- }
-}
-
-static void pathArcSegment(QPainterPath &path,
- qreal xc, qreal yc,
- qreal th0, qreal th1,
- qreal rx, qreal ry, qreal xAxisRotation)
-{
- qreal sinTh, cosTh;
- qreal a00, a01, a10, a11;
- qreal x1, y1, x2, y2, x3, y3;
- qreal t;
- qreal thHalf;
-
- sinTh = qSin(xAxisRotation * (Q_PI / 180.0));
- cosTh = qCos(xAxisRotation * (Q_PI / 180.0));
-
- a00 = cosTh * rx;
- a01 = -sinTh * ry;
- a10 = sinTh * rx;
- a11 = cosTh * ry;
-
- thHalf = 0.5 * (th1 - th0);
- t = (8.0 / 3.0) * qSin(thHalf * 0.5) * qSin(thHalf * 0.5) / qSin(thHalf);
- x1 = xc + qCos(th0) - t * qSin(th0);
- y1 = yc + qSin(th0) + t * qCos(th0);
- x3 = xc + qCos(th1);
- y3 = yc + qSin(th1);
- x2 = x3 + t * qSin(th1);
- y2 = y3 - t * qCos(th1);
-
- path.cubicTo(a00 * x1 + a01 * y1, a10 * x1 + a11 * y1,
- a00 * x2 + a01 * y2, a10 * x2 + a11 * y2,
- a00 * x3 + a01 * y3, a10 * x3 + a11 * y3);
-}
-
-static void pathArc(QPainterPath &path,
- qreal rx,
- qreal ry,
- qreal x_axis_rotation,
- int large_arc_flag,
- int sweep_flag,
- qreal x,
- qreal y,
- qreal curx, qreal cury)
-{
- qreal sin_th, cos_th;
- qreal a00, a01, a10, a11;
- qreal x0, y0, x1, y1, xc, yc;
- qreal d, sfactor, sfactor_sq;
- qreal th0, th1, th_arc;
- int i, n_segs;
- qreal dx, dy, dx1, dy1, Pr1, Pr2, Px, Py, check;
-
- rx = qAbs(rx);
- ry = qAbs(ry);
-
- sin_th = qSin(x_axis_rotation * (Q_PI / 180.0));
- cos_th = qCos(x_axis_rotation * (Q_PI / 180.0));
-
- dx = (curx - x) / 2.0;
- dy = (cury - y) / 2.0;
- dx1 = cos_th * dx + sin_th * dy;
- dy1 = -sin_th * dx + cos_th * dy;
- Pr1 = rx * rx;
- Pr2 = ry * ry;
- Px = dx1 * dx1;
- Py = dy1 * dy1;
- /* Spec : check if radii are large enough */
- check = Px / Pr1 + Py / Pr2;
- if (check > 1) {
- rx = rx * qSqrt(check);
- ry = ry * qSqrt(check);
- }
-
- a00 = cos_th / rx;
- a01 = sin_th / rx;
- a10 = -sin_th / ry;
- a11 = cos_th / ry;
- x0 = a00 * curx + a01 * cury;
- y0 = a10 * curx + a11 * cury;
- x1 = a00 * x + a01 * y;
- y1 = a10 * x + a11 * y;
- /* (x0, y0) is current point in transformed coordinate space.
- (x1, y1) is new point in transformed coordinate space.
-
- The arc fits a unit-radius circle in this space.
- */
- d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
- sfactor_sq = 1.0 / d - 0.25;
- if (sfactor_sq < 0) sfactor_sq = 0;
- sfactor = qSqrt(sfactor_sq);
- if (sweep_flag == large_arc_flag) sfactor = -sfactor;
- xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
- yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
- /* (xc, yc) is center of the circle. */
-
- th0 = qAtan2(y0 - yc, x0 - xc);
- th1 = qAtan2(y1 - yc, x1 - xc);
-
- th_arc = th1 - th0;
- if (th_arc < 0 && sweep_flag)
- th_arc += 2 * Q_PI;
- else if (th_arc > 0 && !sweep_flag)
- th_arc -= 2 * Q_PI;
-
- n_segs = qCeil(qAbs(th_arc / (Q_PI * 0.5 + 0.001)));
-
- for (i = 0; i < n_segs; i++) {
- pathArcSegment(path, xc, yc,
- th0 + i * th_arc / n_segs,
- th0 + (i + 1) * th_arc / n_segs,
- rx, ry, x_axis_rotation);
- }
-}
-
-
-static bool parsePathDataFast(const QString &dataStr, QPainterPath &path)
-{
- qreal x0 = 0, y0 = 0; // starting point
- qreal x = 0, y = 0; // current point
- char lastMode = 0;
- QPointF ctrlPt;
- const QChar *str = dataStr.constData();
- const QChar *end = str + dataStr.size();
-
- while (str != end) {
- while (str->isSpace())
- ++str;
- QChar pathElem = *str;
- ++str;
- QChar endc = *end;
- *const_cast<QChar *>(end) = 0; // parseNumbersArray requires 0-termination that QStringRef cannot guarantee
- QVarLengthArray<qreal, 8> arg;
- parseNumbersArray(str, arg);
- *const_cast<QChar *>(end) = endc;
- if (pathElem == QLatin1Char('z') || pathElem == QLatin1Char('Z'))
- arg.append(0);//dummy
- const qreal *num = arg.constData();
- int count = arg.count();
- while (count > 0) {
- qreal offsetX = x; // correction offsets
- qreal offsetY = y; // for relative commands
- switch (pathElem.unicode()) {
- case 'm': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = x0 = num[0] + offsetX;
- y = y0 = num[1] + offsetY;
- num += 2;
- count -= 2;
- path.moveTo(x0, y0);
-
- // As per 1.2 spec 8.3.2 The "moveto" commands
- // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
- // the subsequent pairs shall be treated as implicit 'lineto' commands.
- pathElem = QLatin1Char('l');
- }
- break;
- case 'M': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = x0 = num[0];
- y = y0 = num[1];
- num += 2;
- count -= 2;
- path.moveTo(x0, y0);
-
- // As per 1.2 spec 8.3.2 The "moveto" commands
- // If a 'moveto' is followed by multiple pairs of coordinates without explicit commands,
- // the subsequent pairs shall be treated as implicit 'lineto' commands.
- pathElem = QLatin1Char('L');
- }
- break;
- case 'z':
- case 'Z': {
- x = x0;
- y = y0;
- count--; // skip dummy
- num++;
- path.closeSubpath();
- }
- break;
- case 'l': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = num[0] + offsetX;
- y = num[1] + offsetY;
- num += 2;
- count -= 2;
- path.lineTo(x, y);
-
- }
- break;
- case 'L': {
- if (count < 2) {
- num++;
- count--;
- break;
- }
- x = num[0];
- y = num[1];
- num += 2;
- count -= 2;
- path.lineTo(x, y);
- }
- break;
- case 'h': {
- x = num[0] + offsetX;
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'H': {
- x = num[0];
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'v': {
- y = num[0] + offsetY;
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'V': {
- y = num[0];
- num++;
- count--;
- path.lineTo(x, y);
- }
- break;
- case 'c': {
- if (count < 6) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1(num[0] + offsetX, num[1] + offsetY);
- QPointF c2(num[2] + offsetX, num[3] + offsetY);
- QPointF e(num[4] + offsetX, num[5] + offsetY);
- num += 6;
- count -= 6;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 'C': {
- if (count < 6) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1(num[0], num[1]);
- QPointF c2(num[2], num[3]);
- QPointF e(num[4], num[5]);
- num += 6;
- count -= 6;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 's': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1;
- if (lastMode == 'c' || lastMode == 'C' ||
- lastMode == 's' || lastMode == 'S')
- c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c1 = QPointF(x, y);
- QPointF c2(num[0] + offsetX, num[1] + offsetY);
- QPointF e(num[2] + offsetX, num[3] + offsetY);
- num += 4;
- count -= 4;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 'S': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c1;
- if (lastMode == 'c' || lastMode == 'C' ||
- lastMode == 's' || lastMode == 'S')
- c1 = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c1 = QPointF(x, y);
- QPointF c2(num[0], num[1]);
- QPointF e(num[2], num[3]);
- num += 4;
- count -= 4;
- path.cubicTo(c1, c2, e);
- ctrlPt = c2;
- x = e.x();
- y = e.y();
- break;
- }
- case 'q': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c(num[0] + offsetX, num[1] + offsetY);
- QPointF e(num[2] + offsetX, num[3] + offsetY);
- num += 4;
- count -= 4;
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 'Q': {
- if (count < 4) {
- num += count;
- count = 0;
- break;
- }
- QPointF c(num[0], num[1]);
- QPointF e(num[2], num[3]);
- num += 4;
- count -= 4;
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 't': {
- if (count < 2) {
- num += count;
- count = 0;
- break;
- }
- QPointF e(num[0] + offsetX, num[1] + offsetY);
- num += 2;
- count -= 2;
- QPointF c;
- if (lastMode == 'q' || lastMode == 'Q' ||
- lastMode == 't' || lastMode == 'T')
- c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c = QPointF(x, y);
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 'T': {
- if (count < 2) {
- num += count;
- count = 0;
- break;
- }
- QPointF e(num[0], num[1]);
- num += 2;
- count -= 2;
- QPointF c;
- if (lastMode == 'q' || lastMode == 'Q' ||
- lastMode == 't' || lastMode == 'T')
- c = QPointF(2*x-ctrlPt.x(), 2*y-ctrlPt.y());
- else
- c = QPointF(x, y);
- path.quadTo(c, e);
- ctrlPt = c;
- x = e.x();
- y = e.y();
- break;
- }
- case 'a': {
- if (count < 7) {
- num += count;
- count = 0;
- break;
- }
- qreal rx = (*num++);
- qreal ry = (*num++);
- qreal xAxisRotation = (*num++);
- qreal largeArcFlag = (*num++);
- qreal sweepFlag = (*num++);
- qreal ex = (*num++) + offsetX;
- qreal ey = (*num++) + offsetY;
- count -= 7;
- qreal curx = x;
- qreal cury = y;
- pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
- int(sweepFlag), ex, ey, curx, cury);
-
- x = ex;
- y = ey;
- }
- break;
- case 'A': {
- if (count < 7) {
- num += count;
- count = 0;
- break;
- }
- qreal rx = (*num++);
- qreal ry = (*num++);
- qreal xAxisRotation = (*num++);
- qreal largeArcFlag = (*num++);
- qreal sweepFlag = (*num++);
- qreal ex = (*num++);
- qreal ey = (*num++);
- count -= 7;
- qreal curx = x;
- qreal cury = y;
- pathArc(path, rx, ry, xAxisRotation, int(largeArcFlag),
- int(sweepFlag), ex, ey, curx, cury);
-
- x = ex;
- y = ey;
- }
- break;
- default:
- return false;
- }
- lastMode = pathElem.toLatin1();
- }
- }
- return true;
-}
-
void QSGContext2D::setPathString(const QString& path)
{
Q_D(QSGContext2D);
d->path = QPainterPath();
- parsePathDataFast(path, d->path);
+ QDeclarativeSvgParser::parsePathDataFast(path, d->path);
}
QList<int> QSGContext2D::getImageData(qreal sx, qreal sy, qreal sw, qreal sh)
diff --git a/src/declarative/items/qsganimation.cpp b/src/declarative/items/qsganimation.cpp
index 0822974397..eda5629eb9 100644
--- a/src/declarative/items/qsganimation.cpp
+++ b/src/declarative/items/qsganimation.cpp
@@ -43,6 +43,9 @@
#include "qsganimation_p_p.h"
#include "qsgstateoperations_p.h"
+#include <qdeclarativeproperty_p.h>
+#include <qdeclarativepath_p.h>
+
#include <QtDeclarative/qdeclarativeinfo.h>
#include <QtCore/qmath.h>
#include <QtCore/qsequentialanimationgroup.h>
@@ -439,4 +442,229 @@ void QSGAnchorAnimation::transition(QDeclarativeStateActions &actions,
}
}
+QSGPathAnimation::QSGPathAnimation(QObject *parent)
+: QDeclarativeAbstractAnimation(*(new QSGPathAnimationPrivate), parent)
+{
+ Q_D(QSGPathAnimation);
+ d->pa = new QDeclarativeBulkValueAnimator;
+ QDeclarative_setParent_noEvent(d->pa, this);
+}
+
+QSGPathAnimation::~QSGPathAnimation()
+{
+}
+
+int QSGPathAnimation::duration() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->pa->duration();
+}
+
+void QSGPathAnimation::setDuration(int duration)
+{
+ if (duration < 0) {
+ qmlInfo(this) << tr("Cannot set a duration of < 0");
+ return;
+ }
+
+ Q_D(QSGPathAnimation);
+ if (d->pa->duration() == duration)
+ return;
+ d->pa->setDuration(duration);
+ emit durationChanged(duration);
+}
+
+QEasingCurve QSGPathAnimation::easing() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->pa->easingCurve();
+}
+
+void QSGPathAnimation::setEasing(const QEasingCurve &e)
+{
+ Q_D(QSGPathAnimation);
+ if (d->pa->easingCurve() == e)
+ return;
+
+ d->pa->setEasingCurve(e);
+ emit easingChanged(e);
+}
+
+QDeclarativePath *QSGPathAnimation::path() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->path;
+}
+
+void QSGPathAnimation::setPath(QDeclarativePath *path)
+{
+ Q_D(QSGPathAnimation);
+ if (d->path == path)
+ return;
+
+ d->path = path;
+ emit pathChanged();
+}
+
+QSGItem *QSGPathAnimation::target() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->target;
+}
+
+void QSGPathAnimation::setTarget(QSGItem *target)
+{
+ Q_D(QSGPathAnimation);
+ if (d->target == target)
+ return;
+
+ d->target = target;
+ emit targetChanged();
+}
+
+QSGPathAnimation::Orientation QSGPathAnimation::orientation() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->orientation;
+}
+
+void QSGPathAnimation::setOrientation(Orientation orientation)
+{
+ Q_D(QSGPathAnimation);
+ if (d->orientation == orientation)
+ return;
+
+ d->orientation = orientation;
+ emit orientationChanged(d->orientation);
+}
+
+QPointF QSGPathAnimation::anchorPoint() const
+{
+ Q_D(const QSGPathAnimation);
+ return d->anchorPoint;
+}
+
+void QSGPathAnimation::setAnchorPoint(const QPointF &point)
+{
+ Q_D(QSGPathAnimation);
+ if (d->anchorPoint == point)
+ return;
+
+ d->anchorPoint = point;
+ emit anchorPointChanged(point);
+}
+
+QAbstractAnimation *QSGPathAnimation::qtAnimation()
+{
+ Q_D(QSGPathAnimation);
+ return d->pa;
+}
+
+void QSGPathAnimation::transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QSGPathAnimation);
+ QSGPathAnimationUpdater *data = new QSGPathAnimationUpdater;
+
+ data->orientation = d->orientation;
+ data->anchorPoint = d->anchorPoint;
+ data->reverse = direction == Backward ? true : false;
+ data->fromSourced = false;
+ data->fromDefined = d->path ? !d->path->hasStartX() || !d->path->hasStartY() ? false : true : false; //### handle x/y separately, as well as endpoint specification?
+ int origModifiedSize = modified.count();
+
+ for (int i = 0; i < actions.count(); ++i) {
+ QDeclarativeAction &action = actions[i];
+ if (action.event)
+ continue;
+ if (action.specifiedObject == d->target && action.property.name() == QLatin1String("x")) {
+ data->toX = action.toValue.toReal();
+ modified << action.property;
+ action.fromValue = action.toValue;
+ }
+ if (action.specifiedObject == d->target && action.property.name() == QLatin1String("y")) {
+ data->toY = action.toValue.toReal();
+ modified << action.property;
+ action.fromValue = action.toValue;
+ }
+ }
+
+ if (d->target && d->path &&
+ (modified.count() > origModifiedSize || data->fromDefined)) {
+ data->target = d->target;
+ data->path = d->path;
+ if (!d->rangeIsSet) {
+ d->pa->setStartValue(qreal(0));
+ d->pa->setEndValue(qreal(1));
+ d->rangeIsSet = true;
+ }
+ d->pa->setFromSourcedValue(&data->fromSourced);
+ d->pa->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ d->pa->setFromSourcedValue(0);
+ d->pa->setAnimValue(0, QAbstractAnimation::DeleteWhenStopped);
+ delete data;
+ }
+}
+
+void QSGPathAnimationUpdater::setValue(qreal v)
+{
+ if (!fromSourced && !fromDefined) { //### check if !toDefined?
+ qreal startX = reverse ? toX + anchorPoint.x() : target->x() + anchorPoint.x();
+ qreal startY = reverse ? toY + anchorPoint.y() : target->y() + anchorPoint.y();
+ qreal endX = reverse ? target->x() + anchorPoint.x() : toX + anchorPoint.x();
+ qreal endY = reverse ? target->y() + anchorPoint.y() : toY + anchorPoint.y();
+
+ prevBez.isValid = false;
+ painterPath = path->createPath(QPointF(startX, startY), QPointF(endX, endY), QStringList(), pathLength, attributePoints);
+ fromSourced = true;
+ }
+
+ qreal angle;
+ bool fixed = orientation == QSGPathAnimation::Fixed;
+ QPointF currentPos = !painterPath.isEmpty() ? path->sequentialPointAt(painterPath, pathLength, attributePoints, prevBez, v, fixed ? 0 : &angle) : path->sequentialPointAt(v, fixed ? 0 : &angle);
+
+ //adjust position according to anchor point
+ if (!anchorPoint.isNull()) {
+ currentPos -= anchorPoint;
+ if ((reverse && v == 1.0) || (!reverse && v == 0.0)) {
+ if (!anchorPoint.isNull() && !fixed)
+ target->setTransformOriginPoint(anchorPoint);
+ }
+ }
+
+ //### too expensive to reconstruct properties each time?
+ QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, "x"), currentPos.x(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, "y"), currentPos.y(), QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+
+ //adjust angle according to orientation
+ if (!fixed) {
+ switch (orientation) {
+ case QSGPathAnimation::RightFirst:
+ angle = -angle;
+ break;
+ case QSGPathAnimation::LeftFirst:
+ angle = -angle + 180;
+ break;
+ case QSGPathAnimation::BottomFirst:
+ angle = -angle + 270;
+ break;
+ case QSGPathAnimation::TopFirst:
+ angle = -angle + 450;
+ break;
+ default:
+ angle = 0;
+ break;
+ }
+ QDeclarativePropertyPrivate::write(QDeclarativeProperty(target, "rotation"), angle, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+
+ //### resetting transform causes visual jump if ending on an angle
+// if ((reverse && v == 0.0) || (!reverse && v == 1.0)) {
+// if (!anchorPoint.isNull() && !fixed)
+// target->setTransformOriginPoint(QPointF());
+// }
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsganimation_p.h b/src/declarative/items/qsganimation_p.h
index ee3fe8d02d..6406b863a0 100644
--- a/src/declarative/items/qsganimation_p.h
+++ b/src/declarative/items/qsganimation_p.h
@@ -122,10 +122,72 @@ protected:
virtual QAbstractAnimation *qtAnimation();
};
+class QSGItem;
+class QDeclarativePath;
+class QSGPathAnimationPrivate;
+class Q_AUTOTEST_EXPORT QSGPathAnimation : public QDeclarativeAbstractAnimation
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGPathAnimation)
+
+ Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged)
+ Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged)
+ Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(QSGItem *target READ target WRITE setTarget NOTIFY targetChanged)
+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
+ Q_PROPERTY(QPointF anchorPoint READ anchorPoint WRITE setAnchorPoint NOTIFY anchorPointChanged)
+
+public:
+ QSGPathAnimation(QObject *parent=0);
+ virtual ~QSGPathAnimation();
+
+ enum Orientation {
+ Fixed,
+ RightFirst,
+ LeftFirst,
+ BottomFirst,
+ TopFirst
+ };
+ Q_ENUMS(Orientation)
+
+ int duration() const;
+ void setDuration(int);
+
+ QEasingCurve easing() const;
+ void setEasing(const QEasingCurve &);
+
+ QDeclarativePath *path() const;
+ void setPath(QDeclarativePath *);
+
+ QSGItem *target() const;
+ void setTarget(QSGItem *);
+
+ Orientation orientation() const;
+ void setOrientation(Orientation orientation);
+
+ QPointF anchorPoint() const;
+ void setAnchorPoint(const QPointF &point);
+
+protected:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ virtual QAbstractAnimation *qtAnimation();
+
+Q_SIGNALS:
+ void durationChanged(int);
+ void easingChanged(const QEasingCurve &);
+ void pathChanged();
+ void targetChanged();
+ void orientationChanged(Orientation);
+ void anchorPointChanged(const QPointF &);
+};
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QSGParentAnimation)
QML_DECLARE_TYPE(QSGAnchorAnimation)
+QML_DECLARE_TYPE(QSGPathAnimation)
QT_END_HEADER
diff --git a/src/declarative/items/qsganimation_p_p.h b/src/declarative/items/qsganimation_p_p.h
index 6f26f35234..e26dbbd9fb 100644
--- a/src/declarative/items/qsganimation_p_p.h
+++ b/src/declarative/items/qsganimation_p_p.h
@@ -56,6 +56,7 @@
#include "qsganimation_p.h"
+#include <private/qdeclarativepath_p.h>
#include <private/qdeclarativeanimation_p_p.h>
QT_BEGIN_NAMESPACE
@@ -92,6 +93,46 @@ public:
QList<QSGItem*> targets;
};
+class QSGPathAnimationUpdater : public QDeclarativeBulkValueUpdater
+{
+public:
+ QDeclarativePath *path;
+
+ QPainterPath painterPath;
+ QDeclarativeCachedBezier prevBez;
+ qreal pathLength;
+ QList<QDeclarativePath::AttributePoint> attributePoints;
+
+ QSGItem *target;
+ bool reverse;
+ bool fromSourced;
+ bool fromDefined;
+ qreal toX;
+ qreal toY;
+ QSGPathAnimation::Orientation orientation;
+ QPointF anchorPoint;
+ QSGPathAnimationUpdater() : path(0), target(0), reverse(false),
+ fromSourced(false), fromDefined(false), toX(0), toY(0), orientation(QSGPathAnimation::Fixed) {}
+ ~QSGPathAnimationUpdater() {}
+ void setValue(qreal v);
+};
+
+class QSGPathAnimationPrivate : public QDeclarativeAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QSGPathAnimation)
+public:
+ QSGPathAnimationPrivate() : path(0), target(0),
+ rangeIsSet(false), orientation(QSGPathAnimation::Fixed), pa(0) {}
+
+ QDeclarativePath *path;
+ QSGItem *target;
+ bool rangeIsSet;
+ QSGPathAnimation::Orientation orientation;
+ QPointF anchorPoint;
+ QDeclarativeBulkValueAnimator *pa;
+};
+
+
QT_END_NAMESPACE
#endif // QSGANIMATION_P_H
diff --git a/src/declarative/items/qsgcanvas.cpp b/src/declarative/items/qsgcanvas.cpp
index 2f663681ae..3e3a8b5842 100644
--- a/src/declarative/items/qsgcanvas.cpp
+++ b/src/declarative/items/qsgcanvas.cpp
@@ -1537,7 +1537,7 @@ void QSGCanvasPrivate::updateDirtyNode(QSGItem *item)
itemPriv->transforms.at(ii)->applyTo(&matrix);
if (itemPriv->scale != 1. || itemPriv->rotation != 0.) {
- QPointF origin = itemPriv->computeTransformOrigin();
+ QPointF origin = item->transformOriginPoint();
matrix.translate(origin.x(), origin.y());
if (itemPriv->scale != 1.)
matrix.scale(itemPriv->scale, itemPriv->scale);
diff --git a/src/declarative/items/qsgflickable.cpp b/src/declarative/items/qsgflickable.cpp
index 21474be8d9..e207e4bfd0 100644
--- a/src/declarative/items/qsgflickable.cpp
+++ b/src/declarative/items/qsgflickable.cpp
@@ -175,6 +175,7 @@ QSGFlickablePrivate::QSGFlickablePrivate()
, hMoved(false), vMoved(false)
, movingHorizontally(false), movingVertically(false)
, stealMouse(false), pressed(false), interactive(true), calcVelocity(false)
+ , pixelAligned(false)
, deceleration(QML_FLICK_DEFAULTDECELERATION)
, maxVelocity(QML_FLICK_DEFAULTMAXVELOCITY), reportedVelocitySmoothing(100)
, delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(400)
@@ -778,6 +779,21 @@ void QSGFlickable::setFlickableDirection(FlickableDirection direction)
}
}
+bool QSGFlickable::pixelAligned() const
+{
+ Q_D(const QSGFlickable);
+ return d->pixelAligned;
+}
+
+void QSGFlickable::setPixelAligned(bool align)
+{
+ Q_D(QSGFlickable);
+ if (align != d->pixelAligned) {
+ d->pixelAligned = align;
+ emit pixelAlignedChanged();
+ }
+}
+
void QSGFlickablePrivate::handleMousePressEvent(QMouseEvent *event)
{
Q_Q(QSGFlickable);
@@ -1081,14 +1097,15 @@ void QSGFlickablePrivate::clearDelayedPress()
}
}
+//XXX pixelAligned ignores the global position of the Flickable, i.e. assumes Flickable itself is pixel aligned.
void QSGFlickablePrivate::setViewportX(qreal x)
{
- contentItem->setX(x);
+ contentItem->setX(pixelAligned ? qRound(x) : x);
}
void QSGFlickablePrivate::setViewportY(qreal y)
{
- contentItem->setY(y);
+ contentItem->setY(pixelAligned ? qRound(y) : y);
}
void QSGFlickable::timerEvent(QTimerEvent *event)
diff --git a/src/declarative/items/qsgflickable_p.h b/src/declarative/items/qsgflickable_p.h
index 14f5232cd8..d638b921c5 100644
--- a/src/declarative/items/qsgflickable_p.h
+++ b/src/declarative/items/qsgflickable_p.h
@@ -90,6 +90,8 @@ class Q_AUTOTEST_EXPORT QSGFlickable : public QSGItem
Q_PROPERTY(QSGFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
+ Q_PROPERTY(bool pixelAligned READ pixelAligned WRITE setPixelAligned NOTIFY pixelAlignedChanged)
+
Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
Q_PROPERTY(QDeclarativeListProperty<QSGItem> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
@@ -156,6 +158,9 @@ public:
FlickableDirection flickableDirection() const;
void setFlickableDirection(FlickableDirection);
+ bool pixelAligned() const;
+ void setPixelAligned(bool align);
+
Q_INVOKABLE void resizeContent(qreal w, qreal h, QPointF center);
Q_INVOKABLE void returnToBounds();
@@ -188,6 +193,7 @@ Q_SIGNALS:
void flickEnded();
void dragStarted();
void dragEnded();
+ void pixelAlignedChanged();
protected:
virtual bool childMouseEventFilter(QSGItem *, QEvent *);
diff --git a/src/declarative/items/qsgflickable_p_p.h b/src/declarative/items/qsgflickable_p_p.h
index 3ac6d87864..21c31060b8 100644
--- a/src/declarative/items/qsgflickable_p_p.h
+++ b/src/declarative/items/qsgflickable_p_p.h
@@ -168,6 +168,7 @@ public:
bool pressed : 1;
bool interactive : 1;
bool calcVelocity : 1;
+ bool pixelAligned : 1;
QElapsedTimer lastPosTime;
QPointF lastPos;
QPointF pressPos;
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index bc4954a168..e2fe5cd9c8 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -160,12 +160,15 @@ public:
FxViewItem *snapItemAt(qreal pos) const;
int snapIndex() const;
- virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
- virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual void visibleItemsChanged();
virtual FxViewItem *newViewItem(int index, QSGItem *item);
virtual void repositionPackageItemAt(QSGItem *item, int index);
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem);
+ virtual void resetFirstItemPosition();
+ virtual void moveItemBy(FxViewItem *item, const QList<FxViewItem *> &items, const QList<FxViewItem *> &movedBackwards);
virtual void createHighlight();
virtual void updateHighlight();
@@ -173,6 +176,7 @@ public:
virtual void setPosition(qreal pos);
virtual void layoutVisibleItems();
+ bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, QList<FxViewItem *> *, QList<FxViewItem *>*, FxViewItem *);
virtual qreal headerSize() const;
virtual qreal footerSize() const;
@@ -383,7 +387,7 @@ FxViewItem *QSGGridViewPrivate::newViewItem(int modelIndex, QSGItem *item)
return new FxGridItemSG(item, q, false);
}
-bool QSGGridViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
+bool QSGGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
{
int colPos = colPosAt(visibleIndex);
int rowPos = rowPosAt(visibleIndex);
@@ -475,7 +479,7 @@ bool QSGGridViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer
return changed;
}
-bool QSGGridViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+bool QSGGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxGridItemSG *item = 0;
bool changed = false;
@@ -560,6 +564,24 @@ void QSGGridViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
}
}
+void QSGGridViewPrivate::resetItemPosition(FxViewItem *item, FxViewItem *toItem)
+{
+ FxGridItemSG *toGridItem = static_cast<FxGridItemSG*>(toItem);
+ static_cast<FxGridItemSG*>(item)->setPosition(toGridItem->colPos(), toGridItem->rowPos());
+}
+
+void QSGGridViewPrivate::resetFirstItemPosition()
+{
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.first());
+ item->setPosition(0, 0);
+}
+
+void QSGGridViewPrivate::moveItemBy(FxViewItem *item, const QList<FxViewItem *> &forwards, const QList<FxViewItem *> &backwards)
+{
+ int moveCount = forwards.count() - backwards.count();
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(item);
+ gridItem->setPosition(gridItem->colPos(), gridItem->rowPos() + ((moveCount / columns) * rowSize()));
+}
void QSGGridViewPrivate::createHighlight()
{
@@ -602,6 +624,8 @@ void QSGGridViewPrivate::createHighlight()
void QSGGridViewPrivate::updateHighlight()
{
+ applyPendingChanges();
+
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
bool strictHighlight = haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange;
@@ -750,7 +774,7 @@ void QSGGridViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeo
if (item == q) {
if (newGeometry.height() != oldGeometry.height() || newGeometry.width() != oldGeometry.width()) {
updateViewport();
- scheduleLayout();
+ q->polish();
}
}
}
@@ -1370,6 +1394,7 @@ void QSGGridView::setCellWidth(int cellWidth)
d->cellWidth = qMax(1, cellWidth);
d->updateViewport();
emit cellWidthChanged();
+ d->forceLayout = true;
d->layout();
}
}
@@ -1387,6 +1412,7 @@ void QSGGridView::setCellHeight(int cellHeight)
d->cellHeight = qMax(1, cellHeight);
d->updateViewport();
emit cellHeightChanged();
+ d->forceLayout = true;
d->layout();
}
}
@@ -1688,349 +1714,96 @@ void QSGGridView::moveCurrentIndexRight()
}
}
-
-void QSGGridView::itemsInserted(int modelIndex, int count)
+bool QSGGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, QList<FxViewItem *> *movedBackwards, QList<FxViewItem *> *addedItems, FxViewItem *firstVisible)
{
- Q_D(QSGGridView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
+ Q_Q(QSGGridView);
+
+ int modelIndex = change.index;
+ int count = change.count;
+
+ int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
- int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
if (index < 0) {
- int i = d->visibleItems.count() - 1;
- while (i > 0 && d->visibleItems.at(i)->index == -1)
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
--i;
- if (d->visibleItems.at(i)->index + 1 == modelIndex) {
+ if (visibleItems.at(i)->index + 1 == modelIndex) {
// Special case of appending an item to the model.
- index = d->visibleIndex + d->visibleItems.count();
+ index = visibleIndex + visibleItems.count();
} else {
- if (modelIndex <= d->visibleIndex) {
+ if (modelIndex <= visibleIndex) {
// Insert before visible items
- d->visibleIndex += count;
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = d->visibleItems.at(i);
+ visibleIndex += count;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
}
- if (d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem)
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- d->scheduleLayout();
- d->itemCount += count;
- emit countChanged();
- return;
+ return true;
}
}
int insertCount = count;
- if (index < d->visibleIndex && d->visibleItems.count()) {
- insertCount -= d->visibleIndex - index;
- index = d->visibleIndex;
- modelIndex = d->visibleIndex;
+ if (index < visibleIndex && visibleItems.count()) {
+ insertCount -= visibleIndex - index;
+ index = visibleIndex;
+ modelIndex = visibleIndex;
}
- qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+width()+1 : d->position();
- int to = d->buffer+tempPos+d->size()-1;
+ qreal tempPos = isRightToLeftTopToBottom() ? -position()-size()+q->width()+1 : position();
+ int to = buffer+tempPos+size()-1;
int colPos = 0;
int rowPos = 0;
- if (d->visibleItems.count()) {
- index -= d->visibleIndex;
- if (index < d->visibleItems.count()) {
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index));
+ if (visibleItems.count()) {
+ index -= visibleIndex;
+ if (index < visibleItems.count()) {
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index));
colPos = gridItem->colPos();
rowPos = gridItem->rowPos();
} else {
// appending items to visible list
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index-1));
- colPos = gridItem->colPos() + d->colSize();
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index-1));
+ colPos = gridItem->colPos() + colSize();
rowPos = gridItem->rowPos();
- if (colPos > d->colSize() * (d->columns-1)) {
+ if (colPos > colSize() * (columns-1)) {
colPos = 0;
- rowPos += d->rowSize();
+ rowPos += rowSize();
}
}
}
// Update the indexes of the following visible items.
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = d->visibleItems.at(i);
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
- bool addedVisible = false;
- QList<FxGridItemSG*> added;
int i = 0;
- while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
- if (!addedVisible) {
- d->scheduleLayout();
- addedVisible = true;
+ bool prevAddedCount = addedItems->count();
+ while (i < insertCount && rowPos <= to + rowSize()*(columns - (colPos/colSize()))/qreal(columns)) {
+ FxViewItem *item = 0;
+ if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
+ if (item->index > modelIndex + i)
+ movedBackwards->append(item);
+ item->index = modelIndex + i;
}
- FxGridItemSG *item = static_cast<FxGridItemSG*>(d->createItem(modelIndex + i));
- d->visibleItems.insert(index, item);
- item->setPosition(colPos, rowPos);
- added.append(item);
- colPos += d->colSize();
- if (colPos > d->colSize() * (d->columns-1)) {
+ if (!item)
+ item = createItem(modelIndex + i);
+ visibleItems.insert(index, item);
+ if (!change.isMove())
+ addedItems->append(item);
+ colPos += colSize();
+ if (colPos > colSize() * (columns-1)) {
colPos = 0;
- rowPos += d->rowSize();
+ rowPos += rowSize();
}
++index;
++i;
}
- if (i < insertCount) {
- // We didn't insert all our new items, which means anything
- // beyond the current index is not visible - remove it.
- while (d->visibleItems.count() > index) {
- d->releaseItem(d->visibleItems.takeLast());
- }
- }
-
- // update visibleIndex
- d->visibleIndex = 0;
- for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
-
- if (d->itemCount && d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem) {
- d->currentItem->index = d->currentIndex;
- static_cast<FxGridItemSG*>(d->currentItem)->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
- }
- emit currentIndexChanged();
- } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
- setCurrentIndex(0);
- }
-
- // everything is in order now - emit add() signal
- for (int j = 0; j < added.count(); ++j)
- added.at(j)->attached->emitAdd();
-
- d->itemCount += count;
- emit countChanged();
-}
-
-void QSGGridView::itemsRemoved(int modelIndex, int count)
-{
- Q_D(QSGGridView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
-
- d->itemCount -= count;
- bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
- bool removedVisible = false;
-
- // Remove the items from the visible list, skipping anything already marked for removal
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index == -1 || item->index < modelIndex) {
- // already removed, or before removed items
- if (item->index < modelIndex && !removedVisible) {
- d->scheduleLayout();
- removedVisible = true;
- }
- ++it;
- } else if (item->index >= modelIndex + count) {
- // after removed items
- item->index -= count;
- ++it;
- } else {
- // removed item
- if (!removedVisible) {
- d->scheduleLayout();
- removedVisible = true;
- }
- item->attached->emitRemove();
- if (item->attached->delayRemove()) {
- item->index = -1;
- connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
- ++it;
- } else {
- it = d->visibleItems.erase(it);
- d->releaseItem(item);
- }
- }
- }
-
- // update visibleIndex
- d->visibleIndex = 0;
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
-
- // fix current
- if (d->currentIndex >= modelIndex + count) {
- d->currentIndex -= count;
- if (d->currentItem)
- d->currentItem->index -= count;
- emit currentIndexChanged();
- } else if (currentRemoved) {
- // current item has been removed.
- d->releaseItem(d->currentItem);
- d->currentItem = 0;
- d->currentIndex = -1;
- if (d->itemCount)
- d->updateCurrent(qMin(modelIndex, d->itemCount-1));
- else
- emit currentIndexChanged();
- }
-
- if (removedVisible && d->visibleItems.isEmpty()) {
- d->timeline.clear();
- if (d->itemCount == 0) {
- d->setPosition(d->contentStartPosition());
- d->updateHeader();
- d->updateFooter();
- }
- }
-
- emit countChanged();
-}
-
-
-void QSGGridView::itemsMoved(int from, int to, int count)
-{
- Q_D(QSGGridView);
- if (!isComponentComplete() || !d->isValid())
- return;
- d->updateUnrequestedIndexes();
-
- if (d->visibleItems.isEmpty()) {
- d->refill();
- return;
- }
-
- d->moveReason = QSGGridViewPrivate::Other;
-
- bool movingBackwards = from > to;
- d->adjustMoveParameters(&from, &to, &count);
-
- QHash<int,FxGridItemSG*> moved;
- int moveByCount = 0;
- FxGridItemSG *firstVisible = static_cast<FxGridItemSG*>(d->firstVisibleItem());
- int firstItemIndex = firstVisible ? firstVisible->index : -1;
-
- // if visibleItems.first() is above the content start pos, and the items
- // beneath it are moved, ensure this first item is later repositioned correctly
- // (to above the next visible item) so that subsequent layout() is correct
- bool repositionFirstItem = firstVisible
- && d->visibleItems.first()->position() < firstVisible->position()
- && from > d->visibleItems.first()->index;
-
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index >= from && item->index < from + count) {
- // take the items that are moving
- item->index += (to-from);
- moved.insert(item->index, static_cast<FxGridItemSG*>(item));
- if (repositionFirstItem)
- moveByCount++;
- it = d->visibleItems.erase(it);
- } else {
- if (item->index > from && item->index != -1) {
- // move everything after the moved items.
- item->index -= count;
- if (item->index < d->visibleIndex)
- d->visibleIndex = item->index;
- }
- ++it;
- }
- }
-
- int movedCount = 0;
- int endIndex = d->visibleIndex;
- it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (movedCount < count && item->index >= to && item->index < to + count) {
- // place items in the target position, reusing any existing items
- int targetIndex = item->index + movedCount;
- FxGridItemSG *movedItem = moved.take(targetIndex);
- if (!movedItem)
- movedItem = static_cast<FxGridItemSG*>(d->createItem(targetIndex));
- it = d->visibleItems.insert(it, movedItem);
- ++it;
- ++movedCount;
- } else {
- if (item->index != -1) {
- if (item->index >= to) {
- // update everything after the moved items.
- item->index += count;
- }
- endIndex = item->index;
- }
- ++it;
- }
- }
-
- // If we have moved items to the end of the visible items
- // then add any existing moved items that we have
- while (FxGridItemSG *item = moved.take(endIndex+1)) {
- d->visibleItems.append(item);
- ++endIndex;
- }
-
- // update visibleIndex
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
- // if first visible item is moving but another item is moving up to replace it,
- // do this positioning now to avoid shifting all content forwards
- if (movingBackwards && firstItemIndex >= 0) {
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index == firstItemIndex) {
- static_cast<FxGridItemSG*>(*it)->setPosition(firstVisible->colPos(),
- firstVisible->rowPos());
- break;
- }
- }
- }
-
- // Fix current index
- if (d->currentIndex >= 0 && d->currentItem) {
- int oldCurrent = d->currentIndex;
- d->currentIndex = d->model->indexOf(d->currentItem->item, this);
- if (oldCurrent != d->currentIndex) {
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- }
-
- // Whatever moved items remain are no longer visible items.
- while (moved.count()) {
- int idx = moved.begin().key();
- FxGridItemSG *item = moved.take(idx);
- if (d->currentItem && item->item == d->currentItem->item)
- item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
- d->releaseItem(item);
- }
-
- // Ensure we don't cause an ugly list scroll.
- if (d->visibleItems.count() && moveByCount > 0) {
- FxGridItemSG *first = static_cast<FxGridItemSG*>(d->visibleItems.first());
- first->setPosition(first->colPos(), first->rowPos() + ((moveByCount / d->columns) * d->rowSize()));
- }
-
- d->layout();
+ return addedItems->count() > prevAddedCount;
}
/*!
@@ -2098,6 +1871,7 @@ void QSGGridView::itemsMoved(int from, int to, int count)
\bold Note: methods should only be called after the Component has completed.
*/
+
QSGGridViewAttached *QSGGridView::qmlAttachedProperties(QObject *obj)
{
return new QSGGridViewAttached(obj);
diff --git a/src/declarative/items/qsggridview_p.h b/src/declarative/items/qsggridview_p.h
index ae4ce346db..1cdf81d213 100644
--- a/src/declarative/items/qsggridview_p.h
+++ b/src/declarative/items/qsggridview_p.h
@@ -109,11 +109,6 @@ Q_SIGNALS:
protected:
virtual void viewportMoved();
virtual void keyPressEvent(QKeyEvent *);
-
-private Q_SLOTS:
- void itemsInserted(int index, int count);
- void itemsRemoved(int index, int count);
- void itemsMoved(int from, int to, int count);
};
class QSGGridViewAttached : public QSGItemViewAttached
diff --git a/src/declarative/items/qsgimagebase.cpp b/src/declarative/items/qsgimagebase.cpp
index f8f2183a15..5c6334de66 100644
--- a/src/declarative/items/qsgimagebase.cpp
+++ b/src/declarative/items/qsgimagebase.cpp
@@ -163,6 +163,12 @@ void QSGImageBase::setCache(bool cache)
load();
}
+QPixmap QSGImageBase::pixmap() const
+{
+ Q_D(const QSGImageBase);
+ return d->pix.pixmap();
+}
+
void QSGImageBase::setMirror(bool mirror)
{
Q_D(QSGImageBase);
diff --git a/src/declarative/items/qsgimagebase_p.h b/src/declarative/items/qsgimagebase_p.h
index 567c46d30b..e17ca3b059 100644
--- a/src/declarative/items/qsgimagebase_p.h
+++ b/src/declarative/items/qsgimagebase_p.h
@@ -79,6 +79,8 @@ public:
bool cache() const;
void setCache(bool);
+ QPixmap pixmap() const;
+
virtual void setSourceSize(const QSize&);
QSize sourceSize() const;
void resetSourceSize();
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index addb046e62..f3de1a6b3f 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -3192,6 +3192,18 @@ void QSGItemPrivate::setState(const QString &state)
_states()->setState(state);
}
+QString QSGItem::state() const
+{
+ Q_D(const QSGItem);
+ return d->state();
+}
+
+void QSGItem::setState(const QString &state)
+{
+ Q_D(QSGItem);
+ d->setState(state);
+}
+
QDeclarativeListProperty<QSGTransform> QSGItem::transform()
{
Q_D(QSGItem);
@@ -3469,9 +3481,21 @@ void QSGItem::setTransformOrigin(TransformOrigin origin)
QPointF QSGItem::transformOriginPoint() const
{
Q_D(const QSGItem);
+ if (!d->transformOriginPoint.isNull())
+ return d->transformOriginPoint;
return d->computeTransformOrigin();
}
+void QSGItem::setTransformOriginPoint(const QPointF &point)
+{
+ Q_D(QSGItem);
+ if (d->transformOriginPoint == point)
+ return;
+
+ d->transformOriginPoint = point;
+ d->dirty(QSGItemPrivate::TransformOrigin);
+}
+
qreal QSGItem::z() const
{
Q_D(const QSGItem);
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index 9cd549d3b8..6653a4fe1b 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -119,7 +119,7 @@ class Q_DECLARATIVE_EXPORT QSGItem : public QObject, public QDeclarativeParserSt
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QDeclarativeListProperty<QDeclarativeState> states READ states DESIGNABLE false)
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitions DESIGNABLE false)
- Q_PRIVATE_PROPERTY(QSGItem::d_func(), QString state READ state WRITE setState NOTIFY stateChanged)
+ Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QSGAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
Q_PRIVATE_PROPERTY(QSGItem::d_func(), QSGAnchorLine left READ left CONSTANT FINAL)
@@ -205,6 +205,9 @@ public:
bool clip() const;
void setClip(bool);
+ QString state() const;
+ void setState(const QString &);
+
qreal baselineOffset() const;
void setBaselineOffset(qreal);
@@ -232,6 +235,7 @@ public:
TransformOrigin transformOrigin() const;
void setTransformOrigin(TransformOrigin);
QPointF transformOriginPoint() const;
+ void setTransformOriginPoint(const QPointF &);
qreal z() const;
void setZ(qreal);
diff --git a/src/declarative/items/qsgitem_p.h b/src/declarative/items/qsgitem_p.h
index 513aba2bf6..e48c1043e5 100644
--- a/src/declarative/items/qsgitem_p.h
+++ b/src/declarative/items/qsgitem_p.h
@@ -300,6 +300,8 @@ public:
Qt::MouseButtons acceptedMouseButtons;
Qt::InputMethodHints imHints;
+ QPointF transformOriginPoint;
+
virtual qreal getImplicitWidth() const;
virtual qreal getImplicitHeight() const;
virtual void implicitWidthChanged();
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 0d147d31fc..2e24155b7d 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -61,6 +61,7 @@
#include "qsggridview_p.h"
#include "qsgpathview_p.h"
#include <private/qdeclarativepath_p.h>
+#include <private/qdeclarativepathinterpolator_p.h>
#include "qsgpositioners_p.h"
#include "qsgrepeater_p.h"
#include "qsgloader_p.h"
@@ -125,6 +126,9 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QDeclarativePathLine>(uri,major,minor,"PathLine");
qmlRegisterType<QDeclarativePathPercent>(uri,major,minor,"PathPercent");
qmlRegisterType<QDeclarativePathQuad>(uri,major,minor,"PathQuad");
+ qmlRegisterType<QDeclarativePathCatmullRomCurve>("QtQuick",2,0,"PathCurve");
+ qmlRegisterType<QDeclarativePathArc>("QtQuick",2,0,"PathArc");
+ qmlRegisterType<QDeclarativePathSvg>("QtQuick",2,0,"PathSvg");
qmlRegisterType<QSGPathView>(uri,major,minor,"PathView");
qmlRegisterUncreatableType<QSGBasePositioner>(uri,major,minor,"Positioner",
QStringLiteral("Positioner is an abstract type that is only available as an attached property."));
@@ -172,8 +176,8 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QSGShaderEffectItem>("QtQuick", 2, 0, "ShaderEffectItem"); // TODO: Remove after grace period.
qmlRegisterType<QSGShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
qmlRegisterType<QSGShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
- qmlRegisterUncreatableType<QSGShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QSGShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh.")); // TODO: Remove after grace period.
- qmlRegisterType<QSGGridMesh>("QtQuick", 2, 0, "GridMesh"); // TODO: Remove after grace period.
+ qmlRegisterUncreatableType<QSGShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QSGShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
+ qmlRegisterType<QSGGridMesh>("QtQuick", 2, 0, "GridMesh");
qmlRegisterUncreatableType<QSGPaintedItem>("QtQuick", 2, 0, "PaintedItem", QSGPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
@@ -189,6 +193,8 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QSGAnchorSet>();
qmlRegisterType<QSGAnchorAnimation>(uri, major, minor,"AnchorAnimation");
qmlRegisterType<QSGParentAnimation>(uri, major, minor,"ParentAnimation");
+ qmlRegisterType<QSGPathAnimation>("QtQuick",2,0,"PathAnimation");
+ qmlRegisterType<QDeclarativePathInterpolator>("QtQuick",2,0,"PathInterpolator");
qmlRegisterType<QSGDragTarget>("QtQuick", 2, 0, "DragTarget");
qmlRegisterType<QSGDragTargetEvent>();
diff --git a/src/declarative/items/qsgitemview.cpp b/src/declarative/items/qsgitemview.cpp
index 5543f12f6d..2b3f51b648 100644
--- a/src/declarative/items/qsgitemview.cpp
+++ b/src/declarative/items/qsgitemview.cpp
@@ -58,6 +58,102 @@ FxViewItem::~FxViewItem()
}
}
+
+QSGItemViewChangeSet::QSGItemViewChangeSet()
+ : active(false)
+{
+ reset();
+}
+
+bool QSGItemViewChangeSet::hasPendingChanges() const
+{
+ return !pendingChanges.isEmpty();
+}
+
+void QSGItemViewChangeSet::doInsert(int index, int count)
+{
+ pendingChanges.insert(index, count);
+
+ if (newCurrentIndex >= index) {
+ // adjust current item index
+ newCurrentIndex += count;
+ currentChanged = true;
+ } else if (newCurrentIndex < 0) {
+ newCurrentIndex = 0;
+ currentChanged = true;
+ }
+
+ itemCount += count;
+}
+
+void QSGItemViewChangeSet::doRemove(int index, int count)
+{
+ itemCount -= count;
+ pendingChanges.remove(index, count);
+
+ if (newCurrentIndex >= index + count) {
+ newCurrentIndex -= count;
+ currentChanged = true;
+ } else if (newCurrentIndex >= index && newCurrentIndex < index + count) {
+ // current item has been removed.
+ currentRemoved = true;
+ newCurrentIndex = -1;
+ if (itemCount)
+ newCurrentIndex = qMin(index, itemCount-1);
+ currentChanged = true;
+ }
+}
+
+void QSGItemViewChangeSet::doMove(int from, int to, int count)
+{
+ pendingChanges.move(from, to, count);
+
+ if (to > from) {
+ if (newCurrentIndex >= from) {
+ if (newCurrentIndex < from + count)
+ newCurrentIndex += (to-from);
+ else if (newCurrentIndex < to + count)
+ newCurrentIndex -= count;
+ }
+ currentChanged = true;
+ } else if (to < from) {
+ if (newCurrentIndex >= to) {
+ if (newCurrentIndex >= from && newCurrentIndex < from + count)
+ newCurrentIndex -= (from-to);
+ else if (newCurrentIndex < from)
+ newCurrentIndex += count;
+ }
+ currentChanged = true;
+ }
+}
+
+void QSGItemViewChangeSet::QSGItemViewChangeSet::doChange(int index, int count)
+{
+ pendingChanges.change(index, count);
+}
+
+void QSGItemViewChangeSet::prepare(int currentIndex, int count)
+{
+ if (active)
+ return;
+ reset();
+ active = true;
+ itemCount = count;
+ newCurrentIndex = currentIndex;
+}
+
+void QSGItemViewChangeSet::reset()
+{
+ itemCount = 0;
+ newCurrentIndex = -1;
+ pendingChanges.clear();
+ removedItems.clear();
+ active = false;
+ currentChanged = false;
+ currentRemoved = false;
+}
+
+
QSGItemView::QSGItemView(QSGFlickablePrivate &dd, QSGItem *parent)
: QSGFlickable(dd, parent)
{
@@ -81,6 +177,7 @@ QSGItem *QSGItemView::currentItem() const
Q_D(const QSGItemView);
if (!d->currentItem)
return 0;
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->currentItem->item;
}
@@ -213,14 +310,16 @@ void QSGItemView::setDelegate(QDeclarativeComponent *delegate)
int QSGItemView::count() const
{
Q_D(const QSGItemView);
- if (d->model)
- return d->model->count();
- return 0;
+ if (!d->model)
+ return 0;
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
+ return d->model->count();
}
int QSGItemView::currentIndex() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->currentIndex;
}
@@ -230,6 +329,8 @@ void QSGItemView::setCurrentIndex(int index)
if (d->requestedIndex >= 0) // currently creating item
return;
d->currentIndexCleared = (index == -1);
+
+ d->applyPendingChanges();
if (index == d->currentIndex)
return;
if (isComponentComplete() && d->isValid()) {
@@ -313,6 +414,7 @@ QDeclarativeComponent *QSGItemView::header() const
QSGItem *QSGItemView::headerItem() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->header ? d->header->item : 0;
}
@@ -320,6 +422,7 @@ void QSGItemView::setHeader(QDeclarativeComponent *headerComponent)
{
Q_D(QSGItemView);
if (d->headerComponent != headerComponent) {
+ d->applyPendingChanges();
delete d->header;
d->header = 0;
d->headerComponent = headerComponent;
@@ -348,6 +451,7 @@ QDeclarativeComponent *QSGItemView::footer() const
QSGItem *QSGItemView::footerItem() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->footer ? d->footer->item : 0;
}
@@ -355,6 +459,7 @@ void QSGItemView::setFooter(QDeclarativeComponent *footerComponent)
{
Q_D(QSGItemView);
if (d->footerComponent != footerComponent) {
+ d->applyPendingChanges();
delete d->footer;
d->footer = 0;
d->footerComponent = footerComponent;
@@ -373,6 +478,7 @@ void QSGItemView::setFooter(QDeclarativeComponent *footerComponent)
QDeclarativeComponent *QSGItemView::highlight() const
{
Q_D(const QSGItemView);
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
return d->highlightComponent;
}
@@ -380,6 +486,7 @@ void QSGItemView::setHighlight(QDeclarativeComponent *highlightComponent)
{
Q_D(QSGItemView);
if (highlightComponent != d->highlightComponent) {
+ d->applyPendingChanges();
d->highlightComponent = highlightComponent;
d->createHighlight();
if (d->currentItem)
@@ -391,9 +498,8 @@ void QSGItemView::setHighlight(QDeclarativeComponent *highlightComponent)
QSGItem *QSGItemView::highlightItem() const
{
Q_D(const QSGItemView);
- if (!d->highlight)
- return 0;
- return d->highlight->item;
+ const_cast<QSGItemViewPrivate*>(d)->applyPendingChanges();
+ return d->highlight ? d->highlight->item : 0;
}
bool QSGItemView::highlightFollowsCurrentItem() const
@@ -506,10 +612,10 @@ void QSGItemViewPrivate::positionViewAtIndex(int index, int mode)
return;
if (mode < QSGItemView::Beginning || mode > QSGItemView::Contain)
return;
+
+ applyPendingChanges();
int idx = qMax(qMin(index, model->count()-1), 0);
- if (layoutScheduled)
- layout();
qreal pos = isContentFlowReversed() ? -position() - size() : position();
FxViewItem *item = visibleItem(idx);
qreal maxExtent;
@@ -614,6 +720,12 @@ int QSGItemView::indexAt(qreal x, qreal y) const
return -1;
}
+void QSGItemViewPrivate::applyPendingChanges()
+{
+ Q_Q(QSGItemView);
+ if (q->isComponentComplete() && currentChanges.hasPendingChanges())
+ layout();
+}
// for debugging only
void QSGItemViewPrivate::checkVisible() const
@@ -629,8 +741,6 @@ void QSGItemViewPrivate::checkVisible() const
}
}
-
-
void QSGItemViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_Q(QSGItemView);
@@ -638,10 +748,19 @@ void QSGItemViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeo
if (!q->isComponentComplete())
return;
- if (header && header->item == item)
+ if (header && header->item == item) {
updateHeader();
- else if (footer && footer->item == item)
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ if (!q->isMoving() && !q->isFlicking())
+ fixupPosition();
+ } else if (footer && footer->item == item) {
updateFooter();
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ if (!q->isMoving() && !q->isFlicking())
+ fixupPosition();
+ }
if (currentItem && currentItem->item == item)
updateHighlight();
@@ -665,14 +784,55 @@ void QSGItemView::destroyRemoved()
// Correct the positioning of the items
d->updateSections();
+ d->forceLayout = true;
d->layout();
}
-void QSGItemView::itemsChanged(int, int)
+void QSGItemView::itemsInserted(int index, int count)
{
Q_D(QSGItemView);
- d->updateSections();
- d->layout();
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doInsert(index, count);
+ polish();
+}
+
+void QSGItemView::itemsRemoved(int index, int count)
+{
+ Q_D(QSGItemView);
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doRemove(index, count);
+ polish();
+}
+
+void QSGItemView::itemsMoved(int from, int to, int count)
+{
+ Q_D(QSGItemView);
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ if (from == to || count <= 0 || from < 0 || to < 0)
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doMove(from, to, count);
+ polish();
+}
+
+void QSGItemView::itemsChanged(int index, int count)
+{
+ Q_D(QSGItemView);
+ if (!isComponentComplete() || !d->model || !d->model->isValid())
+ return;
+
+ d->currentChanges.prepare(d->currentIndex, d->itemCount);
+ d->currentChanges.doChange(index, count);
+ polish();
}
void QSGItemView::modelReset()
@@ -796,7 +956,6 @@ void QSGItemView::trackedPositionChanged()
}
}
-
void QSGItemView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QSGItemView);
@@ -814,7 +973,7 @@ qreal QSGItemView::minYExtent() const
if (d->minExtentDirty) {
d->minExtent = -d->startPosition();
- if (d->header && d->visibleItems.count())
+ if (d->header)
d->minExtent += d->headerSize();
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
d->minExtent += d->highlightRangeStart;
@@ -885,7 +1044,7 @@ qreal QSGItemView::minXExtent() const
endPositionFirstItem = d->endPositionAt(0);
highlightStart = d->highlightRangeStart;
highlightEnd = d->highlightRangeEnd;
- if (d->header && d->visibleItems.count())
+ if (d->header)
d->minExtent += d->headerSize();
}
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
@@ -934,7 +1093,7 @@ qreal QSGItemView::maxXExtent() const
d->maxExtent = -(d->endPosition() - width());
}
if (d->isContentFlowReversed()) {
- if (d->header && d->visibleItems.count())
+ if (d->header)
d->maxExtent -= d->headerSize();
} else {
if (d->footer)
@@ -1017,7 +1176,7 @@ QSGItemViewPrivate::QSGItemViewPrivate()
, headerComponent(0), header(0), footerComponent(0), footer(0)
, minExtent(0), maxExtent(0)
, ownModel(false), wrap(false), lazyRelease(false), deferredRelease(false)
- , layoutScheduled(false), inViewportMoved(false), currentIndexCleared(false)
+ , inApplyModelChanges(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
, minExtentDirty(true), maxExtentDirty(true)
{
@@ -1082,7 +1241,7 @@ FxViewItem *QSGItemViewPrivate::firstVisibleItem() const {
const qreal pos = isContentFlowReversed() ? -position()-size() : position();
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
- if (item->index != -1 && item->endPosition() >= pos)
+ if (item->index != -1 && item->endPosition() > pos)
return item;
}
return visibleItems.count() ? visibleItems.first() : 0;
@@ -1105,18 +1264,6 @@ int QSGItemViewPrivate::mapFromModel(int modelIndex) const
return -1; // Not in visibleList
}
-void QSGItemViewPrivate::adjustMoveParameters(int *from, int *to, int *count) const
-{
- if (*from > *to) {
- // Only move forwards - flip if backwards moving
- int tfrom = *from;
- int tto = *to;
- *from = tto;
- *to = tto + *count;
- *count = tfrom - tto;
- }
-}
-
void QSGItemViewPrivate::init()
{
Q_Q(QSGItemView);
@@ -1130,6 +1277,8 @@ void QSGItemViewPrivate::init()
void QSGItemViewPrivate::updateCurrent(int modelIndex)
{
Q_Q(QSGItemView);
+ applyPendingChanges();
+
if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
currentItem->attached->setIsCurrentItem(false);
@@ -1168,6 +1317,7 @@ void QSGItemViewPrivate::updateCurrent(int modelIndex)
void QSGItemViewPrivate::clear()
{
+ currentChanges.reset();
timeline.clear();
for (int i = 0; i < visibleItems.count(); ++i)
@@ -1207,6 +1357,9 @@ void QSGItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
if (!isValid() || !q->isComponentComplete())
return;
+ currentChanges.reset();
+
+ int prevCount = itemCount;
itemCount = model->count();
qreal bufferFrom = from - buffer;
qreal bufferTo = to + buffer;
@@ -1240,12 +1393,15 @@ void QSGItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
}
lazyRelease = false;
+ if (prevCount != itemCount)
+ emit q->countChanged();
}
void QSGItemViewPrivate::regenerate()
{
Q_Q(QSGItemView);
if (q->isComponentComplete()) {
+ currentChanges.reset();
delete header;
header = 0;
delete footer;
@@ -1260,15 +1416,6 @@ void QSGItemViewPrivate::regenerate()
}
}
-void QSGItemViewPrivate::scheduleLayout()
-{
- Q_Q(QSGItemView);
- if (!layoutScheduled) {
- layoutScheduled = true;
- q->polish();
- }
-}
-
void QSGItemViewPrivate::updateViewport()
{
Q_Q(QSGItemView);
@@ -1283,13 +1430,16 @@ void QSGItemViewPrivate::updateViewport()
void QSGItemViewPrivate::layout()
{
Q_Q(QSGItemView);
- layoutScheduled = false;
if (!isValid() && !visibleItems.count()) {
clear();
setPosition(contentStartPosition());
return;
}
+ if (!applyModelChanges() && !forceLayout)
+ return;
+ forceLayout = false;
+
layoutVisibleItems();
refill();
@@ -1297,6 +1447,7 @@ void QSGItemViewPrivate::layout()
maxExtentDirty = true;
updateHighlight();
+
if (!q->isMoving() && !q->isFlicking()) {
fixupPosition();
refill();
@@ -1308,6 +1459,134 @@ void QSGItemViewPrivate::layout()
updateUnrequestedPositions();
}
+bool QSGItemViewPrivate::applyModelChanges()
+{
+ Q_Q(QSGItemView);
+ if (!q->isComponentComplete() || !currentChanges.hasPendingChanges() || inApplyModelChanges)
+ return false;
+ inApplyModelChanges = true;
+
+ updateUnrequestedIndexes();
+ moveReason = QSGItemViewPrivate::Other;
+
+ int prevCount = itemCount;
+ bool removedVisible = false;
+
+ FxViewItem *firstVisible = firstVisibleItem();
+ FxViewItem *origVisibleItemsFirst = visibleItems.count() ? visibleItems.first() : 0;
+ int firstItemIndex = firstVisible ? firstVisible->index : -1;
+ QList<FxViewItem *> removedBeforeFirstVisible;
+
+ const QVector<QDeclarativeChangeSet::Remove> &removals = currentChanges.pendingChanges.removes();
+ for (int i=0; i<removals.count(); i++) {
+ itemCount -= removals[i].count;
+
+ // Remove the items from the visible list, skipping anything already marked for removal
+ QList<FxViewItem*>::Iterator it = visibleItems.begin();
+ while (it != visibleItems.end()) {
+ FxViewItem *item = *it;
+ if (item->index == -1 || item->index < removals[i].index) {
+ // already removed, or before removed items
+ if (item->index < removals[i].index && !removedVisible)
+ removedVisible = true;
+ ++it;
+ } else if (item->index >= removals[i].index + removals[i].count) {
+ // after removed items
+ item->index -= removals[i].count;
+ ++it;
+ } else {
+ // removed item
+ removedVisible = true;
+ if (!removals[i].isMove())
+ item->attached->emitRemove();
+
+ if (item->attached->delayRemove() && !removals[i].isMove()) {
+ item->index = -1;
+ QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
+ ++it;
+ } else {
+ if (firstVisible && item->position() < firstVisible->position() && item != visibleItems.first())
+ removedBeforeFirstVisible.append(item);
+ if (removals[i].isMove()) {
+ currentChanges.removedItems.insert(removals[i].moveKey(item->index), item);
+ } else {
+ if (item == firstVisible)
+ firstVisible = 0;
+ currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item);
+ }
+ it = visibleItems.erase(it);
+ }
+ }
+ }
+
+ }
+ if (!removals.isEmpty())
+ updateVisibleIndex();
+
+ const QVector<QDeclarativeChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts();
+ bool addedVisible = false;
+ QList<FxViewItem *> addedItems;
+ QList<FxViewItem *> movedBackwards;
+
+ for (int i=0; i<insertions.count(); i++) {
+ bool wasEmpty = visibleItems.isEmpty();
+ if (applyInsertionChange(insertions[i], &movedBackwards, &addedItems, firstVisible))
+ addedVisible = true;
+ if (wasEmpty && !visibleItems.isEmpty())
+ resetFirstItemPosition();
+ itemCount += insertions[i].count;
+ updateVisibleIndex();
+ }
+ for (int i=0; i<addedItems.count(); ++i)
+ addedItems.at(i)->attached->emitAdd();
+
+ // if first visible item is moving but another item is moving up to replace it,
+ // do this positioning now to avoid shifting all content forwards
+ if (firstVisible && firstItemIndex >= 0) {
+ for (int i=0; i<movedBackwards.count(); i++) {
+ if (movedBackwards[i]->index == firstItemIndex) {
+ resetItemPosition(movedBackwards[i], firstVisible);
+ movedBackwards.removeAt(i);
+ break;
+ }
+ }
+ }
+
+ // Ensure we don't cause an ugly list scroll
+ if (firstVisible && visibleItems.count() && visibleItems.first() != firstVisible) {
+ // ensure first item is placed at correct postion if moving backward
+ // since it will be used to position all subsequent items
+ if (movedBackwards.count() && origVisibleItemsFirst)
+ resetItemPosition(visibleItems.first(), origVisibleItemsFirst);
+ moveItemBy(visibleItems.first(), removedBeforeFirstVisible, movedBackwards);
+ }
+
+ // Whatever removed/moved items remain are no longer visible items.
+ for (QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin();
+ it != currentChanges.removedItems.end(); ++it) {
+ releaseItem(it.value());
+ }
+ currentChanges.removedItems.clear();
+
+ if (currentChanges.currentChanged) {
+ if (currentChanges.currentRemoved && currentItem) {
+ currentItem->attached->setIsCurrentItem(false);
+ releaseItem(currentItem);
+ currentItem = 0;
+ }
+ if (!currentIndexCleared)
+ updateCurrent(currentChanges.newCurrentIndex);
+ }
+ currentChanges.reset();
+
+ updateSections();
+ if (prevCount != itemCount)
+ emit q->countChanged();
+
+ inApplyModelChanges = false;
+ return removedVisible || addedVisible || !currentChanges.pendingChanges.changes().isEmpty();
+}
+
FxViewItem *QSGItemViewPrivate::createItem(int modelIndex)
{
Q_Q(QSGItemView);
@@ -1415,4 +1694,15 @@ void QSGItemViewPrivate::updateUnrequestedPositions()
repositionPackageItemAt(it.key(), it.value());
}
+void QSGItemViewPrivate::updateVisibleIndex()
+{
+ visibleIndex = 0;
+ for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end(); ++it) {
+ if ((*it)->index != -1) {
+ visibleIndex = (*it)->index;
+ break;
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgitemview_p.h b/src/declarative/items/qsgitemview_p.h
index b784015f66..b1093ffdbe 100644
--- a/src/declarative/items/qsgitemview_p.h
+++ b/src/declarative/items/qsgitemview_p.h
@@ -191,13 +191,17 @@ protected:
protected slots:
virtual void updateSections() {}
void destroyRemoved();
- void itemsChanged(int index, int count);
void createdItem(int index, QSGItem *item);
void modelReset();
void destroyingItem(QSGItem *item);
void animStopped();
void trackedPositionChanged();
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count);
+
private:
Q_DECLARE_PRIVATE(QSGItemView)
};
diff --git a/src/declarative/items/qsgitemview_p_p.h b/src/declarative/items/qsgitemview_p_p.h
index f20f4cca3e..2164dd60f4 100644
--- a/src/declarative/items/qsgitemview_p_p.h
+++ b/src/declarative/items/qsgitemview_p_p.h
@@ -45,6 +45,7 @@
#include "qsgitemview_p.h"
#include "qsgflickable_p_p.h"
#include "qsgvisualitemmodel_p.h"
+#include <private/qdeclarativechangeset_p.h>
QT_BEGIN_HEADER
@@ -73,6 +74,30 @@ public:
QSGItemViewAttached *attached;
};
+class QSGItemViewChangeSet
+{
+public:
+ QSGItemViewChangeSet();
+
+ bool hasPendingChanges() const;
+ void prepare(int currentIndex, int count);
+ void reset();
+
+ void doInsert(int index, int count);
+ void doRemove(int index, int count);
+ void doMove(int from, int to, int count);
+ void doChange(int index, int count);
+
+ int itemCount;
+ int newCurrentIndex;
+ QDeclarativeChangeSet pendingChanges;
+ QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *> removedItems;
+
+ bool active : 1;
+ bool currentChanged : 1;
+ bool currentRemoved : 1;
+};
+
class QSGItemViewPrivate : public QSGFlickablePrivate
{
Q_DECLARE_PUBLIC(QSGItemView)
@@ -92,7 +117,6 @@ public:
FxViewItem *visibleItem(int modelIndex) const;
FxViewItem *firstVisibleItem() const;
int mapFromModel(int modelIndex) const;
- void adjustMoveParameters(int *from, int *to, int *count) const;
virtual void init();
virtual void clear();
@@ -102,7 +126,6 @@ public:
void layout();
void refill();
void refill(qreal from, qreal to, bool doBuffer = false);
- void scheduleLayout();
void mirrorChange();
FxViewItem *createItem(int modelIndex);
@@ -115,7 +138,10 @@ public:
void updateTrackedItem();
void updateUnrequestedIndexes();
void updateUnrequestedPositions();
+ void updateVisibleIndex();
void positionViewAtIndex(int index, int mode);
+ void applyPendingChanges();
+ bool applyModelChanges();
void checkVisible() const;
@@ -135,6 +161,7 @@ public:
FxViewItem *trackedItem;
QHash<QSGItem*,int> unrequestedItems;
int requestedIndex;
+ QSGItemViewChangeSet currentChanges;
// XXX split into struct
QDeclarativeComponent *highlightComponent;
@@ -156,8 +183,9 @@ public:
bool wrap : 1;
bool lazyRelease : 1;
bool deferredRelease : 1;
- bool layoutScheduled : 1;
+ bool inApplyModelChanges : 1;
bool inViewportMoved : 1;
+ bool forceLayout : 1;
bool currentIndexCleared : 1;
bool haveHighlightRange : 1;
bool autoHighlight : 1;
@@ -189,15 +217,19 @@ protected:
virtual void setPosition(qreal pos) = 0;
virtual void fixupPosition() = 0;
- virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer) = 0;
- virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo) = 0;
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) = 0;
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
virtual void visibleItemsChanged() = 0;
virtual FxViewItem *newViewItem(int index, QSGItem *item) = 0;
virtual void repositionPackageItemAt(QSGItem *item, int index) = 0;
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem) = 0;
+ virtual void resetFirstItemPosition() = 0;
+ virtual void moveItemBy(FxViewItem *item, const QList<FxViewItem *> &, const QList<FxViewItem *> &) = 0;
virtual void layoutVisibleItems() = 0;
virtual void changedVisibleIndex(int newIndex) = 0;
+ virtual bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, QList<FxViewItem *> *, QList<FxViewItem *> *, FxViewItem *) = 0;
virtual void initializeViewItem(FxViewItem *) {}
virtual void initializeCurrentItem() {}
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index 3be4a4bd58..e8a6bf2d50 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -201,14 +201,17 @@ public:
virtual void init();
virtual void clear();
- virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
- virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual void visibleItemsChanged();
virtual FxViewItem *newViewItem(int index, QSGItem *item);
virtual void initializeViewItem(FxViewItem *item);
virtual void releaseItem(FxViewItem *item);
virtual void repositionPackageItemAt(QSGItem *item, int index);
+ virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem);
+ virtual void resetFirstItemPosition();
+ virtual void moveItemBy(FxViewItem *item, const QList<FxViewItem *> &items, const QList<FxViewItem *> &movedBackwards);
virtual void createHighlight();
virtual void updateHighlight();
@@ -216,6 +219,7 @@ public:
virtual void setPosition(qreal pos);
virtual void layoutVisibleItems();
+ bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, QList<FxViewItem *> *, QList<FxViewItem *> *, FxViewItem *firstVisible);
virtual void updateSections();
void createSection(FxListItemSG *);
@@ -535,7 +539,7 @@ void QSGListViewPrivate::releaseItem(FxViewItem *item)
QSGItemViewPrivate::releaseItem(item);
}
-bool QSGListViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
+bool QSGListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
{
qreal itemEnd = visiblePos;
if (visibleItems.count()) {
@@ -599,7 +603,7 @@ bool QSGListViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer
return changed;
}
-bool QSGListViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+bool QSGListViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
{
FxViewItem *item = 0;
bool changed = false;
@@ -684,6 +688,27 @@ void QSGListViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
}
}
+void QSGListViewPrivate::resetItemPosition(FxViewItem *item, FxViewItem *toItem)
+{
+ static_cast<FxListItemSG*>(item)->setPosition(toItem->position());
+}
+
+void QSGListViewPrivate::resetFirstItemPosition()
+{
+ FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.first());
+ item->setPosition(0);
+}
+
+void QSGListViewPrivate::moveItemBy(FxViewItem *item, const QList<FxViewItem *> &forwards, const QList<FxViewItem *> &backwards)
+{
+ qreal pos = 0;
+ for (int i=0; i<forwards.count(); i++)
+ pos += forwards[i]->size();
+ for (int i=0; i<backwards.count(); i++)
+ pos -= backwards[i]->size();
+ static_cast<FxListItemSG*>(item)->setPosition(item->position() + pos);
+}
+
void QSGListViewPrivate::createHighlight()
{
Q_Q(QSGListView);
@@ -733,6 +758,8 @@ void QSGListViewPrivate::createHighlight()
void QSGListViewPrivate::updateHighlight()
{
+ applyPendingChanges();
+
if ((!currentItem && highlight) || (currentItem && !highlight))
createHighlight();
bool strictHighlight = haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange;
@@ -1009,7 +1036,8 @@ void QSGListViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeo
if (item != contentItem && (!highlight || item != highlight->item)) {
if ((orient == QSGListView::Vertical && newGeometry.height() != oldGeometry.height())
|| (orient == QSGListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
- scheduleLayout();
+ forceLayout = true;
+ q->polish();
}
}
}
@@ -1565,6 +1593,7 @@ void QSGListView::setSpacing(qreal spacing)
Q_D(QSGListView);
if (spacing != d->spacing) {
d->spacing = spacing;
+ d->forceLayout = true;
d->layout();
emit spacingChanged();
}
@@ -2067,373 +2096,109 @@ void QSGListView::updateSections()
roles << d->sectionCriteria->property().toUtf8();
d->model->setWatchedRoles(roles);
d->updateSections();
- if (d->itemCount)
+ if (d->itemCount) {
+ d->forceLayout = true;
d->layout();
+ }
}
}
-void QSGListView::itemsInserted(int modelIndex, int count)
+bool QSGListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, QList<FxViewItem *> *movedBackwards, QList<FxViewItem *> *addedItems, FxViewItem *firstVisible)
{
- Q_D(QSGListView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
- d->updateUnrequestedIndexes();
- d->moveReason = QSGListViewPrivate::Other;
+ Q_Q(QSGListView);
+
+ int modelIndex = change.index;
+ int count = change.count;
+
+
+ qreal tempPos = isRightToLeft() ? -position()-size() : position();
+ int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
- qreal tempPos = d->isRightToLeft() ? -d->position()-d->size() : d->position();
- int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
if (index < 0) {
- int i = d->visibleItems.count() - 1;
- while (i > 0 && d->visibleItems.at(i)->index == -1)
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
--i;
- if (i == 0 && d->visibleItems.first()->index == -1) {
+ if (i == 0 && visibleItems.first()->index == -1) {
// there are no visible items except items marked for removal
- index = d->visibleItems.count();
- } else if (d->visibleItems.at(i)->index + 1 == modelIndex
- && d->visibleItems.at(i)->endPosition() <= d->buffer+tempPos+d->size()) {
+ index = visibleItems.count();
+ } else if (visibleItems.at(i)->index + 1 == modelIndex
+ && visibleItems.at(i)->endPosition() <= buffer+tempPos+size()) {
// Special case of appending an item to the model.
- index = d->visibleItems.count();
+ index = visibleItems.count();
} else {
- if (modelIndex < d->visibleIndex) {
+ if (modelIndex < visibleIndex) {
// Insert before visible items
- d->visibleIndex += count;
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxViewItem *item = d->visibleItems.at(i);
+ visibleIndex += count;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex)
item->index += count;
}
}
- if (d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem)
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- d->scheduleLayout();
- d->itemCount += count;
- emit countChanged();
- return;
+ return true;
}
}
// index can be the next item past the end of the visible items list (i.e. appended)
int pos = 0;
- if (d->visibleItems.count()) {
- pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
- : d->visibleItems.last()->endPosition()+d->spacing;
+ if (visibleItems.count()) {
+ pos = index < visibleItems.count() ? visibleItems.at(index)->position()
+ : visibleItems.last()->endPosition()+spacing;
}
- int initialPos = pos;
- int diff = 0;
- QList<FxListItemSG*> added;
- bool addedVisible = false;
- FxViewItem *firstVisible = d->firstVisibleItem();
+ int prevAddedCount = addedItems->count();
if (firstVisible && pos < firstVisible->position()) {
// Insert items before the visible item.
int insertionIdx = index;
int i = 0;
- int from = tempPos - d->buffer;
+ int from = tempPos - buffer;
+
for (i = count-1; i >= 0 && pos > from; --i) {
- if (!addedVisible) {
- d->scheduleLayout();
- addedVisible = true;
+ FxViewItem *item = 0;
+ if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
+ if (item->index > modelIndex + i)
+ movedBackwards->append(item);
+ item->index = modelIndex + i;
}
- FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
- d->visibleItems.insert(insertionIdx, item);
- pos -= item->size() + d->spacing;
- item->setPosition(pos);
+ if (!item)
+ item = createItem(modelIndex + i);
+
+ visibleItems.insert(insertionIdx, item);
+ if (!change.isMove())
+ addedItems->append(item);
+ pos -= item->size() + spacing;
index++;
}
- if (i >= 0) {
- // If we didn't insert all our new items - anything
- // before the current index is not visible - remove it.
- while (insertionIdx--) {
- FxListItemSG *item = static_cast<FxListItemSG*>(d->visibleItems.takeFirst());
- if (item->index != -1)
- d->visibleIndex++;
- d->releaseItem(item);
- }
- } else {
- // adjust pos of items before inserted items.
- for (int i = insertionIdx-1; i >= 0; i--) {
- FxListItemSG *listItem = static_cast<FxListItemSG*>(d->visibleItems.at(i));
- listItem->setPosition(listItem->position() - (initialPos - pos));
- }
- }
} else {
int i = 0;
- int to = d->buffer+tempPos+d->size();
+ int to = buffer+tempPos+size();
for (i = 0; i < count && pos <= to; ++i) {
- if (!addedVisible) {
- d->scheduleLayout();
- addedVisible = true;
- }
- FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
- d->visibleItems.insert(index, item);
- item->setPosition(pos);
- added.append(item);
- pos += item->size() + d->spacing;
- ++index;
- }
- if (i != count) {
- // We didn't insert all our new items, which means anything
- // beyond the current index is not visible - remove it.
- while (d->visibleItems.count() > index)
- d->releaseItem(d->visibleItems.takeLast());
- }
- diff = pos - initialPos;
- }
- if (d->itemCount && d->currentIndex >= modelIndex) {
- // adjust current item index
- d->currentIndex += count;
- if (d->currentItem) {
- d->currentItem->index = d->currentIndex;
- static_cast<FxListItemSG *>(d->currentItem)->setPosition(static_cast<FxListItemSG *>(d->currentItem)->position() + diff);
- }
- emit currentIndexChanged();
- } else if (!d->itemCount && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
- d->updateCurrent(0);
- }
- // Update the indexes of the following visible items.
- for (; index < d->visibleItems.count(); ++index) {
- FxViewItem *item = d->visibleItems.at(index);
- if (d->currentItem && item->item != d->currentItem->item)
- static_cast<FxListItemSG*>(item)->setPosition(item->position() + diff);
- if (item->index != -1)
- item->index += count;
- }
- // everything is in order now - emit add() signal
- for (int j = 0; j < added.count(); ++j)
- added.at(j)->attached->emitAdd();
-
- d->updateSections();
- d->itemCount += count;
- emit countChanged();
-}
-
-void QSGListView::itemsRemoved(int modelIndex, int count)
-{
- Q_D(QSGListView);
- if (!isComponentComplete() || !d->model || !d->model->isValid())
- return;
- d->moveReason = QSGListViewPrivate::Other;
- d->updateUnrequestedIndexes();
- d->itemCount -= count;
-
- FxViewItem *firstVisible = d->firstVisibleItem();
- int preRemovedSize = 0;
- bool removedVisible = false;
- // Remove the items from the visible list, skipping anything already marked for removal
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index == -1 || item->index < modelIndex) {
- // already removed, or before removed items
- ++it;
- } else if (item->index >= modelIndex + count) {
- // after removed items
- item->index -= count;
- ++it;
- } else {
- // removed item
- if (!removedVisible) {
- d->scheduleLayout();
- removedVisible = true;
- }
- item->attached->emitRemove();
- if (item->attached->delayRemove()) {
- item->index = -1;
- connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
- ++it;
- } else {
- if (item == firstVisible)
- firstVisible = 0;
- if (firstVisible && item->position() < firstVisible->position())
- preRemovedSize += item->size();
- it = d->visibleItems.erase(it);
- d->releaseItem(item);
+ FxViewItem *item = 0;
+ if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
+ if (item->index > modelIndex + i)
+ movedBackwards->append(item);
+ item->index = modelIndex + i;
}
- }
- }
+ if (!item)
+ item = createItem(modelIndex + i);
- if (firstVisible && d->visibleItems.first() != firstVisible)
- static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + preRemovedSize);
-
- // update visibleIndex
- bool haveVisibleIndex = false;
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- haveVisibleIndex = true;
- break;
- }
- }
-
- // fix current
- if (d->currentIndex >= modelIndex + count) {
- d->currentIndex -= count;
- if (d->currentItem)
- d->currentItem->index -= count;
- emit currentIndexChanged();
- } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
- // current item has been removed.
- if (d->currentItem) {
- d->currentItem->attached->setIsCurrentItem(false);
- d->releaseItem(d->currentItem);
- d->currentItem = 0;
+ visibleItems.insert(index, item);
+ if (!change.isMove())
+ addedItems->append(item);
+ pos += item->size() + spacing;
+ ++index;
}
- d->currentIndex = -1;
- if (d->itemCount)
- d->updateCurrent(qMin(modelIndex, d->itemCount-1));
- else
- emit currentIndexChanged();
}
- if (!haveVisibleIndex) {
- d->timeline.clear();
- if (removedVisible && d->itemCount == 0) {
- d->visibleIndex = 0;
- d->visiblePos = 0;
- d->setPosition(d->contentStartPosition());
- d->updateHeader();
- d->updateFooter();
- } else {
- if (modelIndex < d->visibleIndex)
- d->visibleIndex = modelIndex+1;
- d->visibleIndex = qMax(qMin(d->visibleIndex, d->itemCount-1), 0);
- }
+ for (; index < visibleItems.count(); ++index) {
+ FxViewItem *item = visibleItems.at(index);
+ if (item->index != -1)
+ item->index += count;
}
- d->updateSections();
- emit countChanged();
+ return addedItems->count() > prevAddedCount;
}
-void QSGListView::itemsMoved(int from, int to, int count)
-{
- Q_D(QSGListView);
- if (!isComponentComplete() || !d->isValid())
- return;
- d->updateUnrequestedIndexes();
-
- if (d->visibleItems.isEmpty()) {
- d->refill();
- return;
- }
-
- d->moveReason = QSGListViewPrivate::Other;
-
- bool movingBackwards = from > to;
- d->adjustMoveParameters(&from, &to, &count);
-
- QHash<int,FxViewItem*> moved;
- int moveBy = 0;
- FxViewItem *firstVisible = d->firstVisibleItem();
- int firstItemIndex = firstVisible ? firstVisible->index : -1;
-
- // if visibleItems.first() is above the content start pos, and the items
- // beneath it are moved, ensure this first item is later repositioned correctly
- // (to above the next visible item) so that subsequent layout() is correct
- bool repositionFirstItem = firstVisible
- && d->visibleItems.first()->position() < firstVisible->position()
- && from > d->visibleItems.first()->index;
-
- QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (item->index >= from && item->index < from + count) {
- // take the items that are moving
- item->index += (to-from);
- moved.insert(item->index, item);
- if (repositionFirstItem)
- moveBy += item->size();
- it = d->visibleItems.erase(it);
- } else {
- // move everything after the moved items.
- if (item->index > from && item->index != -1)
- item->index -= count;
- ++it;
- }
- }
-
- int movedCount = 0;
- int endIndex = d->visibleIndex;
- it = d->visibleItems.begin();
- while (it != d->visibleItems.end()) {
- FxViewItem *item = *it;
- if (movedCount < count && item->index >= to && item->index < to + count) {
- // place items in the target position, reusing any existing items
- int targetIndex = item->index + movedCount;
- FxViewItem *movedItem = moved.take(targetIndex);
- if (!movedItem)
- movedItem = d->createItem(targetIndex);
- it = d->visibleItems.insert(it, movedItem);
- ++it;
- ++movedCount;
- } else {
- if (item->index != -1) {
- if (item->index >= to) {
- // update everything after the moved items.
- item->index += count;
- }
- endIndex = item->index;
- }
- ++it;
- }
- }
-
- // If we have moved items to the end of the visible items
- // then add any existing moved items that we have
- while (FxViewItem *item = moved.take(endIndex+1)) {
- d->visibleItems.append(item);
- ++endIndex;
- }
-
- // update visibleIndex
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index != -1) {
- d->visibleIndex = (*it)->index;
- break;
- }
- }
-
- // if first visible item is moving but another item is moving up to replace it,
- // do this positioning now to avoid shifting all content forwards
- if (movingBackwards && firstItemIndex >= 0) {
- for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
- if ((*it)->index == firstItemIndex) {
- static_cast<FxListItemSG*>(*it)->setPosition(firstVisible->position());
- break;
- }
- }
- }
-
- // Fix current index
- if (d->currentIndex >= 0 && d->currentItem) {
- int oldCurrent = d->currentIndex;
- d->currentIndex = d->model->indexOf(d->currentItem->item, this);
- if (oldCurrent != d->currentIndex) {
- d->currentItem->index = d->currentIndex;
- emit currentIndexChanged();
- }
- }
-
- // Whatever moved items remain are no longer visible items.
- while (moved.count()) {
- int idx = moved.begin().key();
- FxViewItem *item = moved.take(idx);
- if (d->currentItem && item->item == d->currentItem->item)
- static_cast<FxListItemSG*>(item)->setPosition(d->positionAt(idx));
- d->releaseItem(item);
- }
-
- // Ensure we don't cause an ugly list scroll.
- if (d->visibleItems.count())
- static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + moveBy);
-
- d->updateSections();
- d->layout();
-}
/*!
\qmlmethod QtQuick2::ListView::positionViewAtIndex(int index, PositionMode mode)
diff --git a/src/declarative/items/qsglistview_p.h b/src/declarative/items/qsglistview_p.h
index e45e16b85d..8ff4b05346 100644
--- a/src/declarative/items/qsglistview_p.h
+++ b/src/declarative/items/qsglistview_p.h
@@ -166,11 +166,6 @@ protected:
protected Q_SLOTS:
void updateSections();
-
-private Q_SLOTS:
- void itemsInserted(int index, int count);
- void itemsRemoved(int index, int count);
- void itemsMoved(int from, int to, int count);
};
class QSGListViewAttached : public QSGItemViewAttached
diff --git a/src/declarative/items/qsgshadereffect.cpp b/src/declarative/items/qsgshadereffect.cpp
index 7f7bff7719..f4ad80ea1e 100644
--- a/src/declarative/items/qsgshadereffect.cpp
+++ b/src/declarative/items/qsgshadereffect.cpp
@@ -191,7 +191,7 @@ QSGShaderEffectItem::QSGShaderEffectItem(QSGItem *parent)
QSGShaderEffect::QSGShaderEffect(QSGItem *parent)
: QSGItem(parent)
, m_meshResolution(1, 1)
- , m_deprecatedMesh(0)
+ , m_mesh(0)
, m_cullMode(NoCulling)
, m_blending(true)
, m_dirtyData(true)
@@ -275,63 +275,34 @@ void QSGShaderEffect::setBlending(bool enable)
}
/*!
- \qmlproperty size QtQuick2::ShaderEffect::mesh
+ \qmlproperty variant QtQuick2::ShaderEffect::mesh
- This property holds the mesh resolution. The default resolution is 1x1
- which is the minimum and corresponds to a mesh with four vertices.
- For non-linear vertex transformations, you probably want to set the
- resolution higher.
+ This property defines the mesh used to draw the ShaderEffect. It can hold
+ any mesh object deriving from \l QSGShaderEffectMesh, such as \l GridMesh.
+ If a size value is assigned to this property, the ShaderEffect implicitly
+ uses a \l GridMesh with the value as
+ \l{GridMesh::resolution}{mesh resolution}. By default, this property is
+ the size 1x1.
- \row
- \o \image declarative-gridmesh.png
- \o \qml
- import QtQuick 2.0
-
- ShaderEffect {
- width: 200
- height: 200
- mesh: Qt.size(20, 20)
- property variant source: Image {
- source: "qt-logo.png"
- sourceSize { width: 200; height: 200 }
- smooth: true
- }
- vertexShader: "
- uniform highp mat4 qt_Matrix;
- attribute highp vec4 qt_Vertex;
- attribute highp vec2 qt_MultiTexCoord0;
- varying highp vec2 qt_TexCoord0;
- uniform highp float width;
- void main() {
- highp vec4 pos = qt_Vertex;
- highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
- pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
- gl_Position = qt_Matrix * pos;
- qt_TexCoord0 = qt_MultiTexCoord0;
- }"
- }
- \endqml
- \endrow
+ \sa GridMesh
*/
QVariant QSGShaderEffect::mesh() const
{
- return m_deprecatedMesh ? qVariantFromValue(static_cast<QObject *>(m_deprecatedMesh))
- : qVariantFromValue(m_meshResolution);
+ return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh))
+ : qVariantFromValue(m_meshResolution);
}
void QSGShaderEffect::setMesh(const QVariant &mesh)
{
- // TODO: Replace QVariant with QSize after grace period.
QSGShaderEffectMesh *newMesh = qobject_cast<QSGShaderEffectMesh *>(qVariantValue<QObject *>(mesh));
- if (newMesh && newMesh == m_deprecatedMesh)
+ if (newMesh && newMesh == m_mesh)
return;
- if (m_deprecatedMesh)
- disconnect(m_deprecatedMesh, SIGNAL(geometryChanged()), this, 0);
- m_deprecatedMesh = newMesh;
- if (m_deprecatedMesh) {
- qWarning("ShaderEffect: Setting the mesh to something other than a size is deprecated.");
- connect(m_deprecatedMesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
+ if (m_mesh)
+ disconnect(m_mesh, SIGNAL(geometryChanged()), this, 0);
+ m_mesh = newMesh;
+ if (m_mesh) {
+ connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(updateGeometry()));
} else {
if (qVariantCanConvert<QSize>(mesh)) {
m_meshResolution = mesh.toSize();
@@ -347,7 +318,7 @@ void QSGShaderEffect::setMesh(const QVariant &mesh)
}
}
if (!ok)
- qWarning("ShaderEffect: mesh resolution must be a size.");
+ qWarning("ShaderEffect: mesh property must be size or object deriving from QSGShaderEffectMesh.");
}
m_defaultMesh.setResolution(m_meshResolution);
}
@@ -511,10 +482,9 @@ void QSGShaderEffect::updateProperties()
lookThroughShaderCode(vertexCode);
lookThroughShaderCode(fragmentCode);
- // TODO: Remove !m_deprecatedMesh check after grace period.
- if (!m_deprecatedMesh && !m_source.attributeNames.contains(qt_position_attribute_name))
+ if (!m_mesh && !m_source.attributeNames.contains(qt_position_attribute_name))
qWarning("QSGShaderEffect: Missing reference to \'%s\'.", qt_position_attribute_name);
- if (!m_deprecatedMesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
+ if (!m_mesh && !m_source.attributeNames.contains(qt_texcoord_attribute_name))
qWarning("QSGShaderEffect: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
if (!m_source.respectsMatrix)
qWarning("QSGShaderEffect: Missing reference to \'qt_Matrix\'.");
@@ -608,7 +578,7 @@ QSGNode *QSGShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
node->setFlag(QSGNode::OwnsGeometry, false);
QSGGeometry *geometry = node->geometry();
QRectF rect(0, 0, width(), height());
- QSGShaderEffectMesh *mesh = m_deprecatedMesh ? m_deprecatedMesh : &m_defaultMesh;
+ QSGShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
geometry = mesh->updateGeometry(geometry, m_source.attributeNames, rect);
if (!geometry) {
diff --git a/src/declarative/items/qsgshadereffect_p.h b/src/declarative/items/qsgshadereffect_p.h
index 5d90fe0e61..a8c3f084e4 100644
--- a/src/declarative/items/qsgshadereffect_p.h
+++ b/src/declarative/items/qsgshadereffect_p.h
@@ -131,7 +131,7 @@ private:
QSGShaderEffectProgram m_source;
QSize m_meshResolution;
- QSGShaderEffectMesh *m_deprecatedMesh; // TODO: Remove after grace period.
+ QSGShaderEffectMesh *m_mesh;
QSGGridMesh m_defaultMesh;
CullMode m_cullMode;
diff --git a/src/declarative/items/qsgshadereffectmesh.cpp b/src/declarative/items/qsgshadereffectmesh.cpp
index 6d3d17e4ff..53fd917e06 100644
--- a/src/declarative/items/qsgshadereffectmesh.cpp
+++ b/src/declarative/items/qsgshadereffectmesh.cpp
@@ -51,8 +51,9 @@ QSGShaderEffectMesh::QSGShaderEffectMesh(QObject *parent)
}
/*!
- \class QSGGridMesh
- \since 5.0
+ \qmlclass GridMesh QSGGridMesh
+ \inqmlmodule QtQuick 2
+ \ingroup qml-utility-elements
\brief GridMesh defines a mesh with vertices arranged in a grid.
GridMesh defines a rectangular mesh consisting of vertices arranged in an
@@ -152,12 +153,47 @@ QSGGeometry *QSGGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QB
}
/*!
- \property QSGGridMesh::resolution
+ \qmlproperty size QtQuick2::GridMesh::resolution
This property holds the grid resolution. The resolution's width and height
specify the number of cells or spacings between vertices horizontally and
vertically respectively. The minimum and default is 1x1, which corresponds
to four vertices in total, one in each corner.
+ For non-linear vertex transformations, you probably want to set the
+ resolution higher.
+
+ \row
+ \o \image declarative-gridmesh.png
+ \o \qml
+ import QtQuick 2.0
+
+ ShaderEffect {
+ width: 200
+ height: 200
+ mesh: GridMesh {
+ resolution: Qt.size(20, 20)
+ }
+ property variant source: Image {
+ source: "qt-logo.png"
+ sourceSize { width: 200; height: 200 }
+ smooth: true
+ }
+ vertexShader: "
+ uniform highp mat4 qt_Matrix;
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec2 qt_MultiTexCoord0;
+ varying highp vec2 qt_TexCoord0;
+ uniform highp float width;
+ void main() {
+ highp vec4 pos = qt_Vertex;
+ highp float d = .5 * smoothstep(0., 1., qt_MultiTexCoord0.y);
+ pos.x = width * mix(d, 1.0 - d, qt_MultiTexCoord0.x);
+ gl_Position = qt_Matrix * pos;
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ }"
+ }
+ \endqml
+ \endrow
*/
void QSGGridMesh::setResolution(const QSize &res)
diff --git a/src/declarative/items/qsgshadereffectmesh_p.h b/src/declarative/items/qsgshadereffectmesh_p.h
index 4a1a8ae61b..428674fdba 100644
--- a/src/declarative/items/qsgshadereffectmesh_p.h
+++ b/src/declarative/items/qsgshadereffectmesh_p.h
@@ -59,7 +59,7 @@ QT_MODULE(Declarative)
class QSGGeometry;
class QRectF;
-class QSGShaderEffectMesh : public QObject
+class Q_DECLARATIVE_EXPORT QSGShaderEffectMesh : public QObject
{
Q_OBJECT
public:
diff --git a/src/declarative/items/qsgtext.cpp b/src/declarative/items/qsgtext.cpp
index a00a217ee3..f936c3f32b 100644
--- a/src/declarative/items/qsgtext.cpp
+++ b/src/declarative/items/qsgtext.cpp
@@ -1328,10 +1328,15 @@ void QSGText::resetMaximumLineCount()
styling markup, in the style of html 3.2:
\code
- <font size="4" color="#ff0000">font size and color</font>
- <b>bold</b>
- <i>italic</i>
- <br>
+ <b></b> - bold
+ <i></i> - italic
+ <br> - new line
+ <p> - paragraph
+ <u> - underlined text
+ <font color="color_name" size="1-7"></font>
+ <h1> to <h6> - headers
+ <a href=""> - anchor
+ <ol type="">, <ul type=""> and <li> - ordered and unordered lists
&gt; &lt; &amp;
\endcode
diff --git a/src/declarative/items/qsgtextedit.cpp b/src/declarative/items/qsgtextedit.cpp
index 1afb36f035..885fdaf395 100644
--- a/src/declarative/items/qsgtextedit.cpp
+++ b/src/declarative/items/qsgtextedit.cpp
@@ -1675,6 +1675,7 @@ void QSGTextEdit::q_textChanged()
void QSGTextEdit::moveCursorDelegate()
{
Q_D(QSGTextEdit);
+ d->determineHorizontalAlignment();
updateMicroFocus();
emit cursorRectangleChanged();
if(!d->cursor)
diff --git a/src/declarative/items/qsgtextinput.cpp b/src/declarative/items/qsgtextinput.cpp
index 42105cf9ce..ab6be666d8 100644
--- a/src/declarative/items/qsgtextinput.cpp
+++ b/src/declarative/items/qsgtextinput.cpp
@@ -403,6 +403,8 @@ bool QSGTextInputPrivate::determineHorizontalAlignment()
if (hAlignImplicit) {
// if no explicit alignment has been set, follow the natural layout direction of the text
QString text = control->text();
+ if (text.isEmpty())
+ text = control->preeditAreaText();
bool isRightToLeft = text.isEmpty() ? QGuiApplication::keyboardInputDirection() == Qt::RightToLeft : text.isRightToLeft();
return setHAlign(isRightToLeft ? QSGTextInput::AlignRight : QSGTextInput::AlignLeft);
}
@@ -1900,6 +1902,7 @@ void QSGTextInput::cursorPosChanged()
void QSGTextInput::updateCursorRectangle()
{
Q_D(QSGTextInput);
+ d->determineHorizontalAlignment();
d->updateHorizontalScroll();
updateRect();//TODO: Only update rect between pos's
updateMicroFocus();
diff --git a/src/declarative/items/qsgview.h b/src/declarative/items/qsgview.h
index 62b52c865b..2d8e8b4067 100644
--- a/src/declarative/items/qsgview.h
+++ b/src/declarative/items/qsgview.h
@@ -43,8 +43,9 @@
#ifndef QSGVIEW_H
#define QSGVIEW_H
-#include <QtCore/qurl.h>
#include <qsgcanvas.h>
+#include <QtCore/qurl.h>
+#include <QtDeclarative/qdeclarativedebug.h>
QT_BEGIN_HEADER