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

Conflicts:
	src/imports/dialogs/qquickmessagedialog.cpp
	src/imports/dialogs/qquickmessagedialog_p.h
	src/qml/debugger/qqmlprofilerservice_p.h
	src/qml/jsruntime/qv4regexpobject.cpp
	tests/auto/qml/debugger/qqmlprofilerservice/qqmlprofilerservice.pro

Change-Id: Ic8a43366b44d6970966acbf03b206d0dee00c28d
This commit is contained in:
Simon Hausmann 2014-01-24 16:37:45 +01:00
commit 22041acdfe
42 changed files with 685 additions and 241 deletions

38
dist/changes-5.2.1 vendored Normal file
View File

@ -0,0 +1,38 @@
Qt 5.2.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.2.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
http://qt-project.org/doc/qt-5.2
The Qt version 5.2 series is binary compatible with the 5.1.x series.
Applications compiled for 5.1 will continue to run with 5.2.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
http://bugreports.qt-project.org/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* Library *
****************************************************************************
QtQml
-----
- [QTBUG-35979] Fixed JavaScript Array.pop() not updating the
internal array length correctly
QtQuick
-------
- [QTBUG-35128] Fixed TextInput to call fixup() on its validator when
being accepted or losing focus, and the validator reports that the input
is in "intermediate" state ie. the input should be fixed up.
- [QTBUG-34517] Fixed an issue that caused QQuickTextInput to not
accept delete/home/backspace/left/right keys when the key was used
in a shortcut.

View File

@ -1966,12 +1966,21 @@ void InstructionSelection::visitRet(V4IR::Ret *s)
Assembler::ScratchRegister);
_as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
} else if (t->type == V4IR::UInt32Type) {
Address tmp = addressForArgument(0);
_as->storeUInt32((Assembler::RegisterID) t->index, Pointer(tmp));
_as->load64(tmp, Assembler::ReturnValueRegister);
Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
_as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
_as->moveDoubleTo64(Assembler::FPGpr0, Assembler::ReturnValueRegister);
_as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
_as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
Assembler::Jump done = _as->jump();
intRange.link(_as);
_as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister);
quint64 tag = QV4::Value::_Integer_Type;
_as->or64(Assembler::TrustedImm64(tag << 32),
Assembler::ReturnValueRegister);
done.link(_as);
} else {
_as->zeroExtend32ToPtr((Assembler::RegisterID) t->index,
Assembler::ReturnValueRegister);
_as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, Assembler::ReturnValueRegister);
quint64 tag;
switch (t->type) {
case V4IR::SInt32Type:

View File

@ -1481,6 +1481,7 @@ protected:
typedef Assembler::Address Address;
typedef Assembler::Pointer Pointer;
#if !defined(ARGUMENTS_IN_REGISTERS)
Address addressForArgument(int index) const
{
// StackFrameRegister points to its old value on the stack, and above
@ -1488,6 +1489,7 @@ protected:
// values before reaching the first argument.
return Address(Assembler::StackFrameRegister, (index + 2) * sizeof(void*));
}
#endif
Pointer baseAddressForCallArguments()
{

View File

@ -860,7 +860,6 @@ private:
if (it->end() < successorStart)
continue;
bool lifeTimeHole = false;
bool isPhiTarget = false;
Expr *moveFrom = 0;
@ -906,9 +905,7 @@ private:
predIt->temp().type);
} else {
int spillSlot = _assignedSpillSlots.value(predIt->temp(), -1);
if (spillSlot == -1)
lifeTimeHole = true;
else
if (spillSlot != -1)
moveFrom = createTemp(Temp::StackSlot, spillSlot, predIt->temp().type);
}
break;
@ -916,9 +913,11 @@ private:
}
}
if (!moveFrom) {
#if defined(QT_NO_DEBUG)
Q_UNUSED(lifeTimeHole);
#else
#if !defined(QT_NO_DEBUG)
bool lifeTimeHole = false;
if (it->ranges().first().start <= successorStart && it->ranges().last().end >= successorStart)
lifeTimeHole = !it->covers(successorStart);
Q_ASSERT(!_info->isPhiTarget(it->temp()) || it->isSplitFromInterval() || lifeTimeHole);
if (_info->def(it->temp()) != successorStart && !it->isSplitFromInterval()) {
const int successorEnd = successor->statements.last()->id;
@ -960,9 +959,6 @@ private:
moveTo = createTemp(Temp::StackSlot, spillSlot, it->temp().type);
} else {
moveTo = createTemp(Temp::PhysicalRegister, platformRegister(*it), it->temp().type);
const int spillSlot = _assignedSpillSlots.value(it->temp(), -1);
if (isPhiTarget && spillSlot != -1)
mapping.add(moveFrom, createTemp(Temp::StackSlot, spillSlot, it->temp().type));
}
// add move to mapping

View File

@ -57,6 +57,7 @@
#include <private/qqmlboundsignal_p.h>
// this contains QUnifiedTimer
#include <private/qabstractanimation_p.h>
#include <private/qv4function_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmetaobject.h>
@ -401,8 +402,20 @@ struct QQmlBindingProfiler {
struct QQmlHandlingSignalProfiler {
QQmlHandlingSignalProfiler(QQmlBoundSignalExpression *expression)
{
Q_QML_PROFILE(startHandlingSignal(expression->sourceFile(), expression->lineNumber(),
expression->columnNumber()));
if (QQmlProfilerService::enabled) {
if (expression->sourceFile().isEmpty()) {
QV4::Function *function = expression->function();
if (function) {
Q_QML_PROFILE(startHandlingSignal(
function->sourceFile(), function->compiledFunction->location.line,
function->compiledFunction->location.column));
}
} else {
Q_QML_PROFILE(startHandlingSignal(
expression->sourceFile(), expression->lineNumber(),
expression->columnNumber()));
}
}
}
~QQmlHandlingSignalProfiler()

View File

@ -238,7 +238,7 @@
Usage:
\code
// First, define the singleton type provider function (callback).
static QJSValue *example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
static QJSValue example_qjsvalue_singletontype_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
{
Q_UNUSED(engine)

View File

@ -746,7 +746,7 @@ static bool js_equal(const QString &string, QV4::ValueRef value)
if (value->isNumber())
return __qmljs_string_to_number(string) == value->asDouble();
if (value->isBoolean())
return __qmljs_string_to_number(string) == value->booleanValue();
return __qmljs_string_to_number(string) == double(value->booleanValue());
if (value->isObject()) {
Scope scope(value->objectValue()->engine());
ScopedValue p(scope, __qmljs_to_primitive(value, PREFERREDTYPE_HINT));

View File

@ -50,7 +50,9 @@
# define alloca _alloca
# endif
#else
#if !defined(__FreeBSD__) && !defined(__DragonFly__)
# include <alloca.h>
#endif
#endif
#endif

View File

@ -77,6 +77,9 @@
#if USE(PTHREADS)
# include <pthread.h>
# include <sys/resource.h>
#if HAVE(PTHREAD_NP_H)
# include <pthread_np.h>
#endif
#endif
QT_BEGIN_NAMESPACE
@ -109,7 +112,11 @@ quintptr getStackLimit()
# else
void* stackBottom = 0;
pthread_attr_t attr;
#if HAVE(PTHREAD_NP_H) && OS(FREEBSD)
if (pthread_attr_get_np(pthread_self(), &attr) == 0) {
#else
if (pthread_getattr_np(pthread_self(), &attr) == 0) {
#endif
size_t stackSize = 0;
pthread_attr_getstack(&attr, &stackBottom, &stackSize);
pthread_attr_destroy(&attr);

View File

@ -67,6 +67,10 @@
#include <sys/storage.h> // __tls()
#endif
#if USE(PTHREADS) && HAVE(PTHREAD_NP_H)
#include <pthread_np.h>
#endif
QT_BEGIN_NAMESPACE
using namespace QV4;
@ -234,7 +238,11 @@ MemoryManager::MemoryManager()
# else
void* stackBottom = 0;
pthread_attr_t attr;
#if HAVE(PTHREAD_NP_H) && OS(FREEBSD)
if (pthread_attr_get_np(pthread_self(), &attr) == 0) {
#else
if (pthread_getattr_np(pthread_self(), &attr) == 0) {
#endif
size_t stackSize = 0;
pthread_attr_getstack(&attr, &stackBottom, &stackSize);
pthread_attr_destroy(&attr);

View File

@ -237,6 +237,15 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope)
: FunctionObject(scope, QStringLiteral("RegExp"))
{
setVTable(staticVTable());
clearLastMatch();
}
void RegExpCtor::clearLastMatch()
{
lastMatch = Primitive::nullValue();
lastInput = engine()->newIdentifier(QString());
lastMatchStart = 0;
lastMatchEnd = 0;
}
ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
@ -299,6 +308,14 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
return construct(that, callData);
}
void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e)
{
RegExpCtor *This = static_cast<RegExpCtor*>(that);
This->lastMatch.mark(e);
This->lastInput.mark(e);
FunctionObject::markObjects(that, e);
}
void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
{
Scope scope(engine);
@ -306,6 +323,28 @@ void RegExpPrototype::init(ExecutionEngine *engine, ObjectRef ctor)
ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(2));
// Properties deprecated in the spec but required by "the web" :(
ctor->defineAccessorProperty(QStringLiteral("lastMatch"), method_get_lastMatch_n<0>, 0);
ctor->defineAccessorProperty(QStringLiteral("$&"), method_get_lastMatch_n<0>, 0);
ctor->defineAccessorProperty(QStringLiteral("$1"), method_get_lastMatch_n<1>, 0);
ctor->defineAccessorProperty(QStringLiteral("$2"), method_get_lastMatch_n<2>, 0);
ctor->defineAccessorProperty(QStringLiteral("$3"), method_get_lastMatch_n<3>, 0);
ctor->defineAccessorProperty(QStringLiteral("$4"), method_get_lastMatch_n<4>, 0);
ctor->defineAccessorProperty(QStringLiteral("$5"), method_get_lastMatch_n<5>, 0);
ctor->defineAccessorProperty(QStringLiteral("$6"), method_get_lastMatch_n<6>, 0);
ctor->defineAccessorProperty(QStringLiteral("$7"), method_get_lastMatch_n<7>, 0);
ctor->defineAccessorProperty(QStringLiteral("$8"), method_get_lastMatch_n<8>, 0);
ctor->defineAccessorProperty(QStringLiteral("$9"), method_get_lastMatch_n<9>, 0);
ctor->defineAccessorProperty(QStringLiteral("lastParen"), method_get_lastParen, 0);
ctor->defineAccessorProperty(QStringLiteral("$+"), method_get_lastParen, 0);
ctor->defineAccessorProperty(QStringLiteral("input"), method_get_input, 0);
ctor->defineAccessorProperty(QStringLiteral("$_"), method_get_input, 0);
ctor->defineAccessorProperty(QStringLiteral("leftContext"), method_get_leftContext, 0);
ctor->defineAccessorProperty(QStringLiteral("$`"), method_get_leftContext, 0);
ctor->defineAccessorProperty(QStringLiteral("rightContext"), method_get_rightContext, 0);
ctor->defineAccessorProperty(QStringLiteral("$'"), method_get_rightContext, 0);
defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
defineDefaultProperty(QStringLiteral("exec"), method_exec, 1);
defineDefaultProperty(QStringLiteral("test"), method_test, 1);
@ -333,7 +372,11 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
}
uint* matchOffsets = (uint*)alloca(r->value->captureCount() * 2 * sizeof(uint));
int result = r->value->match(s, offset, matchOffsets);
const int result = r->value->match(s, offset, matchOffsets);
Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
regExpCtor->clearLastMatch();
if (result == -1) {
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
return Encode::null();
@ -351,10 +394,14 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
array->arrayData->put(i, v);
}
array->setArrayLengthUnchecked(len);
array->memberData[Index_ArrayIndex].value = Primitive::fromInt32(result);
array->memberData[Index_ArrayInput].value = arg.asReturnedValue();
regExpCtor->lastMatch = array;
regExpCtor->lastInput = arg->stringValue();
regExpCtor->lastMatchStart = matchOffsets[0];
regExpCtor->lastMatchEnd = matchOffsets[1];
if (r->global)
r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]);
@ -395,4 +442,46 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
return Encode::undefined();
}
template <int index>
ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
{
Scope scope(ctx);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
return ctx->engine->newString(QString())->asReturnedValue();
return result.asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
{
Scope scope(ctx);
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastMatch);
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
return ctx->engine->newString(QString())->asReturnedValue();
return result.asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_input(CallContext *ctx)
{
return static_cast<RegExpCtor*>(ctx->engine->regExpCtor.objectValue())->lastInput.asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_leftContext(CallContext *ctx)
{
Scope scope(ctx);
Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
QString lastInput = regExpCtor->lastInput->toQString();
return ctx->engine->newString(lastInput.left(regExpCtor->lastMatchStart))->asReturnedValue();
}
ReturnedValue RegExpPrototype::method_get_rightContext(CallContext *ctx)
{
Scope scope(ctx);
Scoped<RegExpCtor> regExpCtor(scope, ctx->engine->regExpCtor);
QString lastInput = regExpCtor->lastInput->toQString();
return ctx->engine->newString(lastInput.mid(regExpCtor->lastMatchEnd))->asReturnedValue();
}
QT_END_NAMESPACE

View File

@ -107,8 +107,15 @@ struct RegExpCtor: FunctionObject
V4_OBJECT
RegExpCtor(ExecutionContext *scope);
SafeValue lastMatch;
SafeString lastInput;
int lastMatchStart;
int lastMatchEnd;
void clearLastMatch();
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
static void markObjects(Managed *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
@ -120,6 +127,13 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_test(CallContext *ctx);
static ReturnedValue method_toString(CallContext *ctx);
static ReturnedValue method_compile(CallContext *ctx);
template <int index>
static ReturnedValue method_get_lastMatch_n(CallContext *ctx);
static ReturnedValue method_get_lastParen(CallContext *ctx);
static ReturnedValue method_get_input(CallContext *ctx);
static ReturnedValue method_get_leftContext(CallContext *ctx);
static ReturnedValue method_get_rightContext(CallContext *ctx);
};
}

View File

@ -65,6 +65,9 @@ struct Scope {
explicit Scope(ExecutionEngine *e)
: engine(e)
#ifndef QT_NO_DEBUG
, size(0)
#endif
{
mark = engine->jsStackTop;
}

View File

@ -136,6 +136,17 @@ QString QQmlBoundSignalExpression::expression() const
}
}
QV4::Function *QQmlBoundSignalExpression::function() const
{
if (m_expressionFunctionValid) {
Q_ASSERT (context() && engine());
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
QV4::Scoped<QV4::FunctionObject> v(scope, m_v8function.value());
return v ? v->function : 0;
}
return 0;
}
// Parts of this function mirror code in QQmlExpressionPrivate::value() and v8value().
// Changes made here may need to be made there and vice versa.
void QQmlBoundSignalExpression::evaluate(void **a)

View File

@ -90,6 +90,7 @@ public:
quint16 lineNumber() const { return m_line; }
quint16 columnNumber() const { return m_column; }
QString expression() const;
QV4::Function *function() const;
QObject *target() const { return m_target; }
QQmlEngine *engine() const { return context() ? context()->engine : 0; }

View File

@ -1681,6 +1681,7 @@ static AST::FunctionDeclaration *convertSignalHandlerExpressionToFunctionDeclara
AST::FunctionBody *body = new (pool) AST::FunctionBody(elements);
AST::FunctionDeclaration *functionDeclaration = new (pool) AST::FunctionDeclaration(jsEngine->newStringRef(signalName), paramList, body);
functionDeclaration->functionToken = statement->firstSourceLocation();
return functionDeclaration;
}

View File

@ -151,8 +151,10 @@ QT_BEGIN_NAMESPACE
#ifdef QML_THREADED_VME_INTERPRETER
# define QML_INSTR_HEADER void *code;
# define QML_INSTR_HEADER_INIT this->code = 0;
#else
# define QML_INSTR_HEADER quint8 instructionType;
# define QML_INSTR_HEADER_INIT this->instructionType = 0;
#endif
#define QML_INSTR_ENUM(I, FMT) I,
@ -547,6 +549,8 @@ FOR_EACH_QML_INSTR(QML_INSTR_META_TEMPLATE);
template<int Instr>
class QQmlInstructionData : public QQmlInstructionMeta<Instr>::DataType
{
public:
QQmlInstructionData() : QQmlInstructionMeta<Instr>::DataType() { QML_INSTR_HEADER_INIT }
};
QT_END_NAMESPACE

View File

@ -1835,6 +1835,17 @@ QList<QQmlType*> QQmlMetaType::qmlTypes()
return data->nameToType.values();
}
/*!
Returns the list of all registered types.
*/
QList<QQmlType*> QQmlMetaType::qmlAllTypes()
{
QReadLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
return data->types;
}
/*!
Returns the list of registered QML singleton types.
*/

View File

@ -80,6 +80,7 @@ public:
static QList<QString> qmlTypeNames();
static QList<QQmlType*> qmlTypes();
static QList<QQmlType*> qmlSingletonTypes();
static QList<QQmlType*> qmlAllTypes();
static QQmlType *qmlType(const QString &qualifiedName, int, int);
static QQmlType *qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);

View File

@ -2309,6 +2309,7 @@ void QQuickFlickable::timelineCompleted()
return;
}
movementEnding();
d->updateBeginningEnd();
}
void QQuickFlickable::movementStarting()

View File

@ -324,7 +324,6 @@ void QQuickTouchPoint::setSceneY(qreal sceneY)
QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
: QQuickItem(parent),
_currentWindow(0),
_minimumTouchPoints(0),
_maximumTouchPoints(INT_MAX),
_stealMouse(false)
@ -334,8 +333,8 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
if (qmlVisualTouchDebugging()) {
setFlag(QQuickItem::ItemHasContents);
}
#ifdef Q_OS_MAC
connect(this, &QQuickItem::windowChanged, this, &QQuickMultiPointTouchArea::setTouchEventsEnabledForWindow);
#ifdef Q_OS_OSX
setAcceptHoverEvents(true); // needed to enable touch events on mouse hover.
#endif
}
@ -548,28 +547,31 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
_pressedTouchPoints.append(dtp);
}
void QQuickMultiPointTouchArea::setTouchEventsEnabledForWindow(QWindow *window)
#ifdef Q_OS_OSX
void QQuickMultiPointTouchArea::hoverEnterEvent(QHoverEvent *event)
{
Q_UNUSED(event);
setTouchEventsEnabled(true);
}
void QQuickMultiPointTouchArea::hoverLeaveEvent(QHoverEvent *event)
{
Q_UNUSED(event);
setTouchEventsEnabled(false);
}
void QQuickMultiPointTouchArea::setTouchEventsEnabled(bool enable)
{
#ifdef Q_OS_MAC
// Resolve function for enabling touch events from the (cocoa) platform plugin.
typedef void (*RegisterTouchWindowFunction)(QWindow *, bool);
RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>(
QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (!registerTouchWindow)
return; // Not necessarily an error, Qt migh be using a different platform plugin.
return; // Not necessarily an error, Qt might be using a different platform plugin.
// Disable touch on the old window, enable on the new window.
if (_currentWindow)
registerTouchWindow(_currentWindow, false);
if (window)
registerTouchWindow(window, true);
// Save the current window, setTouchEventsEnabledForWindow will be called
// with a null window on disable.
_currentWindow = window;
#else // Q_OS_MAC
Q_UNUSED(window)
#endif
registerTouchWindow(window(), enable);
}
#endif // Q_OS_OSX
void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
{

View File

@ -250,9 +250,11 @@ protected:
bool shouldFilter(QEvent *event);
void grabGesture();
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
protected Q_SLOTS:
void setTouchEventsEnabledForWindow(QWindow *window);
#ifdef Q_OS_OSX
void hoverEnterEvent(QHoverEvent *event);
void hoverLeaveEvent(QHoverEvent *event);
void setTouchEventsEnabled(bool enable);
#endif
private:
void ungrab();
@ -261,7 +263,6 @@ private:
QList<QObject*> _releasedTouchPoints;
QList<QObject*> _pressedTouchPoints;
QList<QObject*> _movedTouchPoints;
QWindow *_currentWindow;
int _minimumTouchPoints;
int _maximumTouchPoints;
bool _stealMouse;

View File

@ -248,14 +248,13 @@ QQuickPinchAreaPrivate::~QQuickPinchAreaPrivate()
QQuickPinchArea::QQuickPinchArea(QQuickItem *parent)
: QQuickItem(*(new QQuickPinchAreaPrivate), parent)
, _currentWindow(0)
{
Q_D(QQuickPinchArea);
d->init();
setAcceptedMouseButtons(Qt::LeftButton);
setFiltersChildMouseEvents(true);
#ifdef Q_OS_MAC
connect(this, &QQuickItem::windowChanged, this, &QQuickPinchArea::setTouchEventsEnabledForWindow);
#ifdef Q_OS_OSX
setAcceptHoverEvents(true); // needed to enable touch events on mouse hover.
#endif
}
@ -537,6 +536,32 @@ void QQuickPinchArea::itemChange(ItemChange change, const ItemChangeData &value)
QQuickItem::itemChange(change, value);
}
#ifdef Q_OS_OSX
void QQuickPinchArea::hoverEnterEvent(QHoverEvent *event)
{
Q_UNUSED(event);
setTouchEventsEnabled(true);
}
void QQuickPinchArea::hoverLeaveEvent(QHoverEvent *event)
{
Q_UNUSED(event);
setTouchEventsEnabled(false);
}
void QQuickPinchArea::setTouchEventsEnabled(bool enable)
{
// Resolve function for enabling touch events from the (cocoa) platform plugin.
typedef void (*RegisterTouchWindowFunction)(QWindow *, bool);
RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>(
QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (!registerTouchWindow)
return; // Not necessarily an error, Qt might be using a different platform plugin.
registerTouchWindow(window(), enable);
}
#endif // Q_OS_OSX
QQuickPinch *QQuickPinchArea::pinch()
{
Q_D(QQuickPinchArea);
@ -545,29 +570,5 @@ QQuickPinch *QQuickPinchArea::pinch()
return d->pinch;
}
void QQuickPinchArea::setTouchEventsEnabledForWindow(QWindow *window)
{
#ifdef Q_OS_MAC
// Resolve function for enabling touch events from the (cocoa) platform plugin.
typedef void (*RegisterTouchWindowFunction)(QWindow *, bool);
RegisterTouchWindowFunction registerTouchWindow = reinterpret_cast<RegisterTouchWindowFunction>(
QGuiApplication::platformNativeInterface()->nativeResourceFunctionForIntegration("registertouchwindow"));
if (!registerTouchWindow)
return; // Not necessarily an error, Qt migh be using a different platform plugin.
// Disable touch on the old window, enable on the new window.
if (_currentWindow)
registerTouchWindow(_currentWindow, false);
if (window)
registerTouchWindow(window, true);
// Save the current window, setTouchEventsEnabledForWindow will be called
// with a null window on disable.
_currentWindow = window;
#else // Q_OS_MAC
Q_UNUSED(window)
#endif
}
QT_END_NAMESPACE

View File

@ -282,9 +282,11 @@ protected:
virtual void geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry);
virtual void itemChange(ItemChange change, const ItemChangeData& value);
private Q_SLOTS:
void setTouchEventsEnabledForWindow(QWindow *window);
#ifdef Q_OS_OSX
void hoverEnterEvent(QHoverEvent *event);
void hoverLeaveEvent(QHoverEvent *event);
void setTouchEventsEnabled(bool enable);
#endif
private:
void updatePinch();
@ -292,7 +294,6 @@ private:
void handleRelease();
private:
QWindow *_currentWindow;
Q_DISABLE_COPY(QQuickPinchArea)
Q_DECLARE_PRIVATE(QQuickPinchArea)
};

View File

@ -2088,7 +2088,7 @@ QRectF QQuickText::boundingRect() const
Q_D(const QQuickText);
QRectF rect = d->layedOutTextRect;
rect.moveLeft(QQuickTextUtil::alignedX(rect.width(), width(), d->hAlign));
rect.moveLeft(QQuickTextUtil::alignedX(rect.width(), width(), effectiveHAlign()));
rect.moveTop(QQuickTextUtil::alignedY(rect.height(), height(), d->vAlign));
if (d->style != Normal)
@ -2225,11 +2225,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
const QColor linkColor = QColor::fromRgba(d->linkColor);
if (d->richText) {
const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), d->hAlign);
const qreal dx = QQuickTextUtil::alignedX(d->layedOutTextRect.width(), width(), effectiveHAlign());
d->ensureDoc();
node->addTextDocument(QPointF(dx, dy), d->extra->doc, color, d->style, styleColor, linkColor);
} else if (d->layedOutTextRect.width() > 0) {
const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), d->hAlign);
const qreal dx = QQuickTextUtil::alignedX(d->lineWidth, width(), effectiveHAlign());
int unelidedLineCount = d->lineCount;
if (d->elideLayout)
unelidedLineCount -= 1;
@ -2501,7 +2501,7 @@ QString QQuickTextPrivate::anchorAt(const QPointF &mousePos) const
link = anchorAt(elideLayout, translatedMousePos);
return link;
} else if (richText && extra.isAllocated() && extra->doc) {
translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), hAlign);
translatedMousePos.rx() -= QQuickTextUtil::alignedX(layedOutTextRect.width(), q->width(), q->effectiveHAlign());
return extra->doc->documentLayout()->anchorAt(translatedMousePos);
}
return QString();

View File

@ -343,6 +343,8 @@ void QQuickWindowPrivate::syncSceneGraph()
if (clearBeforeRendering)
mode |= QSGRenderer::ClearColorBuffer;
renderer->setClearMode(mode);
context->endSync();
}

View File

@ -599,11 +599,6 @@ void Element::computeBounds()
boundsOutsideFloatRange = bounds.isOutsideFloatRange();
}
RenderNodeElement::~RenderNodeElement()
{
delete fbo;
}
bool Batch::isMaterialCompatible(Element *e) const
{
// If material has changed between opaque and translucent, it is not compatible
@ -751,6 +746,7 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_nextRenderOrder(0)
, m_partialRebuild(false)
, m_partialRebuildRoot(0)
, m_useDepthBuffer(true)
, m_opaqueBatches(16)
, m_alphaBatches(16)
, m_batchPool(16)
@ -761,6 +757,8 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_zRange(0)
, m_currentMaterial(0)
, m_currentShader(0)
, m_currentClip(0)
, m_currentClipType(NoClip)
, m_vao(0)
{
setNodeUpdater(new Updater(this));
@ -809,6 +807,8 @@ Renderer::Renderer(QSGRenderContext *ctx)
m_vao = new QOpenGLVertexArrayObject(this);
m_vao->create();
}
m_useDepthBuffer = ctx->openglContext()->format().depthBufferSize() > 0;
}
static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
@ -1005,6 +1005,8 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
snode->data = e;
Q_ASSERT(!m_renderNodeElements.contains(static_cast<QSGRenderNode *>(node)));
m_renderNodeElements.insert(e->renderNode, e);
m_useDepthBuffer = false;
m_rebuild |= FullRebuild;
}
QSGNODE_TRAVERSE(node)
@ -1250,7 +1252,7 @@ void Renderer::buildRenderLists(QSGNode *node)
Q_ASSERT(e);
bool opaque = gn->inheritedOpacity() > OPAQUE_LIMIT && !(gn->activeMaterial()->flags() & QSGMaterial::Blending);
if (opaque)
if (opaque && m_useDepthBuffer)
m_opaqueRenderList << e;
else
m_alphaRenderList << e;
@ -1631,10 +1633,13 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData,
}
}
float *vzorder = (float *) *zData;
float zorder = 1.0f - e->order * m_zRange;
for (int i=0; i<vCount; ++i)
vzorder[i] = zorder;
if (m_useDepthBuffer) {
float *vzorder = (float *) *zData;
float zorder = 1.0f - e->order * m_zRange;
for (int i=0; i<vCount; ++i)
vzorder[i] = zorder;
*zData += vCount * sizeof(float);
}
int iCount = g->indexCount();
quint16 *indices = (quint16 *) *indexData;
@ -1658,7 +1663,6 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData,
}
*vertexData += vCount * vSize;
*zData += vCount * sizeof(float);
*indexData += iCount * sizeof(quint16);
*iBase += vCount;
*indexCount += iCount;
@ -1754,8 +1758,9 @@ void Renderer::uploadBatch(Batch *b)
int bufferSize = b->vertexCount * g->sizeOfVertex();
int ibufferSize = 0;
if (b->merged) {
bufferSize += b->vertexCount * sizeof(float);
ibufferSize = b->indexCount * sizeof(quint16);
if (m_useDepthBuffer)
bufferSize += b->vertexCount * sizeof(float);
} else {
ibufferSize = unmergedIndexSize;
}
@ -1777,7 +1782,7 @@ void Renderer::uploadBatch(Batch *b)
#ifdef QSG_SEPARATE_INDEX_BUFFER
char *indexData = b->ibo.data;
#else
char *indexData = zData + b->vertexCount * sizeof(float);
char *indexData = zData + (m_useDepthBuffer ? b->vertexCount * sizeof(float) : 0);
#endif
quint16 iOffset = 0;
@ -1857,7 +1862,7 @@ void Renderer::uploadBatch(Batch *b)
dump << ") ";
offset += attr.tupleSize * size_of_type(attr.type);
}
if (b->merged) {
if (b->merged && m_useDepthBuffer) {
float zorder = ((float*)(b->vbo.data + b->vertexCount * g->sizeOfVertex()))[i];
dump << " Z:(" << zorder << ")";
}
@ -1907,10 +1912,10 @@ void Renderer::updateClip(const QSGClipNode *clipList, const Batch *batch)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (batch->isOpaque)
glDisable(GL_DEPTH_TEST);
ClipType type = updateStencilClip(m_currentClip);
m_currentClipType = updateStencilClip(m_currentClip);
if (batch->isOpaque) {
glEnable(GL_DEPTH_TEST);
if (type & StencilClip)
if (m_currentClipType & StencilClip)
glDepthMask(true);
}
}
@ -2025,7 +2030,7 @@ void Renderer::renderMergedBatch(const Batch *batch)
QSGMaterial *material = gn->activeMaterial();
ShaderManager::Shader *sms = m_shaderManager->prepareMaterial(material);
ShaderManager::Shader *sms = m_useDepthBuffer ? m_shaderManager->prepareMaterial(material) : m_shaderManager->prepareMaterialNoRewrite(material);
QSGMaterialShader *program = sms->program;
if (m_currentShader != sms)
@ -2054,7 +2059,8 @@ void Renderer::renderMergedBatch(const Batch *batch)
glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, g->sizeOfVertex(), (void *) (qintptr) (offset + draw.vertices));
offset += a.tupleSize * size_of_type(a.type);
}
glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders));
if (m_useDepthBuffer)
glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders));
glDrawElements(g->drawingMode(), draw.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (indexBase + draw.indices));
}
@ -2136,8 +2142,10 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
m_current_determinant = m_current_model_view_matrix.determinant();
m_current_projection_matrix = projectionMatrix();
m_current_projection_matrix(2, 2) = m_zRange;
m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange;
if (m_useDepthBuffer) {
m_current_projection_matrix(2, 2) = m_zRange;
m_current_projection_matrix(2, 3) = 1.0f - e->order * m_zRange;
}
program->updateState(state(dirty), material, m_currentMaterial);
@ -2187,25 +2195,25 @@ void Renderer::renderBatches()
<< " -> Alpha: " << qsg_countNodesInBatches(m_alphaBatches) << " nodes in " << m_alphaBatches.size() << " batches...";
}
for (QHash<QSGRenderNode *, RenderNodeElement *>::const_iterator it = m_renderNodeElements.constBegin();
it != m_renderNodeElements.constEnd(); ++it) {
prepareRenderNode(it.value());
}
QRect r = viewportRect();
glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
glClearColor(clearColor().redF(), clearColor().greenF(), clearColor().blueF(), clearColor().alphaF());
#if defined(QT_OPENGL_ES)
glClearDepthf(1);
#else
glClearDepth(1);
#endif
if (m_useDepthBuffer) {
#if defined(QT_OPENGL_ES)
glClearDepthf(1);
#else
glClearDepth(1);
#endif
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(true);
glDisable(GL_BLEND);
} else {
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
}
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glDepthMask(true);
glColorMask(true, true, true, true);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
@ -2232,7 +2240,8 @@ void Renderer::renderBatches()
}
glEnable(GL_BLEND);
glDepthMask(false);
if (m_useDepthBuffer)
glDepthMask(false);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
if (Q_LIKELY(renderAlpha)) {
@ -2252,7 +2261,6 @@ void Renderer::renderBatches()
updateStencilClip(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Renderer::deleteRemovedElements()
@ -2404,33 +2412,15 @@ void Renderer::render()
m_vao->release();
}
void Renderer::prepareRenderNode(RenderNodeElement *e)
void Renderer::renderRenderNode(Batch *batch)
{
if (e->fbo && e->fbo->size() != deviceRect().size()) {
delete e->fbo;
e->fbo = 0;
}
if (Q_UNLIKELY(debug_render))
qDebug() << " -" << batch << "rendernode";
if (!e->fbo)
e->fbo = new QOpenGLFramebufferObject(deviceRect().size(), QOpenGLFramebufferObject::CombinedDepthStencil);
e->fbo->bind();
Q_ASSERT(batch->first->isRenderNode);
RenderNodeElement *e = (RenderNodeElement *) batch->first;
glDisable(GL_STENCIL_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
QSGRenderNode::RenderState state;
QMatrix4x4 pm = projectionMatrix();
state.projectionMatrix = &pm;
state.scissorEnabled = false;
state.stencilEnabled = false;
setActiveShader(0, 0);
QSGNode *clip = e->renderNode->parent();
e->renderNode->m_clip_list = 0;
@ -2442,6 +2432,16 @@ void Renderer::prepareRenderNode(RenderNodeElement *e)
clip = clip->parent();
}
updateClip(e->renderNode->m_clip_list, batch);
QSGRenderNode::RenderState state;
QMatrix4x4 pm = projectionMatrix();
state.projectionMatrix = &pm;
state.scissorEnabled = m_currentClipType & ScissorClip;
state.stencilEnabled = m_currentClipType & StencilClip;
state.scissorRect = m_current_scissor_rect;
state.stencilValue = m_current_stencil_value;
QSGNode *xform = e->renderNode->parent();
QMatrix4x4 matrix;
while (xform != rootNode()) {
@ -2463,66 +2463,51 @@ void Renderer::prepareRenderNode(RenderNodeElement *e)
opacity = opacity->parent();
}
glDisable(GL_STENCIL_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
e->renderNode->render(state);
e->renderNode->m_matrix = 0;
e->renderNode->m_clip_list = 0;
bindable()->bind();
}
void Renderer::renderRenderNode(Batch *batch)
{
updateStencilClip(0);
m_currentClip = 0;
setActiveShader(0, 0);
if (!m_shaderManager->blitProgram) {
m_shaderManager->blitProgram = new QOpenGLShaderProgram();
QSGShaderSourceBuilder::initializeProgramFromFiles(
m_shaderManager->blitProgram,
QStringLiteral(":/scenegraph/shaders/rendernode.vert"),
QStringLiteral(":/scenegraph/shaders/rendernode.frag"));
m_shaderManager->blitProgram->bindAttributeLocation("av", 0);
m_shaderManager->blitProgram->bindAttributeLocation("at", 1);
m_shaderManager->blitProgram->link();
Q_ASSERT(m_shaderManager->blitProgram->isLinked());
QSGRenderNode::StateFlags changes = e->renderNode->changedStates();
if (changes & QSGRenderNode::ViewportState) {
QRect r = viewportRect();
glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
}
RenderNodeElement *e = static_cast<RenderNodeElement *>(batch->first);
glBindTexture(GL_TEXTURE_2D, e->fbo->texture());
if (changes & QSGRenderNode::StencilState) {
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0xff);
glDisable(GL_STENCIL_TEST);
}
m_shaderManager->blitProgram->bind();
if (changes & (QSGRenderNode::StencilState | QSGRenderNode::ScissorState)) {
glDisable(GL_SCISSOR_TEST);
m_currentClip = 0;
m_currentClipType = NoClip;
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
if (changes & QSGRenderNode::DepthState)
glDisable(GL_DEPTH_TEST);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
if (changes & QSGRenderNode::ColorState)
bindable()->reactivate();
float z = 1.0f - e->order * m_zRange;
if (changes & QSGRenderNode::BlendState) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
float av[] = { -1, -1, z,
1, -1, z,
-1, 1, z,
1, 1, z };
float at[] = { 0, 0,
1, 0,
0, 1,
1, 1 };
if (changes & QSGRenderNode::CullState) {
glFrontFace(isMirrored() ? GL_CW : GL_CCW);
glDisable(GL_CULL_FACE);
}
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, av);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, at);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindTexture(GL_TEXTURE_2D, 0);
}
QT_END_NAMESPACE

View File

@ -194,15 +194,11 @@ struct RenderNodeElement : public Element {
RenderNodeElement(QSGRenderNode *rn)
: Element(0)
, renderNode(rn)
, fbo(0)
{
isRenderNode = true;
}
~RenderNodeElement();
QSGRenderNode *renderNode;
QOpenGLFramebufferObject *fbo;
};
struct BatchRootInfo {
@ -436,7 +432,6 @@ private:
void renderUnmergedBatch(const Batch *batch);
void updateClip(const QSGClipNode *clipList, const Batch *batch);
const QMatrix4x4 &matrixForRoot(Node *node);
void prepareRenderNode(RenderNodeElement *e);
void renderRenderNode(Batch *batch);
void setActiveShader(QSGMaterialShader *program, ShaderManager::Shader *shader);
@ -460,6 +455,8 @@ private:
bool m_partialRebuild;
QSGNode *m_partialRebuildRoot;
bool m_useDepthBuffer;
QHash<QSGRenderNode *, RenderNodeElement *> m_renderNodeElements;
QDataBuffer<Batch *> m_opaqueBatches;
QDataBuffer<Batch *> m_alphaBatches;
@ -483,6 +480,7 @@ private:
QSGMaterialShader *m_currentProgram;
ShaderManager::Shader *m_currentShader;
const QSGClipNode *m_currentClip;
ClipType m_currentClipType;
// For minimal OpenGL core profile support
QOpenGLVertexArrayObject *m_vao;

View File

@ -210,10 +210,17 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext)
static bool dumped = false;
if (!dumped && qEnvironmentVariableIsSet("QSG_INFO")) {
dumped = true;
qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR);
qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER);
qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION);
qDebug() << "GL_EXTENSIONS:\n " << QByteArray((const char *) glGetString(GL_EXTENSIONS)).replace(" ", "\n ").constData();
QSurfaceFormat format = renderContext->openglContext()->format();
qDebug() << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize();
qDebug() << "Depth Buffer: " << format.depthBufferSize();
qDebug() << "Stencil Buffer: " << format.stencilBufferSize();
qDebug() << "Samples: " << format.samples();
qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR);
qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER);
qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION);
QSet<QByteArray> exts = renderContext->openglContext()->extensions();
QByteArray all; foreach (const QByteArray &e, exts) all += ' ' + e;
qDebug() << "GL_EXTENSIONS: " << all.constData();
}
d->mutex.unlock();
@ -282,8 +289,10 @@ QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc)
QSurfaceFormat QSGContext::defaultSurfaceFormat() const
{
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
static bool useStencil = qEnvironmentVariableIsEmpty("QSG_NO_STENCIL_BUFFER");
format.setDepthBufferSize(useDepth ? 24 : 0);
format.setStencilBufferSize(useStencil ? 8 : 0);
if (QQuickWindow::hasDefaultAlphaBuffer())
format.setAlphaBufferSize(8);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
@ -349,6 +358,12 @@ QSGRenderContext::~QSGRenderContext()
invalidate();
}
void QSGRenderContext::endSync()
{
qDeleteAll(m_texturesToDelete);
m_texturesToDelete.clear();
}
static QBasicMutex qsg_framerender_mutex;
void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
@ -466,6 +481,9 @@ void QSGRenderContext::invalidate()
if (!m_gl)
return;
qDeleteAll(m_texturesToDelete);
m_texturesToDelete.clear();
qDeleteAll(m_textures.values());
m_textures.clear();
@ -608,10 +626,8 @@ QSGTexture *QSGRenderContext::textureForFactory(QQuickTextureFactory *factory, Q
void QSGRenderContext::textureFactoryDestroyed(QObject *o)
{
m_mutex.lock();
QSGTexture *t = m_textures.take(static_cast<QQuickTextureFactory *>(o));
m_texturesToDelete << m_textures.take(static_cast<QQuickTextureFactory *>(o));
m_mutex.unlock();
if (t)
t->deleteLater();
}
QT_END_NAMESPACE

View File

@ -94,6 +94,7 @@ public:
virtual void invalidate();
virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId);
virtual void endSync();
virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo);
QSGDepthStencilBufferManager *depthStencilBufferManager();
@ -124,6 +125,7 @@ protected:
QMutex m_mutex;
QHash<QQuickTextureFactory *, QSGTexture *> m_textures;
QSet<QSGTexture *> m_texturesToDelete;
QSGAtlasTexture::Manager *m_atlasManager;
QSGDepthStencilBufferManager *m_depthStencilManager;

View File

@ -385,7 +385,7 @@ void QSGDefaultRectangleNode::updateGeometry()
int borderTail = 0;
int outerAAHead = 0;
int outerAATail = 0;
bool hasFill = m_color.rgba() != 0 || !stops.isEmpty();
bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
if (hasFill)
indexCount += fillIndexCount;
if (m_antialiasing) {
@ -609,7 +609,7 @@ void QSGDefaultRectangleNode::updateGeometry()
int borderTail = 0;
int outerAAHead = 0;
int outerAATail = 0;
bool hasFill = m_color.rgba() != 0 || !stops.isEmpty();
bool hasFill = m_color.alpha() > 0 || !stops.isEmpty();
if (hasFill)
indexCount += fillIndexCount;
if (m_antialiasing) {

View File

@ -48,6 +48,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QSurface>
#include <QtGui/qpa/qplatformnativeinterface.h>
#include <private/qsgtexture_p.h>
@ -144,10 +145,21 @@ Atlas::Atlas(const QSize &size)
{
#ifdef QT_OPENGL_ES
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
|| deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
|| deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0;
#else
static bool wrongfullyReportsBgra8888Support = false;
#endif
const char *ext = (const char *) glGetString(GL_EXTENSIONS);
if (strstr(ext, "GL_EXT_bgra")
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
|| strstr(ext, "GL_IMG_texture_format_BGRA8888")) {
if (!wrongfullyReportsBgra8888Support
&& (strstr(ext, "GL_EXT_bgra")
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
|| strstr(ext, "GL_IMG_texture_format_BGRA8888"))) {
m_internalFormat = m_externalFormat = GL_BGRA;
#ifdef Q_OS_IOS
} else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {

View File

@ -47,8 +47,10 @@
#include <qthread.h>
#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlglobal_p.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformnativeinterface.h>
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(__UCLIBC__)
#define CAN_BACKTRACE_EXECINFO
#endif
@ -679,14 +681,25 @@ void QSGPlainTexture::bind()
GLenum externalFormat = GL_RGBA;
GLenum internalFormat = GL_RGBA;
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
static bool wrongfullyReportsBgra8888Support = deviceName->compare(QStringLiteral("samsung SM-T211"), Qt::CaseInsensitive) == 0
|| deviceName->compare(QStringLiteral("samsung SM-T210"), Qt::CaseInsensitive) == 0
|| deviceName->compare(QStringLiteral("samsung SM-T215"), Qt::CaseInsensitive) == 0;
#else
static bool wrongfullyReportsBgra8888Support = false;
#endif
QOpenGLContext *context = QOpenGLContext::currentContext();
if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) {
externalFormat = GL_BGRA;
#ifdef QT_OPENGL_ES
internalFormat = GL_BGRA;
#endif
} else if (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
|| context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) {
} else if (!wrongfullyReportsBgra8888Support
&& (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
|| context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888")))) {
externalFormat = GL_BGRA;
internalFormat = GL_BGRA;
#ifdef Q_OS_IOS

View File

@ -0,0 +1,9 @@
import QtQuick 2.0
Rectangle {
width: 400
height: 400
onWidthChanged: console.log(width);
Component.onCompleted: width = 500;
}

View File

@ -19,4 +19,5 @@ OTHER_FILES += \
data/test.qml \
data/exit.qml \
data/scenegraphTest.qml \
data/TestImage_2x2.png
data/TestImage_2x2.png \
data/signalSourceLocation.qml

View File

@ -181,6 +181,7 @@ private slots:
void scenegraphData();
void profileOnExit();
void controlFromJS();
void signalSourceLocation();
};
void QQmlProfilerClient::messageReceived(const QByteArray &message)
@ -513,6 +514,35 @@ void tst_QQmlProfilerService::controlFromJS()
QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
void tst_QQmlProfilerService::signalSourceLocation()
{
connect(true, "signalSourceLocation.qml");
QVERIFY(m_client);
QTRY_COMPARE(m_client->state(), QQmlDebugClient::Enabled);
m_client->setTraceState(true);
while (!(m_process->output().contains(QLatin1String("500"))))
QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
m_client->setTraceState(false);
QVERIFY2(QQmlDebugTest::waitForSignal(m_client, SIGNAL(complete())), "No trace received in time.");
// must start with "StartTrace"
QCOMPARE(m_client->traceMessages.first().messageType, (int)QQmlProfilerClient::Event);
QCOMPARE(m_client->traceMessages.first().detailType, (int)QQmlProfilerClient::StartTrace);
QVERIFY(m_client->traceMessages[14].detailData.endsWith("signalSourceLocation.qml"));
QVERIFY(m_client->traceMessages[14].line == 8);
QVERIFY(m_client->traceMessages[14].column == 28);
QVERIFY(m_client->traceMessages[16].detailData.endsWith("signalSourceLocation.qml"));
QVERIFY(m_client->traceMessages[16].line == 7);
QVERIFY(m_client->traceMessages[16].column == 21);
// must end with "EndTrace"
QCOMPARE(m_client->traceMessages.last().messageType, (int)QQmlProfilerClient::Event);
QCOMPARE(m_client->traceMessages.last().detailType, (int)QQmlProfilerClient::EndTrace);
}
QTEST_MAIN(tst_QQmlProfilerService)
#include "tst_qqmlprofilerservice.moc"

View File

@ -148,6 +148,8 @@ private slots:
void functionDeclarationsInConditionals();
void arrayPop_QTBUG_35979();
void regexpLastMatch();
};
tst_QJSEngine::tst_QJSEngine()
@ -2705,6 +2707,68 @@ void tst_QJSEngine::arrayPop_QTBUG_35979()
QCOMPARE(result.toString(), QString("1,3"));
}
void tst_QJSEngine::regexpLastMatch()
{
QJSEngine eng;
QCOMPARE(eng.evaluate("RegExp.input").toString(), QString());
QJSValue hasProperty;
for (int i = 1; i < 9; ++i) {
hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$" + QString::number(i) + "\")");
QVERIFY(hasProperty.isBool());
QVERIFY(hasProperty.toBool());
}
hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$0\")");
QVERIFY(hasProperty.isBool());
QVERIFY(!hasProperty.toBool());
hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$10\")");
QVERIFY(!hasProperty.toBool());
hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"lastMatch\")");
QVERIFY(hasProperty.toBool());
hasProperty = eng.evaluate("RegExp.hasOwnProperty(\"$&\")");
QVERIFY(hasProperty.toBool());
QJSValue result = eng.evaluate(""
"var re = /h(el)l(o)/\n"
"var text = \"blah hello world\"\n"
"text.match(re)\n");
QVERIFY(!result.isError());
QJSValue match = eng.evaluate("RegExp.$1");
QCOMPARE(match.toString(), QString("el"));
match = eng.evaluate("RegExp.$2");
QCOMPARE(match.toString(), QString("o"));
for (int i = 3; i <= 9; ++i) {
match = eng.evaluate("RegExp.$" + QString::number(i));
QVERIFY(match.isString());
QCOMPARE(match.toString(), QString());
}
QCOMPARE(eng.evaluate("RegExp.input").toString(), QString("blah hello world"));
QCOMPARE(eng.evaluate("RegExp.lastParen").toString(), QString("o"));
QCOMPARE(eng.evaluate("RegExp.leftContext").toString(), QString("blah "));
QCOMPARE(eng.evaluate("RegExp.rightContext").toString(), QString(" world"));
QCOMPARE(eng.evaluate("RegExp.lastMatch").toString(), QString("hello"));
result = eng.evaluate(""
"var re = /h(ello)/\n"
"var text = \"hello\"\n"
"text.match(re)\n");
QVERIFY(!result.isError());
match = eng.evaluate("RegExp.$1");
QCOMPARE(match.toString(), QString("ello"));
for (int i = 2; i <= 9; ++i) {
match = eng.evaluate("RegExp.$" + QString::number(i));
QVERIFY(match.isString());
QCOMPARE(match.toString(), QString());
}
}
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"

View File

@ -1440,17 +1440,23 @@ void tst_qquickflickable::stopAtBounds_data()
{
QTest::addColumn<bool>("transpose");
QTest::addColumn<bool>("invert");
QTest::addColumn<bool>("pixelAligned");
QTest::newRow("left") << false << false;
QTest::newRow("right") << false << true;
QTest::newRow("top") << true << false;
QTest::newRow("bottom") << true << true;
QTest::newRow("left") << false << false << false;
QTest::newRow("right") << false << true << false;
QTest::newRow("top") << true << false << false;
QTest::newRow("bottom") << true << true << false;
QTest::newRow("left,pixelAligned") << false << false << true;
QTest::newRow("right,pixelAligned") << false << true << true;
QTest::newRow("top,pixelAligned") << true << false << true;
QTest::newRow("bottom,pixelAligned") << true << true << true;
}
void tst_qquickflickable::stopAtBounds()
{
QFETCH(bool, transpose);
QFETCH(bool, invert);
QFETCH(bool, pixelAligned);
QQuickView view;
view.setSource(testFileUrl("stopAtBounds.qml"));
@ -1469,6 +1475,7 @@ void tst_qquickflickable::stopAtBounds()
flickable->setContentY(invert ? 100 : 0);
else
flickable->setContentX(invert ? 100 : 0);
flickable->setPixelAligned(pixelAligned);
const int threshold = qApp->styleHints()->startDragDistance();
@ -1518,6 +1525,29 @@ void tst_qquickflickable::stopAtBounds()
}
QTest::mouseRelease(&view, Qt::LeftButton, 0, position);
if (transpose) {
flickable->setContentY(invert ? 100 : 0);
} else {
flickable->setContentX(invert ? 100 : 0);
}
if (invert)
flick(&view, QPoint(20,20), QPoint(100,100), 100);
else
flick(&view, QPoint(100,100), QPoint(20,20), 100);
QVERIFY(flickable->isFlicking());
if (transpose) {
if (invert)
QTRY_COMPARE(flickable->isAtYBeginning(), true);
else
QTRY_COMPARE(flickable->isAtYEnd(), true);
} else {
if (invert)
QTRY_COMPARE(flickable->isAtXBeginning(), true);
else
QTRY_COMPARE(flickable->isAtXEnd(), true);
}
}
void tst_qquickflickable::nestedMouseAreaUsingTouch()

View File

@ -1724,6 +1724,12 @@ void tst_qquicktext::linkInteraction_data()
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignBottom).center())
<< singleLineLink
<< singleLineLink << singleLineLink;
QTest::newRow("click on mirrored link")
<< singleLineText << 240.
<< "horizontalAlignment: Text.AlignLeft; LayoutMirroring.enabled: true"
<< (PointVector() << metrics.characterRectangle(18, Qt::AlignRight, Qt::AlignTop).center())
<< singleLineLink
<< singleLineLink << singleLineLink;
QTest::newRow("click on center aligned link")
<< singleLineText << 240.
<< "horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignVCenter"
@ -2545,6 +2551,18 @@ void tst_qquicktext::boundingRect()
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
QCOMPARE(text->boundingRect().height(), line.height());
QQuickItemPrivate::get(text)->setLayoutMirror(true);
QCOMPARE(text->boundingRect().x(), qreal(0));
QCOMPARE(text->boundingRect().y(), qreal(0));
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
QCOMPARE(text->boundingRect().height(), line.height());
text->setHAlign(QQuickText::AlignLeft);
QCOMPARE(text->boundingRect().x(), text->width() - line.naturalTextWidth());
QCOMPARE(text->boundingRect().y(), qreal(0));
QCOMPARE(text->boundingRect().width(), line.naturalTextWidth());
QCOMPARE(text->boundingRect().height(), line.height());
text->setWrapMode(QQuickText::Wrap);
QCOMPARE(text->boundingRect().right(), text->width());
QCOMPARE(text->boundingRect().y(), qreal(0));

View File

@ -98,14 +98,14 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met
const QMetaObject *meta = object->metaObject();
if (verbose)
qDebug() << "Processing object" << meta->className();
std::cerr << "Processing object" << qPrintable( meta->className() ) << std::endl;
collectReachableMetaObjects(meta, metas);
for (int index = 0; index < meta->propertyCount(); ++index) {
QMetaProperty prop = meta->property(index);
if (QQmlMetaType::isQObject(prop.userType())) {
if (verbose)
qDebug() << " Processing property" << prop.name();
std::cerr << " Processing property" << qPrintable( prop.name() ) << std::endl;
currentProperty = QString("%1::%2").arg(meta->className(), prop.name());
// if the property was not initialized during construction,
@ -175,20 +175,41 @@ QByteArray convertToId(const QMetaObject *mo)
if (!className.isEmpty())
return className;
qWarning() << "Found a QMetaObject without a className, generating a random name";
std::cerr << "Found a QMetaObject without a className, generating a random name" << std::endl;
className = QByteArray("error-unknown-name-");
className.append(QByteArray::number(generatedNames.size()));
generatedNames.insert(mo, className);
return className;
}
QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const QList<QQmlType *> &skip = QList<QQmlType *>())
// Collect all metaobjects for types registered with qmlRegisterType() without parameters
void collectReachableMetaObjectsWithoutQmlName( QSet<const QMetaObject *>& metas ) {
foreach (const QQmlType *ty, QQmlMetaType::qmlAllTypes()) {
if ( ! metas.contains(ty->metaObject()) ) {
if (!ty->isComposite()) {
collectReachableMetaObjects(ty, &metas);
} else {
qmlTypesByCompositeName[ty->elementName()] = ty;
}
}
}
}
QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine,
QSet<const QMetaObject *> &noncreatables,
QSet<const QMetaObject *> &singletons,
const QList<QQmlType *> &skip = QList<QQmlType *>())
{
QSet<const QMetaObject *> metas;
metas.insert(FriendlyQObject::qtMeta());
QHash<QByteArray, QSet<QByteArray> > extensions;
foreach (const QQmlType *ty, QQmlMetaType::qmlTypes()) {
if (!ty->isCreatable())
noncreatables.insert(ty->metaObject());
if (ty->isSingleton())
singletons.insert(ty->metaObject());
if (!ty->isComposite()) {
qmlTypesByCppName[ty->metaObject()->className()].insert(ty);
if (ty->isExtendedType())
@ -255,15 +276,15 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
if (ty->isSingleton()) {
QQmlType::SingletonInstanceInfo *siinfo = ty->singletonInstanceInfo();
if (!siinfo) {
qWarning() << "Internal error, " << tyName
<< "(" << QString::fromUtf8(ty->typeName()) << ")"
<< " is singleton, but has no singletonInstanceInfo";
std::cerr << "Internal error, " << qPrintable(tyName)
<< "(" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")"
<< " is singleton, but has no singletonInstanceInfo" << std::endl;
continue;
}
if (siinfo->qobjectCallback) {
if (verbose)
qDebug() << "Trying to get singleton for " << tyName
<< " (" << siinfo->typeName << ")";
std::cerr << "Trying to get singleton for " << qPrintable(tyName)
<< " (" << qPrintable( siinfo->typeName ) << ")" << std::endl;
siinfo->init(engine);
collectReachableMetaObjects(object, &metas);
object = siinfo->qobjectApi(engine);
@ -273,8 +294,8 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
}
} else {
if (verbose)
qDebug() << "Trying to create object " << tyName
<< " (" << QString::fromUtf8(ty->typeName()) << ")";
std::cerr << "Trying to create object " << qPrintable( tyName )
<< " (" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")" << std::endl;
object = ty->create();
}
@ -282,15 +303,17 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, const
if (object) {
if (verbose)
qDebug() << "Got " << tyName
<< " (" << QString::fromUtf8(ty->typeName()) << ")";
std::cerr << "Got " << qPrintable( tyName )
<< " (" << qPrintable( QString::fromUtf8(ty->typeName()) ) << ")" << std::endl;
collectReachableMetaObjects(object, &metas);
} else {
qWarning() << "Could not create" << tyName;
std::cerr << "Could not create" << qPrintable(tyName) << std::endl;
}
}
}
collectReachableMetaObjectsWithoutQmlName(metas);
return metas;
}
@ -406,6 +429,12 @@ public:
qml->writeArrayBinding(QLatin1String("exports"), QStringList() << exportString);
qml->writeArrayBinding(QLatin1String("exportMetaObjectRevisions"), QStringList() << QString::number(compositeType->minorVersion()));
if (compositeType->isCreatable())
qml->writeIsCreatable(false);
if (compositeType->isSingleton())
qml->writeIsSingleton(true);
for (int index = mainMeta->classInfoCount() - 1 ; index >= 0 ; --index) {
QMetaClassInfo classInfo = mainMeta->classInfo(index);
if (QLatin1String(classInfo.name()) == QLatin1String("DefaultProperty")) {
@ -437,7 +466,7 @@ public:
qml->writeEndObject();
}
void dump(const QMetaObject *meta)
void dump(const QMetaObject *meta, bool isUncreatable, bool isSingleton)
{
qml->writeStartObject("Component");
@ -469,6 +498,12 @@ public:
std::sort(exportStrings.begin(), exportStrings.end());
qml->writeArrayBinding(QLatin1String("exports"), exportStrings);
if (isUncreatable)
qml->writeIsCreatable(false);
if (isSingleton)
qml->writeIsSingleton(true);
// write meta object revisions
QStringList metaObjectRevisions;
foreach (const QString &exportString, exportStrings) {
@ -622,7 +657,6 @@ private:
}
};
enum ExitCode {
EXIT_INVALIDARGUMENTS = 1,
EXIT_SEGV = 2,
@ -642,12 +676,12 @@ void sigSegvHandler(int) {
void printUsage(const QString &appName)
{
qWarning() << qPrintable(QString(
std::cerr << qPrintable(QString(
"Usage: %1 [-v] [-noinstantiate] [-defaultplatform] [-[non]relocatable] 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(
appName));
appName)) << std::endl;
}
int main(int argc, char *argv[])
@ -726,14 +760,14 @@ int main(int argc, char *argv[])
|| arg == QLatin1String("-defaultplatform")) {
continue;
} else {
qWarning() << "Invalid argument: " << arg;
std::cerr << "Invalid argument: " << qPrintable(arg) << std::endl;
return EXIT_INVALIDARGUMENTS;
}
}
if (action == Uri) {
if (positionalArgs.size() != 3 && positionalArgs.size() != 4) {
qWarning() << "Incorrect number of positional arguments";
std::cerr << "Incorrect number of positional arguments" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
pluginImportUri = positionalArgs[1];
@ -742,7 +776,7 @@ int main(int argc, char *argv[])
pluginImportPath = positionalArgs[3];
} else if (action == Path) {
if (positionalArgs.size() != 2 && positionalArgs.size() != 3) {
qWarning() << "Incorrect number of positional arguments";
std::cerr << "Incorrect number of positional arguments" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
pluginImportPath = QDir::fromNativeSeparators(positionalArgs[1]);
@ -750,7 +784,7 @@ int main(int argc, char *argv[])
pluginImportVersion = positionalArgs[2];
} else if (action == Builtins) {
if (positionalArgs.size() != 1) {
qWarning() << "Incorrect number of positional arguments";
std::cerr << "Incorrect number of positional arguments" << std::endl;
return EXIT_INVALIDARGUMENTS;
}
}
@ -760,7 +794,7 @@ int main(int argc, char *argv[])
if (!pluginImportPath.isEmpty()) {
QDir cur = QDir::current();
cur.cd(pluginImportPath);
pluginImportPath = cur.absolutePath();
pluginImportPath = cur.canonicalPath();
QDir::setCurrent(pluginImportPath);
engine.addImportPath(pluginImportPath);
}
@ -773,13 +807,15 @@ int main(int argc, char *argv[])
c.create();
if (!c.errors().isEmpty()) {
foreach (const QQmlError &error, c.errors())
qWarning() << error.toString();
std::cerr << qPrintable( error.toString() ) << std::endl;
return EXIT_IMPORTERROR;
}
}
// find all QMetaObjects reachable from the builtin module
QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(&engine);
QSet<const QMetaObject *> uncreatableMetas;
QSet<const QMetaObject *> singletonMetas;
QSet<const QMetaObject *> defaultReachable = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas);
QList<QQmlType *> defaultTypes = QQmlMetaType::qmlTypes();
// add some otherwise unreachable QMetaObjects
@ -797,7 +833,7 @@ int main(int argc, char *argv[])
QByteArray importCode;
QQmlType *qtObjectType = QQmlMetaType::qmlType(&QObject::staticMetaObject);
if (!qtObjectType) {
qWarning() << "Could not find QtObject type";
std::cerr << "Could not find QtObject type" << std::endl;
importCode = QByteArray("import QtQuick 2.0\n");
} else {
QString module = qtObjectType->qmlTypeName();
@ -826,12 +862,12 @@ int main(int argc, char *argv[])
c.create();
if (!c.errors().isEmpty()) {
foreach (const QQmlError &error, c.errors())
qWarning() << error.toString();
std::cerr << qPrintable( error.toString() ) << std::endl;
return EXIT_IMPORTERROR;
}
}
QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, defaultTypes);
QSet<const QMetaObject *> candidates = collectReachableMetaObjects(&engine, uncreatableMetas, singletonMetas, defaultTypes);
candidates.subtract(defaultReachable);
// Also eliminate meta objects with the same classname.
@ -873,7 +909,7 @@ int main(int argc, char *argv[])
if (relocatable)
dumper.setRelocatableModuleUri(pluginImportUri);
foreach (const QMetaObject *meta, nameToMeta) {
dumper.dump(meta);
dumper.dump(meta, uncreatableMetas.contains(meta), singletonMetas.contains(meta));
}
foreach (const QQmlType *compositeType, qmlTypesByCompositeName)
dumper.dumpComposite(&engine, compositeType, defaultReachableNames);

View File

@ -183,6 +183,16 @@ void QmlStreamWriter::writePotentialLine(const QByteArray &line)
}
}
void QmlStreamWriter::writeIsCreatable(bool isCreatable) {
writeIndent();
m_stream->write(QString("isCreatable: %1\n").arg(isCreatable ? "true" : "false").toUtf8());
}
void QmlStreamWriter::writeIsSingleton(bool isSingleton) {
writeIndent();
m_stream->write(QString("isSingleton: %1\n").arg(isSingleton ? "true" : "false").toUtf8());
}
void QmlStreamWriter::flushPotentialLinesWithNewlines()
{
if (m_maybeOneline)

View File

@ -63,6 +63,8 @@ public:
void writeScriptObjectLiteralBinding(const QString &name, const QList<QPair<QString, QString> > &keyValue);
void writeArrayBinding(const QString &name, const QStringList &elements);
void write(const QString &data);
void writeIsCreatable(bool isCreatable);
void writeIsSingleton(bool isSingleton);
private:
void writeIndent();