aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/qml/common/qv4compileddata_p.h30
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp59
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h13
-rw-r--r--src/qml/parser/qqmljs.g95
-rw-r--r--src/qml/parser/qqmljsast.cpp8
-rw-r--r--src/qml/parser/qqmljsast_p.h25
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h1
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h3
-rw-r--r--src/qml/parser/qqmljslexer.cpp2
-rw-r--r--src/qml/qml/qqmlincubator_p.h4
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp42
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h2
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp13
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h1
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp51
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp84
-rw-r--r--src/quick/handlers/qquickpointerhandler_p.h13
-rw-r--r--src/quick/handlers/qquickpointerhandler_p_p.h2
-rw-r--r--src/quick/items/qquickevents.cpp2
-rw-r--r--src/quick/items/qquickimagebase.cpp20
-rw-r--r--src/quick/items/qquickimagebase_p.h6
-rw-r--r--src/quick/items/qquickimagebase_p_p.h1
-rw-r--r--src/quick/items/qquickitem.cpp78
-rw-r--r--src/quick/items/qquickitem_p.h5
-rw-r--r--src/quick/items/qquickwindow.cpp37
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--src/quick/util/qquickbehavior.cpp76
-rw-r--r--src/quick/util/qquickbehavior_p.h4
-rw-r--r--src/quick/util/qquickglobal.cpp60
-rw-r--r--src/quick/util/qquickimageprovider.cpp18
-rw-r--r--src/quick/util/qquickpixmapcache.cpp14
-rw-r--r--src/quick/util/qquickpixmapcache_p.h5
-rw-r--r--src/quick/util/qquickvaluetypes.cpp42
-rw-r--r--src/quick/util/qquickvaluetypes_p.h52
34 files changed, 821 insertions, 50 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index b9841a76b4..7d6ef14854 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE
// Also change the comment behind the number to describe the latest change. This has the added
// benefit that if another patch changes the version too, it will result in a merge conflict, and
// not get removed silently.
-#define QV4_DATA_STRUCTURE_VERSION 0x29 // Change version format
+#define QV4_DATA_STRUCTURE_VERSION 0x30// support additional required property features
class QIODevice;
class QQmlTypeNameCache;
@@ -672,6 +672,12 @@ struct Property
};
static_assert(sizeof(Property) == 12, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+struct RequiredPropertyExtraData {
+ quint32_le nameIndex;
+};
+
+static_assert (sizeof(RequiredPropertyExtraData) == 4, "RequiredPropertyExtraData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+
struct Alias {
enum Flags : unsigned int {
IsReadOnly = 0x1,
@@ -742,13 +748,16 @@ struct Object
Location locationOfIdProperty;
quint32_le offsetToInlineComponents;
quint16_le nInlineComponents;
+ quint32_le offsetToRequiredPropertyExtraData;
+ quint16_le nRequiredPropertyExtraData;
// Function[]
// Property[]
// Signal[]
// Binding[]
// InlineComponent[]
+// RequiredPropertyExtraData[]
- static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents)
+ static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
{
return ( sizeof(Object)
+ nFunctions * sizeof(quint32)
@@ -759,6 +768,7 @@ struct Object
+ nBindings * sizeof(Binding)
+ nNamedObjectsInComponent * sizeof(int)
+ nInlineComponents * sizeof(InlineComponent)
+ + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
+ 0x7
) & ~0x7;
}
@@ -812,6 +822,16 @@ struct Object
return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
}
+ const RequiredPropertyExtraData *requiredPropertyExtraDataAt(int idx) const
+ {
+ return requiredPropertyExtraDataTable() + idx;
+ }
+
+ const RequiredPropertyExtraData *requiredPropertyExtraDataTable() const
+ {
+ return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
+ }
+
// --- QQmlPropertyCacheCreator interface
int propertyCount() const { return nProperties; }
int aliasCount() const { return nAliases; }
@@ -840,10 +860,14 @@ struct Object
InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
+ typedef TableIterator<RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt> RequiredPropertyExtraDataIterator;
+ RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); };
+ RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); };
+
int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
// ---
};
-static_assert(sizeof(Object) == 76, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Object) == 84, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Import
{
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index be02a08f82..4de7734ecf 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -64,6 +64,33 @@ using namespace QQmlJS;
return false; \
}
+void Object::simplifyRequiredProperties() {
+ // if a property of the current object was marked as required
+ // do not store that information in the ExtraData
+ // but rather mark the property as required
+ QSet<int> required;
+ for (auto it = this->requiredPropertyExtraDataBegin(); it != this->requiredPropertyExtraDataEnd(); ++it)
+ required.insert(it->nameIndex);
+ if (required.isEmpty())
+ return;
+ for (auto it = this->propertiesBegin(); it != this->propertiesEnd(); ++it) {
+ auto requiredIt = required.find(it->nameIndex);
+ if (requiredIt != required.end()) {
+ it->isRequired = true;
+ required.erase(requiredIt);
+ }
+ }
+ QmlIR::RequiredPropertyExtraData *prev = nullptr;
+ auto current = this->requiredPropertyExtraDatas->first;
+ while (current) {
+ if (required.contains(current->nameIndex))
+ prev = current;
+ else
+ requiredPropertyExtraDatas->unlink(prev, current);
+ current = current->next;
+ }
+}
+
bool Parameter::init(QV4::Compiler::JSUnitGenerator *stringGenerator, const QString &parameterName,
const QString &typeName)
{
@@ -162,6 +189,7 @@ void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, cons
functions = pool->New<PoolList<Function> >();
functionsAndExpressions = pool->New<PoolList<CompiledFunctionOrExpression> >();
inlineComponents = pool->New<PoolList<InlineComponent>>();
+ requiredPropertyExtraDatas = pool->New<PoolList<RequiredPropertyExtraData>>();
declarationsOverride = nullptr;
}
@@ -287,6 +315,11 @@ void Object::appendInlineComponent(InlineComponent *ic)
inlineComponents->append(ic);
}
+void Object::appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraData)
+{
+ requiredPropertyExtraDatas->append(extraData);
+}
+
QString Object::appendBinding(Binding *b, bool isListBinding)
{
const bool bindingToDefaultProperty = (b->propertyNameIndex == quint32(0));
@@ -448,6 +481,10 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen
qSwap(_imports, output->imports);
qSwap(_pragmas, output->pragmas);
qSwap(_objects, output->objects);
+
+ for (auto object: output->objects)
+ object->simplifyRequiredProperties();
+
return errors.isEmpty();
}
@@ -982,6 +1019,14 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node)
return false;
}
+bool IRBuilder::visit(AST::UiRequired *ast)
+{
+ auto extraData = New<RequiredPropertyExtraData>();
+ extraData->nameIndex = registerString(ast->name.toString());
+ _object->appendRequiredPropertyExtraData(extraData);
+ return false;
+}
+
QString IRBuilder::asString(QQmlJS::AST::UiQualifiedId *node)
{
QString s;
@@ -1577,7 +1622,7 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
uint nextOffset = objectOffset + objectOffsetTableSize;
for (Object *o : qAsConst(output.objects)) {
objectOffsets.insert(o, nextOffset);
- nextOffset += QV4::CompiledData::Object::calculateSizeExcludingSignalsAndEnums(o->functionCount(), o->propertyCount(), o->aliasCount(), o->enumCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.size(), o->inlineComponentCount());
+ nextOffset += QV4::CompiledData::Object::calculateSizeExcludingSignalsAndEnums(o->functionCount(), o->propertyCount(), o->aliasCount(), o->enumCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.size(), o->inlineComponentCount(), o->requiredPropertyExtraDataCount());
int signalTableSize = 0;
for (const Signal *s = o->firstSignal(); s; s = s->next)
@@ -1660,6 +1705,10 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
objectToWrite->offsetToInlineComponents = nextOffset;
nextOffset += objectToWrite->nInlineComponents * sizeof (QV4::CompiledData::InlineComponent);
+ objectToWrite->nRequiredPropertyExtraData = o->requiredPropertyExtraDataCount();
+ objectToWrite->offsetToRequiredPropertyExtraData = nextOffset;
+ nextOffset += objectToWrite->nRequiredPropertyExtraData * sizeof(QV4::CompiledData::RequiredPropertyExtraData);
+
quint32_le *functionsTable = reinterpret_cast<quint32_le *>(objectPtr + objectToWrite->offsetToFunctions);
for (const Function *f = o->firstFunction(); f; f = f->next)
*functionsTable++ = o->runtimeFunctionIndices.at(f->index);
@@ -1739,6 +1788,14 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
*icToWrite = *ic;
inlineComponentPtr += sizeof(QV4::CompiledData::InlineComponent);
}
+
+ char *requiredPropertyExtraDataPtr = objectPtr + objectToWrite->offsetToRequiredPropertyExtraData;
+ for (auto it = o->requiredPropertyExtraDataBegin(); it != o->requiredPropertyExtraDataEnd(); ++it) {
+ const RequiredPropertyExtraData *extraData = it.ptr;
+ QV4::CompiledData::RequiredPropertyExtraData *extraDataToWrite = reinterpret_cast<QV4::CompiledData::RequiredPropertyExtraData*>(requiredPropertyExtraDataPtr);
+ *extraDataToWrite = *extraData;
+ requiredPropertyExtraDataPtr += sizeof(QV4::CompiledData::RequiredPropertyExtraData);
+ }
}
if (!output.javaScriptCompilationUnit.data) {
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index ea27e65f86..ae74254a42 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -285,6 +285,11 @@ struct Alias : public QV4::CompiledData::Alias
Alias *next;
};
+struct RequiredPropertyExtraData : public QV4::CompiledData::RequiredPropertyExtraData
+{
+ RequiredPropertyExtraData *next;
+};
+
struct Function
{
QV4::CompiledData::Location location;
@@ -341,6 +346,9 @@ public:
int functionCount() const { return functions->count; }
const InlineComponent *inlineComponent() const { return inlineComponents->first; }
int inlineComponentCount() const { return inlineComponents->count; }
+ const RequiredPropertyExtraData *requiredPropertyExtraData() const {return requiredPropertyExtraDatas->first; }
+ int requiredPropertyExtraDataCount() const { return requiredPropertyExtraDatas->count; }
+ void simplifyRequiredProperties();
PoolList<Binding>::Iterator bindingsBegin() const { return bindings->begin(); }
PoolList<Binding>::Iterator bindingsEnd() const { return bindings->end(); }
@@ -356,6 +364,8 @@ public:
PoolList<Function>::Iterator functionsEnd() const { return functions->end(); }
PoolList<InlineComponent>::Iterator inlineComponentsBegin() const { return inlineComponents->begin(); }
PoolList<InlineComponent>::Iterator inlineComponentsEnd() const { return inlineComponents->end(); }
+ PoolList<RequiredPropertyExtraData>::Iterator requiredPropertyExtraDataBegin() const {return requiredPropertyExtraDatas->begin(); }
+ PoolList<RequiredPropertyExtraData>::Iterator requiredPropertyExtraDataEnd() const {return requiredPropertyExtraDatas->end(); }
// If set, then declarations for this object (and init bindings for these) should go into the
// specified object. Used for declarations inside group properties.
@@ -369,6 +379,7 @@ public:
QString appendAlias(Alias *prop, const QString &aliasName, bool isDefaultProperty, const QQmlJS::AST::SourceLocation &defaultToken, QQmlJS::AST::SourceLocation *errorLocation);
void appendFunction(QmlIR::Function *f);
void appendInlineComponent(InlineComponent *ic);
+ void appendRequiredPropertyExtraData(RequiredPropertyExtraData *extraData);
QString appendBinding(Binding *b, bool isListBinding);
Binding *findBinding(quint32 nameIndex) const;
@@ -393,6 +404,7 @@ private:
PoolList<Binding> *bindings;
PoolList<Function> *functions;
PoolList<InlineComponent> *inlineComponents;
+ PoolList<RequiredPropertyExtraData> *requiredPropertyExtraDatas;
};
struct Q_QMLCOMPILER_PRIVATE_EXPORT Pragma
@@ -469,6 +481,7 @@ public:
bool visit(QQmlJS::AST::UiPublicMember *ast) override;
bool visit(QQmlJS::AST::UiScriptBinding *ast) override;
bool visit(QQmlJS::AST::UiSourceElement *ast) override;
+ bool visit(QQmlJS::AST::UiRequired *ast) override;
void throwRecursionDepthError() override
{
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index 2b00caf378..879de92e5f 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -73,7 +73,7 @@
%token T_VAR "var" T_VOID "void" T_WHILE "while"
%token T_WITH "with" T_XOR "^" T_XOR_EQ "^="
%token T_NULL "null" T_TRUE "true" T_FALSE "false"
-%token T_CONST "const" T_LET "let"
+%token T_CONST "const" T_LET "let" T_AT "@"
%token T_DEBUGGER "debugger"
%token T_RESERVED_WORD "reserved word"
%token T_MULTILINE_STRING_LITERAL "multiline string literal"
@@ -739,7 +739,7 @@ TopLevel: T_FEED_JS_EXPRESSION Expression;
} break;
./
-TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember;
+TopLevel: T_FEED_UI_OBJECT_MEMBER UiAnnotatedObjectMember;
/.
case $rule_number: {
sym(1).Node = sym(2).Node;
@@ -913,21 +913,84 @@ Empty: ;
} break;
./
-UiRootMember: UiObjectDefinition;
+UiRootMember: UiAnnotatedObject;
/.
case $rule_number: {
sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
} break;
./
-UiObjectMemberList: UiObjectMember;
+UiSimpleQualifiedId: T_IDENTIFIER;
+/.
+ case $rule_number: {
+ AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1));
+ node->identifierToken = loc(1);
+ sym(1).Node = node;
+ } break;
+./
+
+UiSimpleQualifiedId: UiSimpleQualifiedId T_DOT T_IDENTIFIER;
+/.
+ case $rule_number: {
+ AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ sym(1).Node = node;
+ } break;
+./
+
+UiAnnotationObjectDefinition: UiSimpleQualifiedId UiObjectInitializer;
+/.
+ case $rule_number: {
+ if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
+ sym(1).UiQualifiedId = qualifiedId;
+ } else {
+ sym(1).UiQualifiedId = 0;
+
+ diagnostic_messages.append(compileError(loc(1),
+ QLatin1String("Expected a qualified name id")));
+
+ return false;
+ }
+ AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer);
+ sym(1).Node = node;
+ } break;
+./
+
+UiAnnotation: T_AT UiAnnotationObjectDefinition;
+
+UiAnnotationList: UiAnnotation;
+/.
+ case $rule_number: {
+ sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember);
+ } break;
+./
+
+UiAnnotationList: UiAnnotationList UiAnnotation;
+/.
+ case $rule_number: {
+ AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList(sym(1).UiArrayMemberList, sym(3).UiObjectMember);
+ sym(1).Node = node;
+ } break;
+./
+
+UiAnnotatedObject: UiAnnotationList UiObjectDefinition;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ } break;
+./
+
+UiAnnotatedObject: UiObjectDefinition;
+
+UiObjectMemberList: UiAnnotatedObjectMember;
/.
case $rule_number: {
sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
} break;
./
-UiObjectMemberList: UiObjectMemberList UiObjectMember;
+UiObjectMemberList: UiObjectMemberList UiAnnotatedObjectMember;
/.
case $rule_number: {
AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList(sym(1).UiObjectMemberList, sym(2).UiObjectMember);
@@ -979,6 +1042,15 @@ UiObjectDefinition: UiQualifiedId UiObjectInitializer;
} break;
./
+UiAnnotatedObjectMember: UiAnnotationList UiObjectMember;
+/.
+ case $rule_number: {
+ sym(1).Node = sym(2).Node;
+ } break;
+./
+
+UiAnnotatedObjectMember: UiObjectMember;
+
UiObjectMember: UiObjectDefinition;
UiObjectMember: UiQualifiedId T_COLON ExpressionStatementLookahead T_LBRACKET UiArrayMemberList T_RBRACKET;
@@ -1278,6 +1350,18 @@ OptionalSemicolon: | Semicolon;
and then we would miss a semicolon (see tests/auto/quick/qquickvisualdatamodel/data/objectlist.qml)*/
./
+UiRequired: T_REQUIRED QmlIdentifier Semicolon;
+/.
+ case $rule_number: {
+ AST::UiRequired *node = new (pool) AST::UiRequired(stringRef(2));
+ node->requiredToken = loc(1);
+ node->semicolonToken = loc(3);
+ sym(1).Node = node;
+ } break;
+./
+
+UiObjectMember: UiRequired;
+
UiObjectMember: T_REQUIRED UiObjectMemberPropertyNoInitialiser;
/.
case $rule_number: {
@@ -1288,7 +1372,6 @@ UiObjectMember: T_REQUIRED UiObjectMemberPropertyNoInitialiser;
} break;
./
-
UiObjectMemberWithScriptStatement: T_PROPERTY UiPropertyType QmlIdentifier T_COLON UiScriptStatement OptionalSemicolon;
/.
case $rule_number: {
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index aa3e8ab5e3..416916c547 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -1554,6 +1554,14 @@ void UiInlineComponent::accept0(Visitor *visitor)
visitor->endVisit(this);
}
+void UiRequired::accept0(Visitor *visitor)
+{
+ if (visitor->visit(this)) {
+ }
+
+ visitor->endVisit(this);
+}
+
} } // namespace QQmlJS::AST
QT_END_NAMESPACE
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index a7c95eee2d..446704be91 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -259,7 +259,8 @@ public:
Kind_UiHeaderItemList,
Kind_UiEnumDeclaration,
Kind_UiEnumMemberList,
- Kind_UiVersionSpecifier
+ Kind_UiVersionSpecifier,
+ Kind_UiRequired
};
inline Node() {}
@@ -3106,6 +3107,28 @@ public:
SourceLocation semicolonToken;
};
+class QML_PARSER_EXPORT UiRequired: public Node
+{
+public:
+ QQMLJS_DECLARE_AST_NODE(UiRequired)
+
+ UiRequired(QStringRef name)
+ :name(name)
+ { kind = K; }
+
+ void accept0(Visitor *visitor) override;
+
+ SourceLocation firstSourceLocation() const override
+ { return requiredToken; }
+
+ SourceLocation lastSourceLocation() const override
+ { return semicolonToken; }
+
+ QStringRef name;
+ SourceLocation requiredToken;
+ SourceLocation semicolonToken;
+};
+
class QML_PARSER_EXPORT UiHeaderItemList: public Node
{
public:
diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h
index 8a8ee2dfae..fe260e2bb5 100644
--- a/src/qml/parser/qqmljsastfwd_p.h
+++ b/src/qml/parser/qqmljsastfwd_p.h
@@ -183,6 +183,7 @@ class UiHeaderItemList;
class UiEnumDeclaration;
class UiEnumMemberList;
class UiVersionSpecifier;
+class UiRequired;
} // namespace AST
} // namespace QQmlJS
diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h
index d6b92990ad..fcc48da1d3 100644
--- a/src/qml/parser/qqmljsastvisitor_p.h
+++ b/src/qml/parser/qqmljsastvisitor_p.h
@@ -414,6 +414,9 @@ public:
virtual bool visit(TypeAnnotation *) { return true; }
virtual void endVisit(TypeAnnotation *) {}
+ virtual bool visit(UiRequired *) { return true; }
+ virtual void endVisit(UiRequired *) {}
+
virtual void throwRecursionDepthError() = 0;
quint16 recursionDepth() const { return m_recursionDepth; }
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 80d883e52f..0c61679f0b 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -719,6 +719,8 @@ again:
case ')': return T_RPAREN;
case '(': return T_LPAREN;
+ case '@': return T_AT;
+
case '&':
if (_char == QLatin1Char('=')) {
scanChar();
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index aadb147bd5..a674ff274f 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -61,9 +61,7 @@
QT_BEGIN_NAMESPACE
-class QQmlPropertyData;
-struct RequiredPropertyInfo;
-using RequiredProperties = QHash<QQmlPropertyData*, RequiredPropertyInfo>;
+class RequiredProperties;
class QQmlIncubator;
class Q_QML_PRIVATE_EXPORT QQmlIncubatorPrivate : public QQmlEnginePrivate::Incubator
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index a26cdba53a..6cc2bf49c8 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -1505,23 +1505,45 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings)
_ddata->deferData(_compiledObjectIndex, compilationUnit, context);
+ QSet<QString> postHocRequired;
+ for (auto it = _compiledObject->requiredPropertyExtraDataBegin(); it != _compiledObject->requiredPropertyExtraDataEnd(); ++it)
+ postHocRequired.insert(stringAt(it->nameIndex));
+ bool hadInheritedRequiredProperties = !postHocRequired.empty();
+
for (int propertyIndex = 0; propertyIndex != _compiledObject->propertyCount(); ++propertyIndex) {
const QV4::CompiledData::Property* property = _compiledObject->propertiesBegin() + propertyIndex;
QQmlPropertyData *propertyData = _propertyCache->property(_propertyCache->propertyOffset() + propertyIndex);
- if (property->isRequired) {
- sharedState->hadRequiredProperties = true;
- sharedState->requiredProperties.insert(propertyData,
- RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}});
- }
+ // only compute stringAt if there's a chance for the lookup to succeed
+ auto postHocIt = postHocRequired.isEmpty() ? postHocRequired.end() : postHocRequired.find(stringAt(property->nameIndex));
+ if (!property->isRequired && postHocRequired.end() == postHocIt)
+ continue;
+ if (postHocIt != postHocRequired.end())
+ postHocRequired.erase(postHocIt);
+ sharedState->hadRequiredProperties = true;
+ sharedState->requiredProperties.insert(propertyData,
+ RequiredPropertyInfo {compilationUnit->stringAt(property->nameIndex), compilationUnit->finalUrl(), property->location, {}});
+
}
for (int i = 0; i <= _propertyCache->propertyOffset(); ++i) {
- QQmlPropertyData *propertyData = _propertyCache->property(i);
- if (propertyData && propertyData->isRequired()) {
- sharedState->hadRequiredProperties = true;
- sharedState->requiredProperties.insert(propertyData, RequiredPropertyInfo {propertyData->name(_qobject), compilationUnit->finalUrl(), _compiledObject->location, {}});
- }
+ QQmlPropertyData *propertyData = _propertyCache->maybeUnresolvedProperty(i);
+ if (!propertyData)
+ continue;
+ if (!propertyData->isRequired() && postHocRequired.isEmpty())
+ continue;
+ QString name = propertyData->name(_qobject);
+ auto postHocIt = postHocRequired.find(name);
+ if (!propertyData->isRequired() && postHocRequired.end() == postHocIt )
+ continue;
+
+ if (postHocIt != postHocRequired.end())
+ postHocRequired.erase(postHocIt);
+
+ sharedState->hadRequiredProperties = true;
+ sharedState->requiredProperties.insert(propertyData, RequiredPropertyInfo {name, compilationUnit->finalUrl(), _compiledObject->location, {}});
}
+ if (!postHocRequired.isEmpty() && hadInheritedRequiredProperties)
+ recordError({}, QLatin1String("Property %1 was marked as required but does not exist").arg(*postHocRequired.begin()));
if (_compiledObject->nFunctions > 0)
setupFunctions();
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index f8ad90be15..bca450addb 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -86,7 +86,7 @@ struct RequiredPropertyInfo
QVector<AliasToRequiredInfo> aliasesToRequired;
};
-using RequiredProperties = QHash<QQmlPropertyData*, RequiredPropertyInfo>;
+class RequiredProperties : public QHash<QQmlPropertyData*, RequiredPropertyInfo> {};
struct QQmlObjectCreatorSharedState : public QSharedData
{
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 8d91fa29e4..540e6afda1 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -400,6 +400,19 @@ const QMetaObject *QQmlPropertyCache::createMetaObject()
return _metaObject;
}
+QQmlPropertyData *QQmlPropertyCache::maybeUnresolvedProperty(int index) const
+{
+ if (index < 0 || index >= (propertyIndexCacheStart + propertyIndexCache.count()))
+ return nullptr;
+
+ QQmlPropertyData *rv = nullptr;
+ if (index < propertyIndexCacheStart)
+ return _parent->maybeUnresolvedProperty(index);
+ else
+ rv = const_cast<QQmlPropertyData *>(&propertyIndexCache.at(index - propertyIndexCacheStart));
+ return rv;
+}
+
QQmlPropertyData *QQmlPropertyCache::defaultProperty() const
{
return property(defaultPropertyName(), nullptr, nullptr);
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 9c576aab39..9e6eaf9778 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -120,6 +120,7 @@ public:
}
QQmlPropertyData *property(int) const;
+ QQmlPropertyData *maybeUnresolvedProperty(int) const;
QQmlPropertyData *method(int) const;
QQmlPropertyData *signal(int index) const;
QQmlEnumData *qmlEnum(int) const;
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index 79cb288af8..1216eda477 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -64,6 +64,9 @@ Q_LOGGING_CATEGORY(lcHoverHandler, "qt.quick.handler.hover")
properties can be used to narrow the behavior to detect hovering of
specific kinds of devices or while holding a modifier key.
+ The \l cursorShape property allows changing the cursor whenever
+ \l hovered changes to \c true.
+
\sa MouseArea, PointHandler
*/
@@ -125,4 +128,52 @@ void QQuickHoverHandler::setHovered(bool hovered)
}
}
+/*!
+ \since 5.15
+ \qmlproperty Qt::CursorShape QtQuick::HoverHandler::cursorShape
+ This property holds the cursor shape that will appear whenever
+ \l hovered is \c true and no other handler is overriding it.
+
+ The available cursor shapes are:
+ \list
+ \li Qt.ArrowCursor
+ \li Qt.UpArrowCursor
+ \li Qt.CrossCursor
+ \li Qt.WaitCursor
+ \li Qt.IBeamCursor
+ \li Qt.SizeVerCursor
+ \li Qt.SizeHorCursor
+ \li Qt.SizeBDiagCursor
+ \li Qt.SizeFDiagCursor
+ \li Qt.SizeAllCursor
+ \li Qt.BlankCursor
+ \li Qt.SplitVCursor
+ \li Qt.SplitHCursor
+ \li Qt.PointingHandCursor
+ \li Qt.ForbiddenCursor
+ \li Qt.WhatsThisCursor
+ \li Qt.BusyCursor
+ \li Qt.OpenHandCursor
+ \li Qt.ClosedHandCursor
+ \li Qt.DragCopyCursor
+ \li Qt.DragMoveCursor
+ \li Qt.DragLinkCursor
+ \endlist
+
+ The default value of this property is not set, which allows any active
+ handler on the same \l parentItem to determine the cursor shape.
+ This property can be reset to the initial condition by setting it to
+ \c undefined.
+
+ If any handler with defined \c cursorShape is
+ \l {PointerHandler::active}{active}, that cursor will appear.
+ Else if the HoverHandler has a defined \c cursorShape, that cursor will appear.
+ Otherwise, the \l {QQuickItem::cursor()}{cursor} of \l parentItem will appear.
+
+ \note When this property has not been set, or has been set to \c undefined,
+ if you read the value it will return \c Qt.ArrowCursor.
+
+ \sa Qt::CursorShape, QQuickItem::cursor()
+*/
+
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index c498c96454..adb753e000 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -51,7 +51,6 @@ Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active")
\qmltype PointerHandler
\qmlabstract
\since 5.10
- \preliminary
\instantiates QQuickPointerHandler
\inqmlmodule QtQuick
\brief Abstract handler for pointer events.
@@ -154,6 +153,87 @@ void QQuickPointerHandler::resetDragThreshold()
}
/*!
+ \since 5.15
+ \qmlproperty Qt::CursorShape PointerHandler::cursorShape
+ This property holds the cursor shape that will appear whenever the mouse is
+ hovering over the \l parentItem while \l active is \c true.
+
+ The available cursor shapes are:
+ \list
+ \li Qt.ArrowCursor
+ \li Qt.UpArrowCursor
+ \li Qt.CrossCursor
+ \li Qt.WaitCursor
+ \li Qt.IBeamCursor
+ \li Qt.SizeVerCursor
+ \li Qt.SizeHorCursor
+ \li Qt.SizeBDiagCursor
+ \li Qt.SizeFDiagCursor
+ \li Qt.SizeAllCursor
+ \li Qt.BlankCursor
+ \li Qt.SplitVCursor
+ \li Qt.SplitHCursor
+ \li Qt.PointingHandCursor
+ \li Qt.ForbiddenCursor
+ \li Qt.WhatsThisCursor
+ \li Qt.BusyCursor
+ \li Qt.OpenHandCursor
+ \li Qt.ClosedHandCursor
+ \li Qt.DragCopyCursor
+ \li Qt.DragMoveCursor
+ \li Qt.DragLinkCursor
+ \endlist
+
+ The default value is not set, which allows the \l {QQuickItem::cursor()}{cursor}
+ of \l parentItem to appear. This property can be reset to the same initial
+ condition by setting it to undefined.
+
+ \note When this property has not been set, or has been set to \c undefined,
+ if you read the value it will return \c Qt.ArrowCursor.
+
+ \sa Qt::CursorShape, QQuickItem::cursor(), HoverHandler::cursorShape
+*/
+#if QT_CONFIG(cursor)
+Qt::CursorShape QQuickPointerHandler::cursorShape() const
+{
+ Q_D(const QQuickPointerHandler);
+ return d->cursorShape;
+}
+
+void QQuickPointerHandler::setCursorShape(Qt::CursorShape shape)
+{
+ Q_D(QQuickPointerHandler);
+ if (d->cursorSet && shape == d->cursorShape)
+ return;
+ d->cursorShape = shape;
+ d->cursorSet = true;
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parentItem());
+ itemPriv->hasCursorHandler = true;
+ itemPriv->setHasCursorInChild(true);
+ emit cursorShapeChanged();
+}
+
+void QQuickPointerHandler::resetCursorShape()
+{
+ Q_D(QQuickPointerHandler);
+ if (!d->cursorSet)
+ return;
+ d->cursorShape = Qt::ArrowCursor;
+ d->cursorSet = false;
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parentItem());
+ itemPriv->hasCursorHandler = false;
+ itemPriv->setHasCursorInChild(itemPriv->hasCursor);
+ emit cursorShapeChanged();
+}
+
+bool QQuickPointerHandler::isCursorShapeExplicitlySet() const
+{
+ Q_D(const QQuickPointerHandler);
+ return d->cursorSet;
+}
+#endif
+
+/*!
Notification that the grab has changed in some way which is relevant to this handler.
The \a grabber (subject) will be the Input Handler whose state is changing,
or null if the state change regards an Item.
@@ -597,11 +677,13 @@ QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
: grabPermissions(QQuickPointerHandler::CanTakeOverFromItems |
QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType |
QQuickPointerHandler::ApprovesTakeOverByAnything)
+ , cursorShape(Qt::ArrowCursor)
, enabled(true)
, active(false)
, targetExplicitlySet(false)
, hadKeepMouseGrab(false)
, hadKeepTouchGrab(false)
+ , cursorSet(false)
{
}
diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h
index 34ae9ce2c2..7262f4bcd3 100644
--- a/src/quick/handlers/qquickpointerhandler_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p.h
@@ -72,6 +72,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandler : public QObject, public QQmlP
Q_PROPERTY(GrabPermissions grabPermissions READ grabPermissions WRITE setGrabPermissions NOTIFY grabPermissionChanged)
Q_PROPERTY(qreal margin READ margin WRITE setMargin NOTIFY marginChanged)
Q_PROPERTY(int dragThreshold READ dragThreshold WRITE setDragThreshold RESET resetDragThreshold NOTIFY dragThresholdChanged REVISION 15)
+#if QT_CONFIG(cursor)
+ Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape RESET resetCursorShape NOTIFY cursorShapeChanged REVISION 15)
+#endif
QML_NAMED_ELEMENT(PointerHandler)
QML_UNCREATABLE("PointerHandler is an abstract base class.")
@@ -119,6 +122,13 @@ public:
void setDragThreshold(int t);
void resetDragThreshold();
+#if QT_CONFIG(cursor)
+ Qt::CursorShape cursorShape() const;
+ void setCursorShape(Qt::CursorShape shape);
+ void resetCursorShape();
+ bool isCursorShapeExplicitlySet() const;
+#endif
+
Q_SIGNALS:
void enabledChanged();
void activeChanged();
@@ -128,6 +138,9 @@ Q_SIGNALS:
void grabChanged(QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point);
void grabPermissionChanged();
void canceled(QQuickEventPoint *point);
+#if QT_CONFIG(cursor)
+ Q_REVISION(15) void cursorShapeChanged();
+#endif
protected:
QQuickPointerHandler(QQuickPointerHandlerPrivate &dd, QQuickItem *parent);
diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h
index 5727b1ef55..db053fb6b4 100644
--- a/src/quick/handlers/qquickpointerhandler_p_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p_p.h
@@ -79,11 +79,13 @@ public:
qreal m_margin = 0;
qint16 dragThreshold = -1; // -1 means use the platform default
uint8_t grabPermissions : 8;
+ Qt::CursorShape cursorShape : 6;
bool enabled : 1;
bool active : 1;
bool targetExplicitlySet : 1;
bool hadKeepMouseGrab : 1; // some handlers override target()->setKeepMouseGrab(); this remembers previous state
bool hadKeepTouchGrab : 1; // some handlers override target()->setKeepTouchGrab(); this remembers previous state
+ bool cursorSet : 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 03280e4c1f..469dc3cb4d 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -1626,6 +1626,8 @@ bool QQuickSinglePointEvent::allPointsGrabbed() const
QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const
{
+ if (!m_event)
+ return nullptr;
auto event = static_cast<QMouseEvent *>(m_event);
event->setLocalPos(localPos);
return event;
diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp
index 2118f67387..8849c2005c 100644
--- a/src/quick/items/qquickimagebase.cpp
+++ b/src/quick/items/qquickimagebase.cpp
@@ -396,6 +396,10 @@ void QQuickImageBase::requestFinished()
d->frameCount = d->pix.frameCount();
emit frameCountChanged();
}
+ if (d->colorSpace != d->pix.colorSpace()) {
+ d->colorSpace = d->pix.colorSpace();
+ emit colorSpaceChanged();
+ }
update();
}
@@ -488,6 +492,22 @@ void QQuickImageBase::setAutoTransform(bool transform)
emitAutoTransformBaseChanged();
}
+QColorSpace QQuickImageBase::colorSpace() const
+{
+ Q_D(const QQuickImageBase);
+ return d->colorSpace;
+}
+
+void QQuickImageBase::setColorSpace(const QColorSpace &colorSpace)
+{
+ Q_D(QQuickImageBase);
+ if (d->colorSpace == colorSpace)
+ return;
+ d->colorSpace = colorSpace;
+ d->providerOptions.setTargetColorSpace(colorSpace);
+ emit colorSpaceChanged();
+}
+
QT_END_NAMESPACE
#include "moc_qquickimagebase_p.cpp"
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 238b31b2e5..095547a2cf 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -53,6 +53,7 @@
#include "qquickimplicitsizeitem_p.h"
#include <private/qtquickglobal_p.h>
+#include <QtGui/qcolorspace.h>
QT_BEGIN_NAMESPACE
@@ -70,6 +71,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickImageBase : public QQuickImplicitSizeItem
Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged)
Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged REVISION 14)
Q_PROPERTY(int frameCount READ frameCount NOTIFY frameCountChanged REVISION 14)
+ Q_PROPERTY(QColorSpace colorSpace READ colorSpace WRITE setColorSpace NOTIFY colorSpaceChanged REVISION 15)
QML_NAMED_ELEMENT(ImageBase);
QML_ADDED_IN_MINOR_VERSION(14)
@@ -122,6 +124,9 @@ public:
virtual void setAutoTransform(bool transform);
bool autoTransform() const;
+ QColorSpace colorSpace() const;
+ virtual void setColorSpace(const QColorSpace &colorSpace);
+
static void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio);
// Use a virtual rather than a signal->signal to avoid the huge
@@ -139,6 +144,7 @@ Q_SIGNALS:
Q_REVISION(14) void currentFrameChanged();
Q_REVISION(14) void frameCountChanged();
Q_REVISION(15) void sourceClipRectChanged();
+ Q_REVISION(15) void colorSpaceChanged();
protected:
void loadEmptyUrl();
diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h
index 00a9295ef0..ebb7568caf 100644
--- a/src/quick/items/qquickimagebase_p_p.h
+++ b/src/quick/items/qquickimagebase_p_p.h
@@ -88,6 +88,7 @@ public:
qreal devicePixelRatio;
QRectF sourceClipRect;
QQuickImageProviderOptions providerOptions;
+ QColorSpace colorSpace;
int currentFrame;
int frameCount;
bool async : 1;
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 03cdeb5bef..fe8df6fb64 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -3244,6 +3244,7 @@ QQuickItemPrivate::QQuickItemPrivate()
#else
, touchEnabled(false)
#endif
+ , hasCursorHandler(false)
, dirtyAttributes(0)
, nextDirtyItem(nullptr)
, prevDirtyItem(nullptr)
@@ -7472,14 +7473,14 @@ void QQuickItem::setAcceptTouchEvents(bool enabled)
d->touchEnabled = enabled;
}
-void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
+void QQuickItemPrivate::setHasCursorInChild(bool hc)
{
#if QT_CONFIG(cursor)
Q_Q(QQuickItem);
// if we're asked to turn it off (because of an unsetcursor call, or a node
// removal) then we should make sure it's really ok to turn it off.
- if (!hasCursor && subtreeCursorEnabled) {
+ if (!hc && subtreeCursorEnabled) {
if (hasCursor)
return; // nope! sorry, I have a cursor myself
for (QQuickItem *otherChild : qAsConst(childItems)) {
@@ -7489,14 +7490,14 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
}
}
- subtreeCursorEnabled = hasCursor;
+ subtreeCursorEnabled = hc;
QQuickItem *parent = q->parentItem();
if (parent) {
QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
- parentPrivate->setHasCursorInChild(hasCursor);
+ parentPrivate->setHasCursorInChild(hc);
}
#else
- Q_UNUSED(hasCursor);
+ Q_UNUSED(hc);
#endif
}
@@ -7573,17 +7574,20 @@ void QQuickItem::setCursor(const QCursor &cursor)
}
}
+ QPointF updateCursorPos;
if (!d->hasCursor) {
- d->setHasCursorInChild(true);
d->hasCursor = true;
if (d->window) {
QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window);
QWindow *window = renderWindow ? renderWindow : d->window;
QPointF pos = window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint());
if (contains(mapFromScene(pos)))
- QQuickWindowPrivate::get(d->window)->updateCursor(pos);
+ updateCursorPos = pos;
}
}
+ d->setHasCursorInChild(d->hasCursor || d->hasCursorHandler);
+ if (!updateCursorPos.isNull())
+ QQuickWindowPrivate::get(d->window)->updateCursor(updateCursorPos);
}
/*!
@@ -7597,8 +7601,8 @@ void QQuickItem::unsetCursor()
Q_D(QQuickItem);
if (!d->hasCursor)
return;
- d->setHasCursorInChild(false);
d->hasCursor = false;
+ d->setHasCursorInChild(d->hasCursorHandler);
if (d->extra.isAllocated())
d->extra->cursor = QCursor();
@@ -7611,6 +7615,64 @@ void QQuickItem::unsetCursor()
}
}
+/*!
+ \internal
+ Returns the cursor that should actually be shown, allowing the given
+ \handler to override the Item cursor if it is active or hovered.
+
+ \sa cursor(), setCursor(), QtQuick::PointerHandler::cursor
+*/
+QCursor QQuickItemPrivate::effectiveCursor(const QQuickPointerHandler *handler) const
+{
+ Q_Q(const QQuickItem);
+ if (!handler)
+ return q->cursor();
+ bool hoverCursorSet = false;
+ QCursor hoverCursor;
+ bool activeCursorSet = false;
+ QCursor activeCursor;
+ if (const QQuickHoverHandler *hoverHandler = qobject_cast<const QQuickHoverHandler *>(handler)) {
+ hoverCursorSet = hoverHandler->isCursorShapeExplicitlySet();
+ hoverCursor = hoverHandler->cursorShape();
+ } else if (handler->active()) {
+ activeCursorSet = handler->isCursorShapeExplicitlySet();
+ activeCursor = handler->cursorShape();
+ }
+ if (activeCursorSet)
+ return activeCursor;
+ if (hoverCursorSet)
+ return hoverCursor;
+ return q->cursor();
+}
+
+/*!
+ \internal
+ Returns the Pointer Handler that is currently attempting to set the cursor shape,
+ or null if there is no such handler.
+
+ \sa QtQuick::PointerHandler::cursor
+*/
+QQuickPointerHandler *QQuickItemPrivate::effectiveCursorHandler() const
+{
+ if (!hasPointerHandlers())
+ return nullptr;
+ QQuickPointerHandler *retHoverHandler = nullptr;
+ for (QQuickPointerHandler *h : extra->pointerHandlers) {
+ if (!h->isCursorShapeExplicitlySet())
+ continue;
+ QQuickHoverHandler *hoverHandler = qmlobject_cast<QQuickHoverHandler *>(h);
+ // For now, we don't expect multiple hover handlers in one Item, so we choose the first one found;
+ // but a future use case could be to have different cursors for different tablet stylus devices.
+ // In that case, this function needs more information: which device did the event come from.
+ // TODO Qt 6: add QPointerDevice* as argument to this function? (it doesn't exist yet in Qt 5)
+ if (!retHoverHandler && hoverHandler)
+ retHoverHandler = hoverHandler;
+ if (!hoverHandler && h->active())
+ return h;
+ }
+ return retHoverHandler;
+}
+
#endif
/*!
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 3c0517cb3b..841d91bb40 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -471,6 +471,7 @@ public:
bool isTabFence:1;
bool replayingPressEvent:1;
bool touchEnabled:1;
+ bool hasCursorHandler:1;
enum DirtyType {
TransformOrigin = 0x00000001,
@@ -651,6 +652,10 @@ public:
void setHasCursorInChild(bool hasCursor);
void setHasHoverInChild(bool hasHover);
+#if QT_CONFIG(cursor)
+ QCursor effectiveCursor(const QQuickPointerHandler *handler) const;
+ QQuickPointerHandler *effectiveCursorHandler() const;
+#endif
virtual void updatePolish() { }
};
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 3bb6c19dce..491334f439 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -560,6 +560,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, activeFocusItem(nullptr)
#if QT_CONFIG(cursor)
, cursorItem(nullptr)
+ , cursorHandler(nullptr)
#endif
#if QT_CONFIG(quick_draganddrop)
, dragGrabber(nullptr)
@@ -2967,26 +2968,27 @@ void QQuickWindowPrivate::updateCursor(const QPointF &scenePos)
{
Q_Q(QQuickWindow);
- QQuickItem *oldCursorItem = cursorItem;
- cursorItem = findCursorItem(contentItem, scenePos);
+ auto cursorItemAndHandler = findCursorItemAndHandler(contentItem, scenePos);
- if (cursorItem != oldCursorItem) {
+ if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second) {
QWindow *renderWindow = QQuickRenderControl::renderWindowFor(q);
QWindow *window = renderWindow ? renderWindow : q;
+ cursorItem = cursorItemAndHandler.first;
+ cursorHandler = cursorItemAndHandler.second;
if (cursorItem)
- window->setCursor(cursorItem->cursor());
+ window->setCursor(QQuickItemPrivate::get(cursorItem)->effectiveCursor(cursorHandler));
else
window->unsetCursor();
}
}
-QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF &scenePos)
+QPair<QQuickItem*, QQuickPointerHandler*> QQuickWindowPrivate::findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const
{
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
QPointF p = item->mapFromScene(scenePos);
if (!item->contains(p))
- return nullptr;
+ return {nullptr, nullptr};
}
if (itemPrivate->subtreeCursorEnabled) {
@@ -2995,17 +2997,24 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF
QQuickItem *child = children.at(ii);
if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled)
continue;
- if (QQuickItem *cursorItem = findCursorItem(child, scenePos))
- return cursorItem;
+ auto ret = findCursorItemAndHandler(child, scenePos);
+ if (ret.first)
+ return ret;
+ }
+ if (itemPrivate->hasCursor || itemPrivate->hasCursorHandler) {
+ QPointF p = item->mapFromScene(scenePos);
+ if (!item->contains(p))
+ return {nullptr, nullptr};
+ if (itemPrivate->hasCursorHandler) {
+ if (auto handler = itemPrivate->effectiveCursorHandler())
+ return {item, handler};
+ }
+ if (itemPrivate->hasCursor)
+ return {item, nullptr};
}
}
- if (itemPrivate->hasCursor) {
- QPointF p = item->mapFromScene(scenePos);
- if (item->contains(p))
- return item;
- }
- return nullptr;
+ return {nullptr, nullptr};
}
#endif
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index ef10ba3fe8..6e6dc7a400 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -134,6 +134,7 @@ public:
// Keeps track of the item currently receiving mouse events
#if QT_CONFIG(cursor)
QQuickItem *cursorItem;
+ QQuickPointerHandler *cursorHandler;
#endif
#if QT_CONFIG(quick_draganddrop)
QQuickDragGrabber *dragGrabber;
@@ -197,7 +198,7 @@ public:
#endif
#if QT_CONFIG(cursor)
void updateCursor(const QPointF &scenePos);
- QQuickItem *findCursorItem(QQuickItem *item, const QPointF &scenePos);
+ QPair<QQuickItem*, QQuickPointerHandler*> findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const;
#endif
QList<QQuickItem*> hoverItems;
diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp
index eee8562a2a..ceda5589b2 100644
--- a/src/quick/util/qquickbehavior.cpp
+++ b/src/quick/util/qquickbehavior.cpp
@@ -185,6 +185,80 @@ QVariant QQuickBehavior::targetValue() const
return d->targetValue;
}
+/*!
+ \readonly
+ \qmlpropertygroup QtQuick::Behavior::targetProperty
+ \qmlproperty string QtQuick::Behavior::targetProperty.name
+ \qmlproperty Object QtQuick::Behavior::targetProperty.object
+
+ \table
+ \header
+ \li Property
+ \li Description
+ \row
+ \li name
+ \li This property holds the name of the property being controlled by this Behavior.
+ \row
+ \li object
+ \li This property holds the object of the property being controlled by this Behavior.
+ \endtable
+
+ This property can be used to define custom behaviors based on the name or the object of
+ the property being controlled.
+
+ The following example defines a Behavior fading out and fading in its target object
+ when the property it controls changes:
+ \qml
+ // FadeBehavior.qml
+ import QtQuick 2.15
+
+ Behavior {
+ id: root
+ property Item fadeTarget: targetProperty.object
+ SequentialAnimation {
+ NumberAnimation {
+ target: root.fadeTarget
+ property: "opacity"
+ to: 0
+ easing.type: Easing.InQuad
+ }
+ PropertyAction { } // actually change the controlled property between the 2 other animations
+ NumberAnimation {
+ target: root.fadeTarget
+ property: "opacity"
+ to: 1
+ easing.type: Easing.OutQuad
+ }
+ }
+ }
+ \endqml
+
+ This can be used to animate a text when it changes:
+ \qml
+ import QtQuick 2.15
+
+ Text {
+ id: root
+ property int counter
+ text: counter
+ FadeBehavior on text {}
+ Timer {
+ running: true
+ repeat: true
+ interval: 1000
+ onTriggered: ++root.counter
+ }
+ }
+ \endqml
+
+ \since QtQuick 2.15
+*/
+QQmlProperty QQuickBehavior::targetProperty() const
+{
+ Q_D(const QQuickBehavior);
+ return d->property;
+}
+
void QQuickBehavior::write(const QVariant &value)
{
Q_D(QQuickBehavior);
@@ -265,6 +339,8 @@ void QQuickBehavior::setTarget(const QQmlProperty &property)
if (finalizedIdx < 0)
finalizedIdx = metaObject()->indexOfSlot("componentFinalized()");
engPriv->registerFinalizeCallback(this, finalizedIdx);
+
+ Q_EMIT targetPropertyChanged();
}
void QQuickBehavior::componentFinalized()
diff --git a/src/quick/util/qquickbehavior_p.h b/src/quick/util/qquickbehavior_p.h
index fa9cf6d6bc..a57a26d822 100644
--- a/src/quick/util/qquickbehavior_p.h
+++ b/src/quick/util/qquickbehavior_p.h
@@ -70,6 +70,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBehavior : public QObject, public QQmlPropert
Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation)
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(QVariant targetValue READ targetValue NOTIFY targetValueChanged REVISION 13)
+ Q_PROPERTY(QQmlProperty targetProperty READ targetProperty NOTIFY targetPropertyChanged REVISION 15)
Q_CLASSINFO("DeferredPropertyNames", "animation")
QML_NAMED_ELEMENT(Behavior)
@@ -88,9 +89,12 @@ public:
QVariant targetValue() const;
+ QQmlProperty targetProperty() const;
+
Q_SIGNALS:
void enabledChanged();
void targetValueChanged();
+ void targetPropertyChanged();
private Q_SLOTS:
void componentFinalized();
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 85bc78dee8..3ea2f88712 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -273,6 +273,52 @@ public:
return QMatrix4x4();
}
+ static QColorSpace colorSpaceFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
+ {
+ if (ok)
+ *ok = false;
+ QColorSpace retn;
+ QV4::Scope scope(v4);
+ QV4::ScopedObject obj(scope, object);
+ if (!obj) {
+ if (ok)
+ *ok = false;
+ return retn;
+ }
+
+ QV4::ScopedString s(scope);
+
+ QV4::ScopedValue vName(scope, obj->get((s = v4->newString(QStringLiteral("namedColorSpace")))));
+ if (vName->isInt32()) {
+ if (ok)
+ *ok = true;
+ return QColorSpace((QColorSpace::NamedColorSpace)vName->toInt32());
+ }
+
+ QV4::ScopedValue vPri(scope, obj->get((s = v4->newString(QStringLiteral("primaries")))));
+ QV4::ScopedValue vTra(scope, obj->get((s = v4->newString(QStringLiteral("transferFunction")))));
+ if (!vPri->isInt32() || !vTra->isInt32()) {
+ if (ok)
+ *ok = false;
+ return retn;
+ }
+
+ QColorSpace::Primaries pri = static_cast<QColorSpace::Primaries>(vPri->integerValue());
+ QColorSpace::TransferFunction tra = static_cast<QColorSpace::TransferFunction>(vTra->integerValue());
+ float gamma = 0.0f;
+ if (tra == QColorSpace::TransferFunction::Gamma) {
+ QV4::ScopedValue vGam(scope, obj->get((s = v4->newString(QStringLiteral("gamma")))));
+ if (!vGam->isNumber()) {
+ if (ok)
+ *ok = false;
+ return retn;
+ }
+ gamma = vGam->toNumber();
+ }
+ if (ok) *ok = true;
+ return QColorSpace(pri, tra, gamma);
+ }
+
static QFont fontFromObject(const QV4::Value &object, QV4::ExecutionEngine *v4, bool *ok)
{
if (ok)
@@ -402,6 +448,8 @@ public:
switch (type) {
case QMetaType::QColor:
return &QQuickColorValueType::staticMetaObject;
+ case QMetaType::QColorSpace:
+ return &QQuickColorSpaceValueType::staticMetaObject;
case QMetaType::QFont:
return &QQuickFontValueType::staticMetaObject;
case QMetaType::QVector2D:
@@ -427,6 +475,9 @@ public:
case QMetaType::QColor:
dst.setValue<QColor>(QColor());
return true;
+ case QMetaType::QColorSpace:
+ dst.setValue<QColorSpace>(QColorSpace());
+ return true;
case QMetaType::QFont:
dst.setValue<QFont>(QFont());
return true;
@@ -647,6 +698,9 @@ public:
#endif
bool ok = false;
switch (type) {
+ case QMetaType::QColorSpace:
+ *v = QVariant::fromValue(colorSpaceFromObject(object, v4, &ok));
+ break;
case QMetaType::QFont:
*v = QVariant::fromValue(fontFromObject(object, v4, &ok));
break;
@@ -669,6 +723,8 @@ public:
switch (type) {
case QMetaType::QColor:
return typedEqual<QColor>(lhs, rhs);
+ case QMetaType::QColorSpace:
+ return typedEqual<QColorSpace>(lhs, rhs);
case QMetaType::QFont:
return typedEqual<QFont>(lhs, rhs);
case QMetaType::QVector2D:
@@ -732,6 +788,8 @@ public:
switch (dstType) {
case QMetaType::QColor:
return typedRead<QColor>(src, dstType, dst);
+ case QMetaType::QColorSpace:
+ return typedRead<QColorSpace>(src, dstType, dst);
case QMetaType::QFont:
return typedRead<QFont>(src, dstType, dst);
case QMetaType::QVector2D:
@@ -766,6 +824,8 @@ public:
switch (type) {
case QMetaType::QColor:
return typedWrite<QColor>(src, dst);
+ case QMetaType::QColorSpace:
+ return typedWrite<QColorSpace>(src, dst);
case QMetaType::QFont:
return typedWrite<QFont>(src, dst);
case QMetaType::QVector2D:
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index db82b2d807..80873e2ad5 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -43,6 +43,7 @@
#include "qquickpixmapcache_p.h"
#include <QtQuick/private/qsgcontext_p.h>
#include <private/qqmlglobal_p.h>
+#include <QtGui/qcolorspace.h>
QT_BEGIN_NAMESPACE
@@ -510,6 +511,7 @@ public:
{
}
+ QColorSpace targetColorSpace;
QQuickImageProviderOptions::AutoTransform autoTransform = QQuickImageProviderOptions::UsePluginDefaultTransform;
bool preserveAspectRatioCrop = false;
bool preserveAspectRatioFit = false;
@@ -558,7 +560,8 @@ bool QQuickImageProviderOptions::operator==(const QQuickImageProviderOptions &ot
{
return d->autoTransform == other.d->autoTransform &&
d->preserveAspectRatioCrop == other.d->preserveAspectRatioCrop &&
- d->preserveAspectRatioFit == other.d->preserveAspectRatioFit;
+ d->preserveAspectRatioFit == other.d->preserveAspectRatioFit &&
+ d->targetColorSpace == other.d->targetColorSpace;
}
/*!
@@ -602,6 +605,19 @@ void QQuickImageProviderOptions::setPreserveAspectRatioFit(bool preserveAspectRa
d->preserveAspectRatioFit = preserveAspectRatioFit;
}
+/*!
+ Returns the color space the image provider should return the image in.
+*/
+QColorSpace QQuickImageProviderOptions::targetColorSpace() const
+{
+ return d->targetColorSpace;
+}
+
+void QQuickImageProviderOptions::setTargetColorSpace(const QColorSpace &colorSpace)
+{
+ d->targetColorSpace = colorSpace;
+}
+
QQuickImageProviderWithOptions::QQuickImageProviderWithOptions(ImageType type, Flags flags)
: QQuickAsyncImageProvider()
{
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index bdd1e2c514..2ae9debbc9 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -318,6 +318,7 @@ public:
QSize requestSize;
QQuickImageProviderOptions providerOptions;
QQuickImageProviderOptions::AutoTransform appliedTransform;
+ QColorSpace targetColorSpace;
QQuickTextureFactory *textureFactory;
@@ -436,6 +437,12 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e
maybeRemoveAlpha(image);
if (impsize && impsize->width() < 0)
*impsize = image->size();
+ if (providerOptions.targetColorSpace().isValid()) {
+ if (image->colorSpace().isValid())
+ image->convertToColorSpace(providerOptions.targetColorSpace());
+ else
+ image->setColorSpace(providerOptions.targetColorSpace());
+ }
return true;
} else {
if (errorString)
@@ -1763,6 +1770,13 @@ bool QQuickPixmap::connectDownloadProgress(QObject *object, int method)
return QMetaObject::connect(d->reply, QQuickPixmapReply::downloadProgressIndex, object, method);
}
+QColorSpace QQuickPixmap::colorSpace() const
+{
+ if (!d || !d->textureFactory)
+ return QColorSpace();
+ return d->textureFactory->image().colorSpace();
+}
+
QT_END_NAMESPACE
#include <qquickpixmapcache.moc>
diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h
index 65d102af71..87724d6210 100644
--- a/src/quick/util/qquickpixmapcache_p.h
+++ b/src/quick/util/qquickpixmapcache_p.h
@@ -117,6 +117,9 @@ public:
bool preserveAspectRatioFit() const;
void setPreserveAspectRatioFit(bool preserveAspectRatioFit);
+ QColorSpace targetColorSpace() const;
+ void setTargetColorSpace(const QColorSpace &colorSpace);
+
private:
QSharedDataPointer<QQuickImageProviderOptionsPrivate> d;
};
@@ -156,6 +159,8 @@ public:
void setImage(const QImage &);
void setPixmap(const QQuickPixmap &other);
+ QColorSpace colorSpace() const;
+
QQuickTextureFactory *textureFactory() const;
QRect rect() const;
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index f9cd28cb24..517ed5da38 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -41,6 +41,7 @@
#include <qtquickglobal.h>
#include <private/qqmlvaluetype_p.h>
+#include <private/qcolorspace_p.h>
#include <private/qfont_p.h>
@@ -784,6 +785,47 @@ void QQuickFontValueType::setPreferShaping(bool enable)
v.setStyleStrategy(static_cast<QFont::StyleStrategy>(v.styleStrategy() | QFont::PreferNoShaping));
}
+QQuickColorSpaceValueType::NamedColorSpace QQuickColorSpaceValueType::namedColorSpace() const noexcept
+{
+ if (const auto *p = QColorSpacePrivate::get(v))
+ return (QQuickColorSpaceValueType::NamedColorSpace)p->namedColorSpace;
+ return QQuickColorSpaceValueType::Unknown;
+}
+void QQuickColorSpaceValueType::setNamedColorSpace(QQuickColorSpaceValueType::NamedColorSpace namedColorSpace)
+{
+ v = { (QColorSpace::NamedColorSpace)namedColorSpace };
+}
+
+QQuickColorSpaceValueType::Primaries QQuickColorSpaceValueType::primaries() const noexcept
+{
+ return (QQuickColorSpaceValueType::Primaries)v.primaries();
+}
+
+void QQuickColorSpaceValueType::setPrimaries(QQuickColorSpaceValueType::Primaries primariesId)
+{
+ v.setPrimaries((QColorSpace::Primaries)primariesId);
+}
+
+QQuickColorSpaceValueType::TransferFunction QQuickColorSpaceValueType::transferFunction() const noexcept
+{
+ return (QQuickColorSpaceValueType::TransferFunction)v.transferFunction();
+}
+
+void QQuickColorSpaceValueType::setTransferFunction(QQuickColorSpaceValueType::TransferFunction transferFunction)
+{
+ v.setTransferFunction((QColorSpace::TransferFunction)transferFunction, v.gamma());
+}
+
+float QQuickColorSpaceValueType::gamma() const noexcept
+{
+ return v.gamma();
+}
+
+void QQuickColorSpaceValueType::setGamma(float gamma)
+{
+ v.setTransferFunction(v.transferFunction(), gamma);
+}
+
QT_END_NAMESPACE
#include "moc_qquickvaluetypes_p.cpp"
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index 91a5ea83e5..5c22e5c087 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -56,6 +56,7 @@
#include <private/qqmlvaluetype_p.h>
#include <QtGui/QColor>
+#include <QtGui/QColorSpace>
#include <QtGui/QVector2D>
#include <QtGui/QVector3D>
#include <QtGui/QVector4D>
@@ -408,6 +409,57 @@ public:
void setPreferShaping(bool b);
};
+class QQuickColorSpaceValueType
+{
+ QColorSpace v;
+ Q_GADGET
+
+ Q_PROPERTY(NamedColorSpace namedColorSpace READ namedColorSpace WRITE setNamedColorSpace FINAL)
+ Q_PROPERTY(Primaries primaries READ primaries WRITE setPrimaries FINAL)
+ Q_PROPERTY(TransferFunction transferFunction READ transferFunction WRITE setTransferFunction FINAL)
+ Q_PROPERTY(float gamma READ gamma WRITE setGamma FINAL)
+
+ QML_NAMED_ELEMENT(ColorSpace)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+
+public:
+ enum NamedColorSpace {
+ Unknown = 0,
+ SRgb,
+ SRgbLinear,
+ AdobeRgb,
+ DisplayP3,
+ ProPhotoRgb
+ };
+ Q_ENUM(NamedColorSpace)
+
+ enum class Primaries {
+ Custom = 0,
+ SRgb,
+ AdobeRgb,
+ DciP3D65,
+ ProPhotoRgb
+ };
+ Q_ENUM(Primaries)
+ enum class TransferFunction {
+ Custom = 0,
+ Linear,
+ Gamma,
+ SRgb,
+ ProPhotoRgb
+ };
+ Q_ENUM(TransferFunction)
+
+ NamedColorSpace namedColorSpace() const noexcept;
+ void setNamedColorSpace(NamedColorSpace namedColorSpace);
+ Primaries primaries() const noexcept;
+ void setPrimaries(Primaries primariesId);
+ TransferFunction transferFunction() const noexcept;
+ void setTransferFunction(TransferFunction transferFunction);
+ float gamma() const noexcept;
+ void setGamma(float gamma);
+};
+
QT_END_NAMESPACE
#endif // QQUICKVALUETYPES_P_H