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

Conflicts:
	.qmake.conf

Change-Id: I9d87ed86e95b5901a86cc3aa65d7ac39b0b708c2
This commit is contained in:
Liang Qi 2017-01-14 21:52:09 +01:00
commit 60300fda46
36 changed files with 302 additions and 82 deletions

View File

@ -75,9 +75,21 @@ This example builds on:
Shows how to use \l {QQmlEngine::}{qmlRegisterExtendedType()} to provide an \l {Registering
Extension Objects}{extension object} to a \l QLineEdit without modifying or
subclassing. The QML engine instantiates a \l QLineEdit and sets a property that
only exists on the extension type. The extension type performs calls on the \l
QLineEdit that otherwise will not be accessible to the QML engine.
subclassing.
\snippet referenceexamples/extended/main.cpp 0
The QML engine instantiates a \l QLineEdit
\snippet referenceexamples/extended/main.cpp 1
and sets a property that oly exists on the extension type.
\snippet referenceexamples/extended/example.qml 0
The QML engine instantiates a \l QLineEdit and sets a property that
only exists on the extension type. The extension type performs calls on the
\l QLineEdit that otherwise will not be accessible to the QML engine.
*/
@ -293,12 +305,20 @@ This example builds on:
This example builds on:
\list
\li \l {Extending QML - Default Property Example}
\li \l {Extending QML - Inheritance and Coercion Example}
\li \l {Extending QML - Object and List Property Types Example}
\li \l {Extending QML - Adding Types Example}
\endlist
The Methods Example has an additional method in the \c BirthdayParty class: \c invite().
\c invite() is declared with \l Q_INVOKABLE so that it can be
called from QML.
\snippet referenceexamples/methods/birthdayparty.h 0
In \c example.qml, the \c invite() method is called in the \l [QML]{QtQml::Component::completed()}{Component.onCompleted} signal handler:
\snippet referenceexamples/methods/example.qml 0
*/
/*!

View File

@ -48,11 +48,15 @@ int main(int argc, char ** argv)
{
QApplication app(argc, argv);
// ![0]
qmlRegisterExtendedType<QLineEdit, LineEditExtension>("People", 1,0, "QLineEdit");
// ![0]
// ![1]
QQmlEngine engine;
QQmlComponent component(&engine, QUrl("qrc:example.qml"));
QLineEdit *edit = qobject_cast<QLineEdit *>(component.create());
// ![1]
if (edit) {
edit->show();

View File

@ -38,6 +38,7 @@
**
****************************************************************************/
// ![0]
import QtQuick 2.0
import People 1.0
@ -52,7 +53,6 @@ BirthdayParty {
Person { name: "Anne Brown" }
]
// ![0]
Component.onCompleted: invite("William Green")
// ![0]
}
// ![0]

View File

@ -102,7 +102,7 @@ QSGNode *Graph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
n->background = new NoisyNode(window());
n->grid = new GridNode();
n->line = new LineNode(10, 0.5, QColor("steelblue"));
n->shadow = new LineNode(20, 0.2, QColor::fromRgbF(0.2, 0.2, 0.2, 0.4));
n->shadow = new LineNode(20, 0.2f, QColor::fromRgbF(0.2, 0.2, 0.2, 0.4));
n->appendChildNode(n->background);
n->appendChildNode(n->grid);

View File

@ -762,9 +762,11 @@ bool QQuickLayout::shouldIgnoreItem(QQuickItem *child, QQuickLayoutAttached *&in
void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value)
{
if (change == ItemChildAddedChange) {
Q_D(QQuickLayout);
QQuickItem *item = value.item;
qmlobject_connect(item, QQuickItem, SIGNAL(baselineOffsetChanged(qreal)), this, QQuickLayout, SLOT(invalidateSenderItem()));
QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility);
d->m_hasItemChangeListeners = true;
if (isReady())
updateLayoutItems();
} else if (change == ItemChildRemovedChange) {
@ -802,6 +804,30 @@ bool QQuickLayout::isReady() const
return d_func()->m_isReady;
}
/*!
* \brief QQuickLayout::deactivateRecur
* \internal
*
* Call this from the dtor of the top-level layout.
* Otherwise, it will trigger lots of unneeded item change listeners (itemVisibleChanged()) for all its descendants
* that will have its impact thrown away.
*/
void QQuickLayout::deactivateRecur()
{
if (d_func()->m_hasItemChangeListeners) {
for (int i = 0; i < itemCount(); ++i) {
QQuickItem *item = itemAt(i);
// When deleting a layout with children, there is no reason for the children to inform the layout that their
// e.g. visibility got changed. The layout already knows that all its children will eventually become invisible, so
// we therefore remove its change listener.
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility);
if (QQuickLayout *layout = qobject_cast<QQuickLayout*>(item))
layout->deactivateRecur();
}
d_func()->m_hasItemChangeListeners = false;
}
}
void QQuickLayout::itemSiblingOrderChanged(QQuickItem *item)
{
Q_UNUSED(item);

View File

@ -95,6 +95,7 @@ public:
void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
bool isReady() const;
void deactivateRecur();
/* QQuickItemChangeListener */
@ -134,6 +135,7 @@ public:
protected:
unsigned m_isReady : 1;
unsigned m_disableRearrange : 1;
unsigned m_hasItemChangeListeners : 1; // if false, we don't need to remove its item change listeners...
mutable QSet<QQuickItem *> m_ignoredItems;
};

View File

@ -305,11 +305,7 @@ QQuickGridLayoutBase::~QQuickGridLayoutBase()
// Remove item listeners so we do not act on signalling unnecessarily
// (there is no point, as the layout will be torn down anyway).
for (int i = 0; i < itemCount(); ++i) {
QQuickItem *item = itemAt(i);
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::SiblingOrder | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight | QQuickItemPrivate::Destroyed | QQuickItemPrivate::Visibility);
}
deactivateRecur();
delete d->styleInfo;
}

View File

@ -407,6 +407,11 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory
const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
if (sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
*errorString = QStringLiteral("QML source file has moved to a different location.");
return false;
}
{
const QString foundArchitecture = stringAt(data->architectureIndex);
const QString expectedArchitecture = QSysInfo::buildAbi();

View File

@ -32,4 +32,40 @@
The list of examples demonstrating how to extend C++ to QML or the other way
around.
\noautolist
\table
\row
\li \l {Extending QML - Adding Types Example}
\li Exporting C++ Classes
\row
\li \l {Extending QML - Object and List Property Types Example}
\li Exporting C++ Properties
\row
\li \l {Extending QML - Extension Objects Example}
\li Extension Objects
\row
\li \l {Extending QML - Inheritance and Coercion Example}
\li C++ Inheritance and Coercion
\row
\li \l {Extending QML - Methods Example}
\li Methods Support
\row
\li \l {Extending QML - Attached Properties Example}
\li Attached Properties
\row
\li \l {Extending QML - Signal Support Example}
\li Signal Support
\row
\li \l {Extending QML - Property Value Source Example}
\li Property Value Source
\row
\li \l {Extending QML - Default Property Example}
\li Default Property
\row
\li \l {Extending QML - Grouped Properties Example}
\li Grouped Properties
\endtable
*/

View File

@ -73,7 +73,8 @@
For the object-based types (including Date and RegExp), use the
newT() functions in QJSEngine (e.g. QJSEngine::newObject())
to create a QJSValue of the desired type. For the primitive types,
use one of the QJSValue constructor overloads.
use one of the QJSValue constructor overloads. For other types, e.g.
registered gadget types such as QPoint, you can use QJSEngine::toScriptValue.
The methods named isT() (e.g. isBool(), isUndefined()) can be
used to test if a value is of a certain type. The methods named

View File

@ -158,8 +158,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
}
Q_ASSERT(maxCallDepth > 0);
MemoryManager::GCBlocker gcBlocker(memoryManager);
if (!factory) {
#if QT_CONFIG(qml_interpreter)
bool jitDisabled = true;

View File

@ -88,8 +88,6 @@ void Script::parse()
ExecutionEngine *v4 = scope->engine();
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
IR::Module module(v4->debugger() != 0);
QQmlJS::Engine ee, *engine = &ee;

View File

@ -565,16 +565,6 @@ void MemoryManager::sweep(bool lastSweep)
}
}
bool MemoryManager::isGCBlocked() const
{
return m_d->gcBlocked;
}
void MemoryManager::setGCBlocked(bool blockGC)
{
m_d->gcBlocked = blockGC;
}
void MemoryManager::runGC()
{
if (m_d->gcBlocked) {

View File

@ -76,26 +76,6 @@ class Q_QML_EXPORT MemoryManager
public:
struct Data;
class GCBlocker
{
public:
GCBlocker(MemoryManager *mm)
: mm(mm)
, wasBlocked(mm->isGCBlocked())
{
mm->setGCBlocked(true);
}
~GCBlocker()
{
mm->setGCBlocked(wasBlocked);
}
private:
MemoryManager *mm;
bool wasBlocked;
};
public:
MemoryManager(ExecutionEngine *engine);
~MemoryManager();
@ -309,8 +289,6 @@ public:
return t->d();
}
bool isGCBlocked() const;
void setGCBlocked(bool blockGC);
void runGC();
void dumpStats() const;

View File

@ -199,7 +199,10 @@ void QQmlBoundSignalExpression::evaluate(void **a)
// for several cases (such as QVariant type and QObject-derived types)
//args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
if (type == qMetaTypeId<QJSValue>()) {
callData->args[ii] = *QJSValuePrivate::getValue(reinterpret_cast<QJSValue *>(a[ii + 1]));
if (QV4::Value *v4Value = QJSValuePrivate::getValue(reinterpret_cast<QJSValue *>(a[ii + 1])))
callData->args[ii] = *v4Value;
else
callData->args[ii] = QV4::Encode::undefined();
} else if (type == QMetaType::QVariant) {
callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
} else if (type == QMetaType::Int) {

View File

@ -47,8 +47,6 @@
#include "qqml.h"
#include "qqmlengine.h"
#include "qqmlbinding_p.h"
#include <private/qqmldebugconnector_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
#include "qqmlincubator.h"
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
@ -876,15 +874,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
depthIncreased = false;
}
if (rv) {
if (QQmlEngineDebugService *service =
QQmlDebugConnector::service<QQmlEngineDebugService>()) {
if (!context->isInternal)
context->asQQmlContextPrivate()->instances.append(rv);
service->objectCreated(engine, rv);
}
}
return rv;
}

View File

@ -117,4 +117,14 @@ void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
Q_UNUSED(uri);
}
/*!
\class QQmlExtensionInterface
\internal
\inmodule QtQml
\class QQmlTypesExtensionInterface
\internal
\inmodule QtQml
*/
QT_END_NAMESPACE

View File

@ -335,7 +335,7 @@ int QQmlListReference::count() const
\since 5.0
\inmodule QtQml
\brief The QQmlListProperty class allows applications to expose list-like
properties to QML.
properties of QObject-derived classes to QML.
QML has many list properties, where more than one object value can be assigned.
The use of a list property from QML looks like this:
@ -369,7 +369,8 @@ QML list properties are type-safe - in this case \c {Fruit} is a QObject type th
The \l {Qt Quick 1} version of this class is named QDeclarativeListProperty.
\note QQmlListProperty can only be used for lists of QObject-derived object pointers.
\sa {Extending QML - Object and List Property Types Example}
*/
/*!

View File

@ -53,6 +53,8 @@
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlpropertyvalueinterceptor_p.h>
#include <private/qqmlvaluetypeproxybinding_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
QT_USE_NAMESPACE
@ -216,6 +218,17 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
phase = ObjectsCreated;
if (instance) {
if (QQmlEngineDebugService *service
= QQmlDebugConnector::service<QQmlEngineDebugService>()) {
if (!parentContext->isInternal)
parentContext->asQQmlContextPrivate()->instances.append(instance);
service->objectCreated(engine, instance);
} else if (!parentContext->isInternal && QQmlDebugConnector::service<QV4DebugService>()) {
parentContext->asQQmlContextPrivate()->instances.append(instance);
}
}
return instance;
}

View File

@ -766,7 +766,6 @@ QSGNode *QQuickCanvasItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
if (!texture) {
delete node;
d->node = 0;
delete d->nodeTexture;
d->nodeTexture = 0;
if (d->textureProvider) {
d->textureProvider->tex = 0;

View File

@ -137,6 +137,7 @@ Item {
\li Qt.AltModifier - An Alt key on the keyboard is pressed.
\li Qt.MetaModifier - A Meta key on the keyboard is pressed.
\li Qt.KeypadModifier - A keypad button is pressed.
\li Qt.GroupSwitchModifier - X11 only. A Mode_switch key on the keyboard is pressed.
\endlist
For example, to react to a Shift key + Enter key combination:

View File

@ -341,7 +341,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
position of the release of the click, and whether the click was held.
When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse
parameter has no effect.
parameter has no effect, unless the \l propagateComposedEvents property is \c true.
The corresponding handler is \c onClicked.
*/
@ -385,7 +385,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
position of the press, and which button is pressed.
When handling this signal, changing the \l {MouseEvent::}{accepted} property of the \a mouse
parameter has no effect.
parameter has no effect, unless the \l propagateComposedEvents property is \c true.
The corresponding handler is \c onPressAndHold.
*/

View File

@ -1729,7 +1729,9 @@ void QQuickTextEdit::select(int start, int end)
// QTBUG-11100
updateSelection();
#if QT_CONFIG(im)
updateInputMethod();
#endif
}
/*!

View File

@ -2083,11 +2083,12 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
ut->startAnimations();
}
// Once per frame, send a synthetic hover, in case items have changed position.
// Once per frame, if any items are dirty, send a synthetic hover,
// in case items have changed position, visibility, etc.
// For instance, during animation (including the case of a ListView
// whose delegates contain MouseAreas), a MouseArea needs to know
// whether it has moved into a position where it is now under the cursor.
if (!q->mouseGrabberItem() && !lastMousePosition.isNull()) {
if (!q->mouseGrabberItem() && !lastMousePosition.isNull() && dirtyItemList) {
bool accepted = false;
bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), 0, accepted);
if (!delivered)

View File

@ -979,6 +979,10 @@ void Renderer::nodeChangedBatchRoot(Node *node, Node *root)
e->root = root;
e->boundsComputed = false;
}
} else if (node->type() == QSGNode::RenderNodeType) {
RenderNodeElement *e = node->renderNodeElement();
if (e)
e->root = root;
}
SHADOWNODE_TRAVERSE(node)
@ -2022,6 +2026,8 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
}
ClipType clipType = NoClip;
GLuint vbo = 0;
int vboSize = 0;
glDisable(GL_SCISSOR_TEST);
@ -2106,7 +2112,21 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
const QSGGeometry *g = clip->geometry();
Q_ASSERT(g->attributeCount() > 0);
const QSGGeometry::Attribute *a = g->attributes();
glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), g->vertexData());
if (!vbo)
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
const int vertexByteSize = g->sizeOfVertex() * g->vertexCount();
if (vboSize < vertexByteSize) {
vboSize = vertexByteSize;
glBufferData(GL_ARRAY_BUFFER, vertexByteSize, g->vertexData(), GL_STATIC_DRAW);
} else {
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexByteSize, g->vertexData());
}
glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), 0);
m_clipProgram.setUniformValue(m_clipMatrixId, m);
if (g->indexCount()) {
@ -2115,12 +2135,17 @@ Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
glDrawArrays(g->drawingMode(), 0, g->vertexCount());
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
++m_currentStencilValue;
}
clip = clip->clipList();
}
if (vbo)
glDeleteBuffers(1, &vbo);
if (clipType & StencilClip) {
m_clipProgram.disableAttributeArray(0);
glStencilFunc(GL_EQUAL, m_currentStencilValue, 0xff); // stencil test, ref, test mask
@ -2778,8 +2803,13 @@ void Renderer::renderRenderNode(Batch *batch)
updateClip(rd->m_clip_list, batch);
RenderNodeState state;
QMatrix4x4 pm = projectionMatrix();
if (m_useDepthBuffer) {
pm(2, 2) = m_zRange;
pm(2, 3) = 1.0f - e->order * m_zRange;
}
RenderNodeState state;
state.m_projectionMatrix = &pm;
state.m_scissorEnabled = m_currentClipType & ScissorClip;
state.m_stencilEnabled = m_currentClipType & StencilClip;

View File

@ -160,10 +160,7 @@ QSGRenderNode::StateFlags QSGRenderNode::changedStates() const
\list
\li glDepthMask(false)
\li glDisable(GL_DEPTH_TEST)
\li glStencilMask(0)
\li glEnable(GL_STENCIL_TEST)/glDisable(GL_STENCIL_TEST) depending on clip
\li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff) depending on clip
\li glEnable(GL_SCISSOR_TEST)/glDisable(GL_SCISSOR_TEST) depending on clip
\li glScissor(state.scissorRect.x(), state.scissorRect.y(),
state.scissorRect.width(), state.scissorRect.height()) depending on clip
\li glEnable(GL_BLEND)

View File

@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
\inqmlmodule QtQuick
\since 5.2
\ingroup qtquick-transitions-animations
\inherits Animation
\brief Is the base of all QML animators.
Animator types are a special type of animation which operate

View File

@ -45,6 +45,7 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlproperty.h>
#include <QtQml/qqmlincubator.h>
#include <QtQuick/qquickitem.h>
#include <QtNetwork/qhostaddress.h>
@ -136,6 +137,7 @@ private slots:
void regression_QTCREATORBUG_7451();
void queryObjectWithNonStreamableTypes();
void asynchronousCreate();
};
QmlDebugObjectReference tst_QQmlEngineDebugService::findRootObject(
@ -1220,6 +1222,32 @@ void tst_QQmlEngineDebugService::queryObjectTree()
QCOMPARE(findProperty(animation.properties,"duration").value.toInt(), 100);
}
void tst_QQmlEngineDebugService::asynchronousCreate() {
QmlDebugObjectReference object;
auto connection = connect(m_dbg, &QQmlEngineDebugClient::newObject, this, [&](int objectId) {
object.debugId = objectId;
});
QByteArray asynchronousComponent = "import QtQuick 2.5\n"
"Rectangle { id: asyncRect }";
QQmlComponent component(m_engine);
component.setData(asynchronousComponent, QUrl::fromLocalFile(""));
QVERIFY(component.isReady()); // fails if bad syntax
QQmlIncubator incubator(QQmlIncubator::Asynchronous);
component.create(incubator);
QVERIFY(m_dbg->object().idString != QLatin1String("asyncRect"));
QTRY_VERIFY(object.debugId != -1);
disconnect(connection);
bool success = false;
m_dbg->queryObject(object, &success);
QVERIFY(success);
QTRY_COMPARE(m_dbg->object().idString, QLatin1String("asyncRect"));
}
int main(int argc, char *argv[])
{
int _argc = argc + 1;

View File

@ -489,7 +489,9 @@ void QQmlEngineDebugClient::messageReceived(const QByteArray &data)
return;
} else if (type == "OBJECT_CREATED") {
emit newObjects();
int engineId, objectId, parentId;
ds >> engineId >> objectId >> parentId;
emit newObject(objectId);
return;
} else if (type == "SET_BINDING_R") {
ds >> m_valid;

View File

@ -213,7 +213,7 @@ public:
bool valid() { return m_valid; }
signals:
void newObjects();
void newObject(int objectId);
void valueChanged(QByteArray,QVariant);
void result();

View File

@ -53,6 +53,7 @@ private slots:
void registerImportForImplicitComponent();
void basicVersionChecks();
void recompileAfterChange();
void recompileAfterDirectoryChange();
void fileSelectors();
void localAliases();
void cacheResources();
@ -95,11 +96,17 @@ struct TestCompiler
TestCompiler(QQmlEngine *engine)
: engine(engine)
, tempDir()
, testFilePath(tempDir.path() + QStringLiteral("/test.qml"))
, cacheFilePath(tempDir.path() + QStringLiteral("/test.qmlc"))
, mappedFile(cacheFilePath)
, currentMapping(nullptr)
{
init(tempDir.path());
}
void init(const QString &baseDirectory)
{
closeMapping();
testFilePath = baseDirectory + QStringLiteral("/test.qml");
cacheFilePath = baseDirectory + QStringLiteral("/test.qmlc");
mappedFile.setFileName(cacheFilePath);
}
bool compile(const QByteArray &contents)
@ -187,8 +194,8 @@ struct TestCompiler
QQmlEngine *engine;
const QTemporaryDir tempDir;
const QString testFilePath;
const QString cacheFilePath;
QString testFilePath;
QString cacheFilePath;
QString lastErrorString;
QFile mappedFile;
uchar *currentMapping;
@ -441,6 +448,47 @@ void tst_qmldiskcache::recompileAfterChange()
}
}
void tst_qmldiskcache::recompileAfterDirectoryChange()
{
QQmlEngine engine;
TestCompiler testCompiler(&engine);
QVERIFY(testCompiler.tempDir.isValid());
QVERIFY(QDir(testCompiler.tempDir.path()).mkdir("source1"));
testCompiler.init(testCompiler.tempDir.path() + QLatin1String("/source1"));
{
const QByteArray contents = QByteArrayLiteral("import QtQml 2.0\n"
"QtObject {\n"
" property int blah: 42;\n"
"}");
testCompiler.clearCache();
QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
testCompiler.closeMapping();
}
const QDateTime initialCacheTimeStamp = QFileInfo(testCompiler.cacheFilePath).lastModified();
QDir(testCompiler.tempDir.path()).rename(QStringLiteral("source1"), QStringLiteral("source2"));
waitForFileSystem();
testCompiler.init(testCompiler.tempDir.path() + QLatin1String("/source2"));
{
CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
QScopedPointer<QObject> obj(component.create());
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("blah").toInt(), 42);
}
QFile cacheFile(testCompiler.cacheFilePath);
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
QVERIFY(QFileInfo(testCompiler.cacheFilePath).lastModified() > initialCacheTimeStamp);
}
void tst_qmldiskcache::fileSelectors()
{
QQmlEngine engine;

View File

@ -15,4 +15,6 @@ MyQmlObject
onMySignal: { intProperty = a; realProperty = b; colorProperty = c; variantProperty = d; enumProperty = e; qtEnumProperty = f; }
onBasicSignal: root.mySignal(10, 19.2, Qt.rgba(1, 1, 0, 1), Qt.rgba(1, 0, 1, 1), MyQmlObject.EnumValue3, Qt.LeftButton)
onQjsValueEmittingSignal: {}
}

View File

@ -244,6 +244,7 @@ signals:
void signalWithGlobalName(int parseInt);
void intChanged();
void qjsvalueChanged();
void qjsValueEmittingSignal(QJSValue value);
public slots:
void deleteMe() { delete this; }

View File

@ -1410,6 +1410,7 @@ void tst_qqmlecmascript::signalParameterTypes()
QVERIFY(object != 0);
emit object->basicSignal();
emit object->qjsValueEmittingSignal(QJSValue());
QCOMPARE(object->property("intProperty").toInt(), 10);
QCOMPARE(object->property("realProperty").toReal(), 19.2);

View File

@ -802,6 +802,27 @@ Item {
layout.destroy() // Do not crash
}
Component {
id: rectangle_Component
Rectangle {
width: 100
height: 50
}
}
function test_destroyImplicitInvisibleLayout()
{
var root = rectangle_Component.createObject(container)
root.visible = false
var layout = layout_deleteLayout.createObject(root)
layout.visible = true
// at this point the layout is still invisible because root is invisible
layout.destroy()
// Do not crash when destructing the layout
waitForRendering(container) // should ideally call gc(), but does not work
root.destroy()
}
function test_sizeHintWithHiddenChildren(data) {
var layout = layout_sizeHint_Component.createObject(container)
var grid = layout.children[0]

View File

@ -741,7 +741,7 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
std::cerr << qPrintable(QString(
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] [-noforceqtquick] module.uri version [module/import/path]\n"
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] [-dependencies <dependencies.json>] [-merge <file-to-merge.qmltypes>] [-output <output-file.qmltypes>] [-noforceqtquick] module.uri version [module/import/path]\n"
" %1 [-v] [-noinstantiate] -path path/to/qmldir/directory [version]\n"
" %1 [-v] -builtins\n"
"Example: %1 Qt.labs.folderlistmodel 2.0 /home/user/dev/qt-install/imports").arg(
@ -998,6 +998,7 @@ int main(int argc, char *argv[])
return EXIT_INVALIDARGUMENTS;
}
QString outputFilename;
QString pluginImportUri;
QString pluginImportVersion;
bool relocatable = true;
@ -1051,6 +1052,13 @@ int main(int argc, char *argv[])
} else if (arg == QLatin1String("--noforceqtquick")
|| arg == QLatin1String("-noforceqtquick")){
forceQtQuickDependency = false;
} else if (arg == QLatin1String("--output")
|| arg == QLatin1String("-output")) {
if (++iArg == args.size()) {
std::cerr << "missing output file" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
outputFilename = args.at(iArg);
} else if (arg == QLatin1String("--defaultplatform")
|| arg == QLatin1String("-defaultplatform")) {
continue;
@ -1306,7 +1314,15 @@ int main(int argc, char *argv[])
qml.writeEndObject();
qml.writeEndDocument();
std::cout << bytes.constData() << std::flush;
if (!outputFilename.isEmpty()) {
QFile file(outputFilename);
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
stream << bytes.constData();
}
} else {
std::cout << bytes.constData() << std::flush;
}
// workaround to avoid crashes on exit
QTimer timer;