Merge remote-tracking branch 'origin/5.7' into dev

Conflicts:
	src/quick/items/qquickflickable_p_p.h
	src/quick/items/qquickpathview_p_p.h
	tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp

Change-Id: I77664a095d8a203e07a021c9d5953e02b8b99a1e
This commit is contained in:
Liang Qi 2016-06-20 17:39:48 +02:00
commit 43431619d6
37 changed files with 506 additions and 162 deletions

View File

@ -3,7 +3,7 @@
The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd.
Contact: http://www.qt.io/licensing/
You may use, distribute and copy the Qt GUI Toolkit under the terms of
You may use, distribute and copy the Qt Toolkit under the terms of
GNU Lesser General Public License version 3. That license references
the General Public License version 3, that is displayed below. Other
portions of the Qt Toolkit may be licensed directly under this license.

View File

@ -3,7 +3,7 @@
The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd.
Contact: http://www.qt.io/licensing/
You may use, distribute and copy the Qt GUI Toolkit under the terms of
You may use, distribute and copy the Qt Toolkit under the terms of
GNU Lesser General Public License version 2.1, which is displayed below.
-------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd.
Contact: http://www.qt.io/licensing/
You may use, distribute and copy the Qt GUI Toolkit under the terms of
You may use, distribute and copy the Qt Toolkit under the terms of
GNU Lesser General Public License version 3, which is displayed below.
This license makes reference to the version 3 of the GNU General
Public License, which you can find in the LICENSE.GPLv3 file.

114
dist/changes-5.7.0 vendored Normal file
View File

@ -0,0 +1,114 @@
Qt 5.7 introduces many new features and improvements as well as bugfixes
over the 5.6.x series. Also, there is a change in the licensing terms.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://doc.qt.io/qt-5/index.html
The Qt version 5.7 series is binary compatible with the 5.6.x series.
Applications compiled for 5.6 will continue to run with 5.7.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Important License Changes *
****************************************************************************
This module is no longer available under LGPLv2.1. The libraries are
now available under the following licenses:
* Commercial License
* GNU General Public License v2.0 (LICENSE.GPL2) and later
* GNU Lesser General Public License v3.0 (LICENSE.LGPL3)
The tools are now available under the following licenses:
* Commercial License
* GNU General Public License 3.0 (LICENSE.GPL3) with exceptions
described in The Qt Company GPL Exception 1.0 (LICENSE.GPL3-EXCEPT)
****************************************************************************
* Important Behavior Changes *
****************************************************************************
QtQuick
-------
* [QTBUG-41833] QQuickItem::childAt was incorrectly including any child
whose right or bottom edge was adjacent to the point being checked,
as if it had width+1 and height+1. An Item with a width of 100
covers pixels from x=0..x=99, and likewise with height; so now,
calling childAt(100, 100) on its parent will not return it.
* [QTBUG-51115] TextEdit and TextInput now clear their selection when
becoming read-only.
* QtQuick.Layouts moved to the qtdeclarative repository.
****************************************************************************
* Library *
****************************************************************************
QtQml
-----
- [QTBUG-52556] Made the QML Engine capable of locating QML sub-modules
from within a versioned parent module path. For example, QtQml.Models
2.x can be either in QT_INSTALL_QML/QtQml/Models.2 or in
QT_INSTALL_QML/QtQml.2/Models.
- [QTBUG-36350] Added Connections::enabled property to allow toggling of the
signal handlers inside a Connections element.
- Enabled JIT for x86/x64 targets on Windows 10 and later.
- Enabled JIT for Aarch64.
QtQuick
-------
- Window:
* Added Window.window attached property, allowing access to the QQuickWindow
an Item belongs to.
- GridView & ListView:
* [QTBUG-17051] Added keyNavigationEnabled property to allow mouse and
keyboard interaction to be selectively enabled/disabled.
* Sticky headers or footers are now correctly positioned in the case of
an empty view.
- MouseArea:
* Added mouse.source property to enable distinguishing genuine mouse
events from those that are synthesized from touch or tablet events.
- PathView:
* Added PathView::movementDirection, which sets the direction in which items
move when setting currentIndex.
- QQuickItem:
* Added isAncestorOf() to determine if an item is the ancestor of another
item (i.e. the parent, or a parent further up the item tree).
* [QTBUG-28668] Added support for mapping item's coordinates to and from global
screen coordinates, in the form of Item::mapToGlobal() and
Item::mapFromGlobal().
- TextEdit/TextInput:
* [QTBUG-49503] Added TextEdit::preeditText & TextInput::preeditText,
which allow access to partial (uncommitted) text from an input method.
* [QTBUG-50428] Added TextEdit::clear() and TextInput::clear() which sets the
text to an empty string, but in addition, also clears partial (uncommitted)
text.
- Loader:
* [QTBUG-29789] Object creation previously started asynchronously can be
forced to complete synchronously by changing the "asynchronous" property
from true to false.
Qt.labs.folderlistmodel
-----------------------
- FolderListModel
* [QTBUG-45566] Added FolderListModel::caseSensitive, to control whether or
not filtering is applied case sensitively.

View File

@ -98,7 +98,7 @@ unsigned short getPaddedHeight(ETCHeader *pHeader)
EtcTexture::EtcTexture()
: m_texture_id(0), m_uploaded(false)
{
initializeOpenGLFunctions();
}
EtcTexture::~EtcTexture()
@ -109,8 +109,10 @@ EtcTexture::~EtcTexture()
int EtcTexture::textureId() const
{
if (m_texture_id == 0)
glGenTextures(1, &const_cast<EtcTexture *>(this)->m_texture_id);
if (m_texture_id == 0) {
EtcTexture *texture = const_cast<EtcTexture*>(this);
texture->glGenTextures(1, &texture->m_texture_id);
}
return m_texture_id;
}

View File

@ -51,7 +51,7 @@
#ifndef ETCPROVIDER_H
#define ETCPROVIDER_H
#include <qopengl.h>
#include <QOpenGLFunctions>
#include <QQuickImageProvider>
#include <QtQuick/QSGTexture>
#include <QUrl>
@ -71,7 +71,7 @@ private:
QUrl m_baseUrl;
};
class EtcTexture : public QSGTexture
class EtcTexture : public QSGTexture, protected QOpenGLFunctions
{
Q_OBJECT
public:

View File

@ -43,7 +43,7 @@
#include <machine/ieee.h>
#endif
#if OS(QNX)
#if OS(QNX) && defined(_CPPLIB_VER)
// FIXME: Look into a way to have cmath import its functions into both the standard and global
// namespace. For now, we include math.h since the QNX cmath header only imports its functions
// into the standard namespace.

View File

@ -554,7 +554,7 @@ void NativeDebugger::handleExpressions(QJsonObject *response, const QJsonObject
dict[QStringLiteral("name")] = name;
dict[QStringLiteral("valueencoded")] = QStringLiteral("undefined");
output.append(dict);
} else if (result.ptr && result.ptr->_val) {
} else if (result.ptr && result.ptr->rawValue()) {
collector.collect(&output, QString(), name, *result);
} else {
QJsonObject dict;

View File

@ -119,13 +119,13 @@ from C++:
\code
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QGuiApplication app(argc, argv);
QQmlEngine engine;
QQuickView view;
Message msg;
engine.rootContext()->setContextProperty("msg", &msg);
QQmlComponent component(&engine, QUrl::fromLocalFile("MyItem.qml"));
component.create();
view.engine()->rootContext()->setContextProperty("msg", &msg);
view.setSource(QUrl::fromLocalFile("MyItem.qml"));
view.show();
return app.exec();
}

View File

@ -152,7 +152,7 @@ public:
#endif // Windows on x86
#if CPU(X86_64) && (OS(LINUX) || OS(MAC_OS_X) || OS(FREEBSD) || defined(Q_OS_IOS))
#if CPU(X86_64) && (OS(LINUX) || OS(MAC_OS_X) || OS(FREEBSD) || OS(QNX) || defined(Q_OS_IOS))
enum { RegAllocIsSupported = 1 };
static const JSC::MacroAssembler::RegisterID FramePointerRegister = JSC::X86Registers::ebp;

View File

@ -99,8 +99,8 @@ Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
static Q_ALWAYS_INLINE void storeValue(ReturnedValue *target, uint value)
{
Value v = Value::fromReturnedValue(*target);
v.setValue(value);
Value v;
v.setTagValue(Value::fromReturnedValue(*target).tag(), value);
*target = v.asReturnedValue();
}
@ -195,7 +195,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
n->value = i;
} else {
storeValue(lastFree, i);
sparse->arrayData[i].setTag(Value::Empty_Type);
sparse->arrayData[i].setEmpty();
lastFree = &sparse->arrayData[i].rawValueRef();
}
}
@ -204,7 +204,7 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
if (toCopy < sparse->alloc) {
for (uint i = toCopy; i < sparse->alloc; ++i) {
storeValue(lastFree, i);
sparse->arrayData[i].setTag(Value::Empty_Type);
sparse->arrayData[i].setEmpty();
lastFree = &sparse->arrayData[i].rawValueRef();
}
storeValue(lastFree, UINT_MAX);
@ -402,7 +402,7 @@ uint SparseArrayData::allocate(Object *o, bool doubleSlot)
// found two slots in a row
uint idx = Value::fromReturnedValue(*last).uint_32();
Value lastV = Value::fromReturnedValue(*last);
lastV.setValue(dd->arrayData[lastV.value() + 1].value());
lastV.setTagValue(lastV.tag(), dd->arrayData[lastV.value() + 1].value());
*last = lastV.rawValue();
dd->attrs[idx] = Attr_Accessor;
return idx;

View File

@ -135,7 +135,7 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#define ENABLE_JIT 0
#endif
#if defined(Q_OS_QNX)
#if defined(Q_OS_QNX) && defined(_CPPLIB_VER)
#include <math.h>
#undef isnan
#undef isfinite

View File

@ -74,11 +74,6 @@ void ObjectIterator::init(const Object *o)
object->setM(o ? o->m() : 0);
current->setM(o ? o->m() : 0);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
object->setTag(QV4::Value::Managed_Type);
current->setTag(QV4::Value::Managed_Type);
#endif
if (object->as<ArgumentsObject>()) {
Scope scope(engine);
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();

View File

@ -85,11 +85,9 @@ Page *allocatePage(PersistentValueStorage *storage)
if (p->header.next)
p->header.next->header.prev = &p->header.next;
for (int i = 0; i < kEntriesPerPage - 1; ++i) {
p->values[i].setTag(QV4::Value::Empty_Type);
p->values[i].setInt_32(i + 1);
p->values[i].setEmpty(i + 1);
}
p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type);
p->values[kEntriesPerPage - 1].setInt_32(-1);
p->values[kEntriesPerPage - 1].setEmpty(-1);
storage->firstPage = p;
@ -211,8 +209,7 @@ void PersistentValueStorage::free(Value *v)
Page *p = getPage(v);
v->setTag(QV4::Value::Empty_Type);
v->setInt_32(p->header.freeList);
v->setEmpty(p->header.freeList);
p->header.freeList = v - p->values;
if (!--p->header.refCount)
freePage(p);

View File

@ -126,9 +126,6 @@ struct ScopedValue
{
ptr = scope.engine->jsStackTop++;
ptr->setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
ptr->setTag(QV4::Value::Managed_Type);
#endif
}
ScopedValue(const Scope &scope, Managed *m)
@ -150,9 +147,6 @@ struct ScopedValue
ScopedValue &operator=(Heap::Base *o) {
ptr->setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
ptr->setTag(QV4::Value::Managed_Type);
#endif
return *this;
}
@ -192,18 +186,12 @@ struct Scoped
inline void setPointer(const Managed *p) {
ptr->setM(p ? p->m() : 0);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
ptr->setTag(QV4::Value::Managed_Type);
#endif
}
Scoped(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
ptr->setM(0);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
ptr->setTag(QV4::Value::Managed_Type);
#endif
}
Scoped(const Scope &scope, const Value &v)
@ -345,14 +333,14 @@ struct ScopedCallData {
inline Value &Value::operator =(const ScopedValue &v)
{
_val = v.ptr->val();
_val = v.ptr->rawValue();
return *this;
}
template<typename T>
inline Value &Value::operator=(const Scoped<T> &t)
{
_val = t.ptr->val();
_val = t.ptr->rawValue();
return *this;
}

View File

@ -72,6 +72,7 @@ typedef uint Bool;
struct Q_QML_PRIVATE_EXPORT Value
{
private:
/*
We use two different ways of encoding JS values. One for 32bit and one for 64bit systems.
@ -96,10 +97,10 @@ struct Q_QML_PRIVATE_EXPORT Value
quint64 _val;
Q_ALWAYS_INLINE quint64 val() const { return _val; }
Q_ALWAYS_INLINE void setVal(quint64 v) { _val = v; }
Q_ALWAYS_INLINE void setValue(quint32 v) { memcpy(&_val, &v, 4); }
Q_ALWAYS_INLINE void setTag(quint32 t) { memcpy(4 + (quint8 *)&_val, &t, 4); }
public:
Q_ALWAYS_INLINE quint64 &rawValueRef() { return _val; }
Q_ALWAYS_INLINE quint64 rawValue() const { return _val; }
Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
static inline int valueOffset() { return 0; }
@ -119,17 +120,53 @@ struct Q_QML_PRIVATE_EXPORT Value
Q_ALWAYS_INLINE Heap::Base *m() const { Q_UNREACHABLE(); return Q_NULLPTR; }
Q_ALWAYS_INLINE void setM(Heap::Base *b) { Q_UNUSED(b); Q_UNREACHABLE(); }
#elif defined(QV4_USE_64_BIT_VALUE_ENCODING)
Q_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; }
Q_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); }
Q_ALWAYS_INLINE Heap::Base *m() const
{
Heap::Base *b;
memcpy(&b, &_val, 8);
return b;
}
Q_ALWAYS_INLINE void setM(Heap::Base *b)
{
memcpy(&_val, &b, 8);
}
#else // !QV4_USE_64_BIT_VALUE_ENCODING
Q_ALWAYS_INLINE Heap::Base *m() const { Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32)); Heap::Base *b; quint32 v = value(); memcpy(&b, &v, 4); return b; }
Q_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); setValue(v); }
Q_ALWAYS_INLINE Heap::Base *m() const
{
Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32));
Heap::Base *b;
quint32 v = value();
memcpy(&b, &v, 4);
return b;
}
Q_ALWAYS_INLINE void setM(Heap::Base *b)
{
quint32 v;
memcpy(&v, &b, 4);
setTagValue(Managed_Type, v);
}
#endif
Q_ALWAYS_INLINE int int_32() const { int i; quint32 v = value(); memcpy(&i, &v, 4); return i; }
Q_ALWAYS_INLINE void setInt_32(int i) { quint32 u; memcpy(&u, &i, 4); setValue(u); }
Q_ALWAYS_INLINE int int_32() const
{
return int(value());
}
Q_ALWAYS_INLINE void setInt_32(int i)
{
setTagValue(Integer_Type_Internal, quint32(i));
}
Q_ALWAYS_INLINE uint uint_32() const { return value(); }
Q_ALWAYS_INLINE void setEmpty()
{
setTagValue(Empty_Type, value());
}
Q_ALWAYS_INLINE void setEmpty(int i)
{
setTagValue(Empty_Type, quint32(i));
}
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
enum Masks {
SilentNaNBit = 0x00040000,
@ -266,7 +303,6 @@ struct Q_QML_PRIVATE_EXPORT Value
int i = (int)d;
if (i == d) {
setInt_32(i);
setTag(Integer_Type_Internal);
return true;
}
}
@ -304,22 +340,10 @@ struct Q_QML_PRIVATE_EXPORT Value
return isManaged() ? m() : nullptr;
}
Q_ALWAYS_INLINE quint64 &rawValueRef() {
return _val;
}
Q_ALWAYS_INLINE quint64 rawValue() const {
return _val;
}
Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
static inline Value fromHeapObject(Heap::Base *m)
{
Value v;
v.setRawValue(0);
v.setM(m);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
v.setTag(Managed_Type);
#endif
return v;
}
@ -340,7 +364,7 @@ struct Q_QML_PRIVATE_EXPORT Value
inline bool tryIntegerConversion() {
bool b = integerCompatible();
if (b)
setTag(Integer_Type_Internal);
setTagValue(Integer_Type_Internal, value());
return b;
}
@ -393,7 +417,7 @@ struct Q_QML_PRIVATE_EXPORT Value
Value &operator=(ReturnedValue v) { _val = v; return *this; }
Value &operator=(Managed *m) {
if (!m) {
setTagValue(Undefined_Type, 0);
setM(0);
} else {
_val = reinterpret_cast<Value *>(m)->_val;
}
@ -401,9 +425,6 @@ struct Q_QML_PRIVATE_EXPORT Value
}
Value &operator=(Heap::Base *o) {
setM(o);
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
setTag(Managed_Type);
#endif
return *this;
}
@ -494,13 +515,7 @@ struct Q_QML_PRIVATE_EXPORT Primitive : public Value
inline Primitive Primitive::undefinedValue()
{
Primitive v;
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
v.setRawValue(quint64(Undefined_Type) << Tag_Shift);
#else
v.setRawValue(0);
v.setTag(Undefined_Type);
v.setValue(0);
#endif
v.setTagValue(Undefined_Type, 0);
return v;
}
@ -514,11 +529,7 @@ inline Primitive Primitive::emptyValue()
inline Primitive Primitive::nullValue()
{
Primitive v;
#ifndef QV4_USE_64_BIT_VALUE_ENCODING
v.setRawValue(quint64(Null_Type_Internal) << Tag_Shift);
#else
v.setTagValue(Null_Type_Internal, 0);
#endif
return v;
}
@ -539,7 +550,7 @@ inline Primitive Primitive::fromDouble(double d)
inline Primitive Primitive::fromInt32(int i)
{
Primitive v;
v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
v.setTagValue(Integer_Type_Internal, 0);
v.setInt_32(i);
return v;
}
@ -548,8 +559,7 @@ inline Primitive Primitive::fromUInt32(uint i)
{
Primitive v;
if (i < INT_MAX) {
v.setTagValue(Integer_Type_Internal, 0); // For mingw482, because it complains, and for VS9, because of internal compiler errors.
v.setInt_32((int)i);
v.setTagValue(Integer_Type_Internal, i);
} else {
v.setDouble(i);
}

View File

@ -407,7 +407,7 @@ The following functions are also on the Qt object.
\li \c "unix" - Other Unix-based OS
\li \c "windows" - Windows
\li \c "wince" - Windows CE
\li \c "winrt" - Windows RT
\li \c "winrt" - Windows Runtime
\li \c "winphone" - Windows Phone
\endlist
\endtable

View File

@ -433,7 +433,7 @@ example shows a simple use of QQmlIncubator.
QQmlIncubator incubator;
component->create(incubator);
while (incubator.isReady()) {
while (!incubator.isReady()) {
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
}

View File

@ -1937,7 +1937,8 @@ void QQmlTypeLoader::trimCache()
QList<TypeCache::Iterator> unneededTypes;
for (TypeCache::Iterator iter = m_typeCache.begin(), end = m_typeCache.end(); iter != end; ++iter) {
QQmlTypeData *typeData = iter.value();
if (typeData->m_compiledData && typeData->m_compiledData->count() == 1) {
if (typeData->m_compiledData && typeData->count() == 1
&& typeData->m_compiledData->count() == 1) {
// There are no live objects of this type
unneededTypes.append(iter);
}

View File

@ -62,6 +62,7 @@
#include <private/qquicktimeline_p_p.h>
#include <private/qquickanimation_p_p.h>
#include <private/qquicktransitionmanager_p_p.h>
#include <private/qpodvector_p.h>
QT_BEGIN_NAMESPACE

View File

@ -1549,10 +1549,12 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
Note that cacheBuffer is not a pixel buffer - it only maintains additional
instantiated delegates.
Setting this value can make scrolling the list smoother at the expense
of additional memory usage. It is not a substitute for creating efficient
delegates; the fewer objects and bindings in a delegate, the faster a view may be
scrolled.
\note Setting this property is not a replacement for creating efficient delegates.
It can improve the smoothness of scrolling behavior at the expense of additional
memory usage. The fewer objects and bindings in a delegate, the faster a
view can be scrolled. It is important to realize that setting a cacheBuffer
will only postpone issues caused by slow-loading delegates, it is not a
solution for this scenario.
The cacheBuffer operates outside of any display margins specified by
displayMarginBeginning or displayMarginEnd.

View File

@ -2364,8 +2364,9 @@ QQuickItem::~QQuickItem()
while (!d->childItems.isEmpty())
d->childItems.constFirst()->setParentItem(0);
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
const auto listeners = d->changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
if (anchor)
anchor->clearItem(this);
}
@ -2374,14 +2375,13 @@ QQuickItem::~QQuickItem()
update item anchors that depended on us unless they are our child (and will also be destroyed),
or our sibling, and our parent is also being destroyed.
*/
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
if (anchor && anchor->item && anchor->item->parentItem() && anchor->item->parentItem() != this)
anchor->update();
}
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Destroyed)
change.listener->itemDestroyed(this);
}
@ -3628,8 +3628,8 @@ QQuickAnchors *QQuickItemPrivate::anchors() const
void QQuickItemPrivate::siblingOrderChanged()
{
Q_Q(QQuickItem);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::SiblingOrder) {
change.listener->itemSiblingOrderChanged(q);
}
@ -3737,8 +3737,8 @@ void QQuickItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeo
bool widthChange = (newGeometry.width() != oldGeometry.width());
bool heightChange = (newGeometry.height() != oldGeometry.height());
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
const auto listeners = d->changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Geometry) {
if (change.gTypes == QQuickItemPrivate::GeometryChange) {
change.listener->itemGeometryChanged(this, newGeometry, oldGeometry);
@ -3874,7 +3874,7 @@ void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *liste
void QQuickItemPrivate::updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, GeometryChangeTypes types)
{
ChangeListener change(listener, types);
int index = changeListeners.find(change);
int index = changeListeners.indexOf(change);
if (index > -1)
changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
else
@ -3888,7 +3888,7 @@ void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeLis
if (types == NoChange) {
changeListeners.removeOne(change);
} else {
int index = changeListeners.find(change);
int index = changeListeners.indexOf(change);
if (index > -1)
changeListeners[index].gTypes = change.gTypes; //we may have different GeometryChangeTypes
}
@ -4297,8 +4297,8 @@ void QQuickItem::setBaselineOffset(qreal offset)
d->baselineOffset = offset;
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
const auto listeners = d->changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Geometry) {
QQuickAnchorsPrivate *anchor = change.listener->anchorPrivate();
if (anchor)
@ -5969,66 +5969,72 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt
{
Q_Q(QQuickItem);
switch (change) {
case QQuickItem::ItemChildAddedChange:
case QQuickItem::ItemChildAddedChange: {
q->itemChange(change, data);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Children) {
change.listener->itemChildAdded(q, data.item);
}
}
break;
case QQuickItem::ItemChildRemovedChange:
}
case QQuickItem::ItemChildRemovedChange: {
q->itemChange(change, data);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Children) {
change.listener->itemChildRemoved(q, data.item);
}
}
break;
}
case QQuickItem::ItemSceneChange:
q->itemChange(change, data);
break;
case QQuickItem::ItemVisibleHasChanged:
case QQuickItem::ItemVisibleHasChanged: {
q->itemChange(change, data);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Visibility) {
change.listener->itemVisibilityChanged(q);
}
}
break;
case QQuickItem::ItemParentHasChanged:
}
case QQuickItem::ItemParentHasChanged: {
q->itemChange(change, data);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Parent) {
change.listener->itemParentChanged(q, data.item);
}
}
break;
case QQuickItem::ItemOpacityHasChanged:
}
case QQuickItem::ItemOpacityHasChanged: {
q->itemChange(change, data);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Opacity) {
change.listener->itemOpacityChanged(q);
}
}
break;
}
case QQuickItem::ItemActiveFocusHasChanged:
q->itemChange(change, data);
break;
case QQuickItem::ItemRotationHasChanged:
case QQuickItem::ItemRotationHasChanged: {
q->itemChange(change, data);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::Rotation) {
change.listener->itemRotationChanged(q);
}
}
break;
}
case QQuickItem::ItemAntialiasingHasChanged:
// fall through
case QQuickItem::ItemDevicePixelRatioHasChanged:
@ -6383,8 +6389,8 @@ void QQuickItem::resetWidth()
void QQuickItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickItem);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::ImplicitWidth) {
change.listener->itemImplicitWidthChanged(q);
}
@ -6547,8 +6553,8 @@ void QQuickItem::resetHeight()
void QQuickItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickItem);
for (int ii = 0; ii < changeListeners.count(); ++ii) {
const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
const auto listeners = changeListeners;
for (const QQuickItemPrivate::ChangeListener &change : listeners) {
if (change.types & QQuickItemPrivate::ImplicitHeight) {
change.listener->itemImplicitHeightChanged(q);
}

View File

@ -63,7 +63,6 @@
#include <QtQuick/qsgnode.h>
#include "qquickclipnode_p.h"
#include <private/qpodvector_p.h>
#include <QtQuick/private/qquickstate_p.h>
#include <private/qqmlnullablevalue_p.h>
#include <private/qqmlnotifier_p.h>
@ -332,7 +331,7 @@ public:
Q_DECLARE_FLAGS(GeometryChangeTypes, GeometryChangeType)
struct ChangeListener {
ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::ChangeTypes t) : listener(l), types(t), gTypes(GeometryChange) {}
ChangeListener(QQuickItemChangeListener *l = Q_NULLPTR, QQuickItemPrivate::ChangeTypes t = 0) : listener(l), types(t), gTypes(GeometryChange) {}
ChangeListener(QQuickItemChangeListener *l, QQuickItemPrivate::GeometryChangeTypes gt) : listener(l), types(Geometry), gTypes(gt) {}
QQuickItemChangeListener *listener;
QQuickItemPrivate::ChangeTypes types;
@ -386,7 +385,7 @@ public:
inline Qt::MouseButtons acceptedMouseButtons() const;
QPODVector<QQuickItemPrivate::ChangeListener,4> changeListeners;
QVector<QQuickItemPrivate::ChangeListener> changeListeners;
void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types);
void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types);
@ -935,6 +934,7 @@ QSGNode *QQuickItemPrivate::childContainerNode()
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickItemPrivate::ChangeTypes)
Q_DECLARE_TYPEINFO(QQuickItemPrivate::ChangeListener, Q_PRIMITIVE_TYPE);
QT_END_NAMESPACE

View File

@ -2219,10 +2219,12 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation)
Note that cacheBuffer is not a pixel buffer - it only maintains additional
instantiated delegates.
Setting this value can improve the smoothness of scrolling behavior at the expense
of additional memory usage. It is not a substitute for creating efficient
delegates; the fewer objects and bindings in a delegate, the faster a view can be
scrolled.
\note Setting this property is not a replacement for creating efficient delegates.
It can improve the smoothness of scrolling behavior at the expense of additional
memory usage. The fewer objects and bindings in a delegate, the faster a
view can be scrolled. It is important to realize that setting a cacheBuffer
will only postpone issues caused by slow-loading delegates, it is not a
solution for this scenario.
The cacheBuffer operates outside of any display margins specified by
displayMarginBeginning or displayMarginEnd.

View File

@ -1313,10 +1313,12 @@ void QQuickPathView::resetPathItemCount()
allowing creation to occur across multiple frames and reducing the
likelihood of skipping frames.
Setting this value can improve the smoothness of scrolling behavior at the expense
of additional memory usage. It is not a substitute for creating efficient
delegates; the fewer objects and bindings in a delegate, the faster a view can be
moved.
\note Setting this property is not a replacement for creating efficient delegates.
It can improve the smoothness of scrolling behavior at the expense of additional
memory usage. The fewer objects and bindings in a delegate, the faster a
view can be scrolled. It is important to realize that setting cacheItemCount
will only postpone issues caused by slow-loading delegates, it is not a
solution for this scenario.
\sa pathItemCount
*/

View File

@ -61,6 +61,7 @@
#include <private/qquickanimation_p_p.h>
#include <private/qqmldelegatemodel_p.h>
#include <private/qquicktimeline_p_p.h>
#include <private/qpodvector_p.h>
QT_BEGIN_NAMESPACE

View File

@ -1154,7 +1154,10 @@ void QQuickTextPrivate::setLineGeometry(QTextLine &line, qreal lineWidth, qreal
foreach (QQuickStyledTextImgTag *image, imagesInLine) {
totalLineHeight = qMax(totalLineHeight, textTop + image->pos.y() + image->size.height());
image->pos.setX(line.cursorToX(image->position));
const int leadX = line.cursorToX(image->position);
const int trailX = line.cursorToX(image->position, QTextLine::Trailing);
const bool rtl = trailX < leadX;
image->pos.setX(leadX + (rtl ? (-image->offset - image->size.width()) : image->offset));
image->pos.setY(image->pos.y() + height + textTop);
extra->visibleImgTags << image;
}

View File

@ -1042,6 +1042,7 @@ void QQuickTextInput::q_validatorChanged()
QRectF QQuickTextInputPrivate::anchorRectangle() const
{
Q_Q(const QQuickTextInput);
QRectF rect;
int a;
// Unfortunately we cannot use selectionStart() and selectionEnd()
@ -1062,8 +1063,8 @@ QRectF QQuickTextInputPrivate::anchorRectangle() const
a = 0;
QTextLine l = m_textLayout.lineForTextPosition(a);
if (l.isValid()) {
qreal x = l.cursorToX(a) - hscroll;
qreal y = l.y() - vscroll;
qreal x = l.cursorToX(a) - hscroll + q->leftPadding();
qreal y = l.y() - vscroll + q->topPadding();
rect.setRect(x, y, 1, l.height());
}
}

View File

@ -103,8 +103,10 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
glyph_t glyphIndex = *it;
int padding = QSG_DEFAULT_DISTANCEFIELD_GLYPH_CACHE_PADDING;
int glyphWidth = qCeil(glyphData(glyphIndex).boundingRect.width()) + distanceFieldRadius() * 2;
QSize glyphSize(glyphWidth + padding * 2, QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) + padding * 2);
QRectF boundingRect = glyphData(glyphIndex).boundingRect;
int glyphWidth = qCeil(boundingRect.width()) + distanceFieldRadius() * 2;
int glyphHeight = qCeil(boundingRect.height()) + distanceFieldRadius() * 2;
QSize glyphSize(glyphWidth + padding * 2, glyphHeight + padding * 2);
QRect alloc = m_areaAllocator->allocate(glyphSize);
if (alloc.isNull()) {
@ -113,11 +115,13 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
glyph_t unusedGlyph = *m_unusedGlyphs.constBegin();
TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
int unusedGlyphWidth = qCeil(glyphData(unusedGlyph).boundingRect.width()) + distanceFieldRadius() * 2;
QRectF unusedGlyphBoundingRect = glyphData(unusedGlyph).boundingRect;
int unusedGlyphWidth = qCeil(unusedGlyphBoundingRect.width()) + distanceFieldRadius() * 2;
int unusedGlyphHeight = qCeil(unusedGlyphBoundingRect.height()) + distanceFieldRadius() * 2;
m_areaAllocator->deallocate(QRect(unusedCoord.x - padding,
unusedCoord.y - padding,
padding * 2 + unusedGlyphWidth,
padding * 2 + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())));
padding * 2 + unusedGlyphHeight));
m_unusedGlyphs.remove(unusedGlyph);
m_glyphsTexture.remove(unusedGlyph);

View File

@ -317,7 +317,6 @@ void QSGDefaultPainterNode::updateRenderTarget()
if (m_texture)
delete m_texture;
texture->setTextureSize(m_size);
m_texture = texture;
}

View File

@ -658,10 +658,13 @@ bool QQuickStyledTextPrivate::parseAnchorAttributes(const QChar *&ch, const QStr
void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QString &textIn, QString &textOut)
{
qreal imgWidth = 0.0;
QFontMetricsF fm(layout.font());
const qreal spaceWidth = fm.width(QChar::Nbsp);
const bool trailingSpace = textOut.endsWith(space);
if (!updateImagePositions) {
QQuickStyledTextImgTag *image = new QQuickStyledTextImgTag;
image->position = textOut.length() + 1;
image->position = textOut.length() + (trailingSpace ? 0 : 1);
QPair<QStringRef,QStringRef> attr;
do {
@ -698,14 +701,16 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri
}
imgWidth = image->size.width();
image->offset = -std::fmod(imgWidth, spaceWidth) / 2.0;
imgTags->append(image);
} else {
// if we already have a list of img tags for this text
// we only want to update the positions of these tags.
QQuickStyledTextImgTag *image = imgTags->value(nbImages);
image->position = textOut.length() + 1;
image->position = textOut.length() + (trailingSpace ? 0 : 1);
imgWidth = image->size.width();
image->offset = -std::fmod(imgWidth, spaceWidth) / 2.0;
QPair<QStringRef,QStringRef> attr;
do {
attr = parseAttribute(ch, textIn);
@ -713,9 +718,9 @@ void QQuickStyledTextPrivate::parseImageAttributes(const QChar *&ch, const QStri
nbImages++;
}
QFontMetricsF fm(layout.font());
QString padding(qFloor(imgWidth / fm.width(QChar::Nbsp)), QChar::Nbsp);
textOut += QLatin1Char(' ');
QString padding(qFloor(imgWidth / spaceWidth), QChar::Nbsp);
if (!trailingSpace)
textOut += QLatin1Char(' ');
textOut += padding;
textOut += QLatin1Char(' ');
}

View File

@ -68,7 +68,7 @@ class Q_AUTOTEST_EXPORT QQuickStyledTextImgTag
{
public:
QQuickStyledTextImgTag()
: position(0), align(QQuickStyledTextImgTag::Bottom), pix(0)
: position(0), offset(0.0), align(QQuickStyledTextImgTag::Bottom), pix(0)
{ }
~QQuickStyledTextImgTag() { delete pix; }
@ -83,6 +83,7 @@ public:
QPointF pos;
QSize size;
int position;
qreal offset; // this offset allows us to compensate for flooring reserved space
Align align;
QQuickPixmap *pix;
};

View File

@ -80,10 +80,19 @@ void tst_QQMLTypeLoader::trimCache()
url.setQuery(QString::number(i));
QQmlTypeData *data = loader.getType(url);
if (i % 5 == 0) // keep references to some of them so that they aren't trimmed
data->compilationUnit()->addref();
// Run an event loop to receive the callback that release()es.
QTRY_COMPARE(data->count(), 2);
data->release();
// keep references to some of them so that they aren't trimmed. References to either the
// QQmlTypeData or its compiledData() should prevent the trimming.
if (i % 10 == 0) {
// keep ref on data, don't add ref on data->compiledData()
} else if (i % 5 == 0) {
data->compilationUnit()->addref();
data->release();
} else {
data->release();
}
}
for (int i = 0; i < 256; ++i) {

View File

@ -7,6 +7,8 @@
linux
[tst_grabImage::test_equals]
linux
[ListView::test_listInteractiveCurrentIndexEnforce]
linux
[Text::test_linecount]
osx
windows

View File

@ -118,9 +118,10 @@ Item {
compare(txtlinecount.lineCount, 2)
txtlinecount.text = txtlinecount.third;
compare(txtlinecount.lineCount, 3)
console.log(txtlinecount.width)
txtlinecount.text = txtlinecount.first;
compare(txtlinecount.lineCount, 1)
txtlinecount.width = 50;
txtlinecount.width = 44;
compare(txtlinecount.lineCount, 3)
}
function test_linecounts() {

View File

@ -35,6 +35,7 @@
#include <QtGui/private/qinputmethod_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
#include <QtGui/qstylehints.h>
#include <private/qquickitem_p.h>
#include "../../shared/util.h"
@ -107,6 +108,7 @@ private slots:
void childrenProperty();
void resourcesProperty();
void changeListener();
void transformCrash();
void implicitSize();
void qtbug_16871();
@ -2694,6 +2696,202 @@ void tst_QQuickItem::childrenRectBottomRightCorner()
delete window;
}
struct TestListener : public QQuickItemChangeListener
{
TestListener(bool remove = false) : remove(remove) { reset(); }
void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &) override { ++itemGeometryChanges; value = newGeometry; }
void itemSiblingOrderChanged(QQuickItem *) override { ++itemSiblingOrderChanges; }
void itemVisibilityChanged(QQuickItem *) override { ++itemVisibilityChanges; }
void itemOpacityChanged(QQuickItem *) override { ++itemOpacityChanges; }
void itemRotationChanged(QQuickItem *) override { ++itemRotationChanges; }
void itemImplicitWidthChanged(QQuickItem *) override { ++itemImplicitWidthChanges; }
void itemImplicitHeightChanged(QQuickItem *) override { ++itemImplicitHeightChanges; }
void itemDestroyed(QQuickItem *item) override
{
++itemDestructions;
// QTBUG-53453
if (remove)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
}
void itemChildAdded(QQuickItem *item, QQuickItem *child) override
{
++itemChildAdditions;
value = QVariant::fromValue(child);
// QTBUG-53453
if (remove)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Children);
}
void itemChildRemoved(QQuickItem *item, QQuickItem *child) override
{
++itemChildRemovals;
value = QVariant::fromValue(child);
// QTBUG-53453
if (remove)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Children);
}
void itemParentChanged(QQuickItem *item, QQuickItem *parent) override
{
++itemParentChanges;
value = QVariant::fromValue(parent);
// QTBUG-53453
if (remove)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent);
}
QQuickAnchorsPrivate *anchorPrivate() override { return nullptr; }
void reset()
{
value = QVariant();
itemGeometryChanges = 0;
itemSiblingOrderChanges = 0;
itemVisibilityChanges = 0;
itemOpacityChanges = 0;
itemDestructions = 0;
itemChildAdditions = 0;
itemChildRemovals = 0;
itemParentChanges = 0;
itemRotationChanges = 0;
itemImplicitWidthChanges = 0;
itemImplicitHeightChanges = 0;
}
bool remove;
QVariant value;
int itemGeometryChanges;
int itemSiblingOrderChanges;
int itemVisibilityChanges;
int itemOpacityChanges;
int itemDestructions;
int itemChildAdditions;
int itemChildRemovals;
int itemParentChanges;
int itemRotationChanges;
int itemImplicitWidthChanges;
int itemImplicitHeightChanges;
};
void tst_QQuickItem::changeListener()
{
QQuickItem item;
TestListener itemListener;
QQuickItemPrivate::get(&item)->addItemChangeListener(&itemListener, QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight |
QQuickItemPrivate::Opacity | QQuickItemPrivate::Rotation);
item.setImplicitWidth(50);
QCOMPARE(itemListener.itemImplicitWidthChanges, 1);
QCOMPARE(itemListener.itemGeometryChanges, 1);
QCOMPARE(itemListener.value, QVariant(QRectF(0,0,50,0)));
item.setImplicitHeight(50);
QCOMPARE(itemListener.itemImplicitHeightChanges, 1);
QCOMPARE(itemListener.itemGeometryChanges, 2);
QCOMPARE(itemListener.value, QVariant(QRectF(0,0,50,50)));
item.setWidth(100);
QCOMPARE(itemListener.itemGeometryChanges, 3);
QCOMPARE(itemListener.value, QVariant(QRectF(0,0,100,50)));
item.setHeight(100);
QCOMPARE(itemListener.itemGeometryChanges, 4);
QCOMPARE(itemListener.value, QVariant(QRectF(0,0,100,100)));
item.setOpacity(0.5);
QCOMPARE(itemListener.itemOpacityChanges, 1);
item.setRotation(90);
QCOMPARE(itemListener.itemRotationChanges, 1);
QQuickItem *parent = new QQuickItem;
TestListener parentListener;
QQuickItemPrivate::get(parent)->addItemChangeListener(&parentListener, QQuickItemPrivate::Children);
QQuickItem *child1 = new QQuickItem;
QQuickItem *child2 = new QQuickItem;
TestListener child1Listener;
TestListener child2Listener;
QQuickItemPrivate::get(child1)->addItemChangeListener(&child1Listener, QQuickItemPrivate::Parent | QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::Destroyed);
QQuickItemPrivate::get(child2)->addItemChangeListener(&child2Listener, QQuickItemPrivate::Parent | QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::Destroyed);
child1->setParentItem(parent);
QCOMPARE(parentListener.itemChildAdditions, 1);
QCOMPARE(parentListener.value, QVariant::fromValue(child1));
QCOMPARE(child1Listener.itemParentChanges, 1);
QCOMPARE(child1Listener.value, QVariant::fromValue(parent));
child2->setParentItem(parent);
QCOMPARE(parentListener.itemChildAdditions, 2);
QCOMPARE(parentListener.value, QVariant::fromValue(child2));
QCOMPARE(child2Listener.itemParentChanges, 1);
QCOMPARE(child2Listener.value, QVariant::fromValue(parent));
child2->stackBefore(child1);
QCOMPARE(child1Listener.itemSiblingOrderChanges, 1);
QCOMPARE(child2Listener.itemSiblingOrderChanges, 1);
child1->setParentItem(nullptr);
QCOMPARE(parentListener.itemChildRemovals, 1);
QCOMPARE(parentListener.value, QVariant::fromValue(child1));
QCOMPARE(child1Listener.itemParentChanges, 2);
QCOMPARE(child1Listener.value, QVariant::fromValue<QQuickItem *>(nullptr));
delete child1;
QCOMPARE(child1Listener.itemDestructions, 1);
delete child2;
QCOMPARE(parentListener.itemChildRemovals, 2);
QCOMPARE(parentListener.value, QVariant::fromValue(child2));
QCOMPARE(child2Listener.itemParentChanges, 2);
QCOMPARE(child2Listener.value, QVariant::fromValue<QQuickItem *>(nullptr));
QCOMPARE(child2Listener.itemDestructions, 1);
QQuickItemPrivate::get(parent)->removeItemChangeListener(&parentListener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0);
// QTBUG-53453: all listeners should get invoked even if they remove themselves while iterating the listeners
QList<TestListener *> listeners;
for (int i = 0; i < 5; ++i)
listeners << new TestListener(true);
// itemChildAdded() x 5
foreach (TestListener *listener, listeners)
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count());
child1 = new QQuickItem(parent);
foreach (TestListener *listener, listeners)
QCOMPARE(listener->itemChildAdditions, 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0);
// itemParentChanged() x 5
foreach (TestListener *listener, listeners)
QQuickItemPrivate::get(child1)->addItemChangeListener(listener, QQuickItemPrivate::Parent);
QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.count(), listeners.count());
child1->setParentItem(nullptr);
foreach (TestListener *listener, listeners)
QCOMPARE(listener->itemParentChanges, 1);
QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.count(), 0);
// itemChildRemoved() x 5
child1->setParentItem(parent);
foreach (TestListener *listener, listeners)
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count());
delete child1;
foreach (TestListener *listener, listeners)
QCOMPARE(listener->itemChildRemovals, 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), 0);
// itemDestroyed() x 5
foreach (TestListener *listener, listeners)
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Destroyed);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.count(), listeners.count());
delete parent;
foreach (TestListener *listener, listeners)
QCOMPARE(listener->itemDestructions, 1);
}
// QTBUG-13893
void tst_QQuickItem::transformCrash()
{

View File

@ -45,7 +45,7 @@
#include <qquickimageprovider.h>
#include <QImage>
#include <QPainter>
#include <qDebug.h>
#include <QDebug>
class ColorImageProvider : public QQuickImageProvider
{