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:
commit
22041acdfe
|
@ -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.
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -50,7 +50,9 @@
|
|||
# define alloca _alloca
|
||||
# endif
|
||||
#else
|
||||
#if !defined(__FreeBSD__) && !defined(__DragonFly__)
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,9 @@ struct Scope {
|
|||
|
||||
explicit Scope(ExecutionEngine *e)
|
||||
: engine(e)
|
||||
#ifndef QT_NO_DEBUG
|
||||
, size(0)
|
||||
#endif
|
||||
{
|
||||
mark = engine->jsStackTop;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -2309,6 +2309,7 @@ void QQuickFlickable::timelineCompleted()
|
|||
return;
|
||||
}
|
||||
movementEnding();
|
||||
d->updateBeginningEnd();
|
||||
}
|
||||
|
||||
void QQuickFlickable::movementStarting()
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -343,6 +343,8 @@ void QQuickWindowPrivate::syncSceneGraph()
|
|||
if (clearBeforeRendering)
|
||||
mode |= QSGRenderer::ClearColorBuffer;
|
||||
renderer->setClearMode(mode);
|
||||
|
||||
context->endSync();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 = ±
|
||||
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 = ±
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import QtQuick 2.0
|
||||
|
||||
Rectangle {
|
||||
width: 400
|
||||
height: 400
|
||||
|
||||
onWidthChanged: console.log(width);
|
||||
Component.onCompleted: width = 500;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue