QJSValue converter for QskGradient added to be compatible with new Qt
6.5 features
This commit is contained in:
parent
57c25294c4
commit
abf325dbde
@ -7,15 +7,15 @@ GridBox
|
||||
//margins: 10 // only possible with Qt <= 6.1 || Qt >= 6.5
|
||||
margins { left: 10; top: 10; right: 10; bottom: 10 }
|
||||
|
||||
background
|
||||
{
|
||||
linear: [ 0.0, 0.0, 1.0, 0.0 ]
|
||||
background:
|
||||
({
|
||||
linear: { x1: 0, y1: 0, x2: 1, y2: 1 }, // diagonal
|
||||
|
||||
stops: [
|
||||
{ position: 0.0, color: "Red" },
|
||||
{ position: 1.0, color: "Yellow" },
|
||||
{ position: 1.0, color: "Yellow" }
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
TestRectangle
|
||||
{
|
||||
|
@ -4,6 +4,8 @@
|
||||
*****************************************************************************/
|
||||
|
||||
#include "QskQml.h"
|
||||
#include "QskQml.hpp"
|
||||
|
||||
#include "QskLayoutQml.h"
|
||||
#include "QskShortcutQml.h"
|
||||
#include "QskMainQml.h"
|
||||
@ -50,301 +52,121 @@
|
||||
#include <QskVirtualKeyboard.h>
|
||||
#include <QskWindow.h>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 )
|
||||
#include <qqmlengine.h>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 )
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qqmlmetatype_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qqmlmetatype_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 5, 0 )
|
||||
|
||||
#define QSK_MODULE_NAME "Skinny"
|
||||
#define QSK_VERSION_MAJOR 1
|
||||
#define QSK_VERSION_MINOR 0
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 3, 0 )
|
||||
#define QSK_STRUCT_VERSION 0
|
||||
#elif QT_VERSION < QT_VERSION_CHECK( 6, 5, 0 )
|
||||
#define QSK_STRUCT_VERSION 1
|
||||
#else
|
||||
#define QSK_STRUCT_VERSION 2
|
||||
#endif
|
||||
|
||||
// Required for QFlags to be constructed from an enum value
|
||||
#define QSK_REGISTER_FLAGS( Type ) \
|
||||
QMetaType::registerConverter< int, Type >( []( int value ) { return Type( value ); } )
|
||||
#include <qjsvalue.h>
|
||||
#include <qjsvalueiterator.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
inline const char* classNameQml( const QMetaObject& metaObject )
|
||||
{
|
||||
// without the "Qsk" prefix
|
||||
return metaObject.className() + 3;
|
||||
}
|
||||
|
||||
/*
|
||||
ClassInfo corresponds to the most reecent QQmlPrivate::RegisterType
|
||||
( structVersion: 2 introduced with Qt 6.5 )
|
||||
Since Qt 6.5 we have QML_STRUCTURED_VALUE and do not need to
|
||||
write our own converter.
|
||||
|
||||
However: we should also be able to implement a generic converter from the
|
||||
metatype information: TODO ...
|
||||
|
||||
For the moment we have these converters:
|
||||
*/
|
||||
class ClassInfo
|
||||
QskGradientStop toGradientStop( const QJSValue& value )
|
||||
{
|
||||
public:
|
||||
return QskGradientStop(
|
||||
value.property( QStringLiteral( "position" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "color" ) ).toVariant().value< QColor >()
|
||||
);
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void setTypeInfo()
|
||||
QskLinearDirection toLinearDirection( const QJSValue& value )
|
||||
{
|
||||
return QskLinearDirection(
|
||||
value.property( QStringLiteral( "x1" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "y1" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "x2" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "y2" ) ).toNumber() );
|
||||
}
|
||||
|
||||
QskConicDirection toConicDirection( const QJSValue& value )
|
||||
{
|
||||
return QskConicDirection(
|
||||
value.property( QStringLiteral( "x" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "y" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "startAngle" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "spanAngle" ) ).toNumber() );
|
||||
}
|
||||
|
||||
QskRadialDirection toRadialDirection( const QJSValue& value )
|
||||
{
|
||||
return QskRadialDirection(
|
||||
value.property( QStringLiteral( "x" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "y" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "radius" ) ).toNumber() );
|
||||
}
|
||||
|
||||
QskGradient toGradient( const QJSValue& value )
|
||||
{
|
||||
QskGradient gradient;
|
||||
|
||||
QJSValueIterator it( value );
|
||||
|
||||
while ( it.hasNext() )
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
it.next();
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
const char* className = T::staticMetaObject.className(); \
|
||||
auto v = it.value();
|
||||
|
||||
const int nameLen = int(strlen(className) ); \
|
||||
const int listLen = int(strlen("QQmlListProperty<") ); \
|
||||
|
||||
QVarLengthArray< char,64 > listName(listLen + nameLen + 2); \
|
||||
memcpy(listName.data(), "QQmlListProperty<", size_t(listLen) ); \
|
||||
memcpy(listName.data() + listLen, className, size_t(nameLen) ); \
|
||||
listName[listLen + nameLen] = '>'; \
|
||||
listName[listLen + nameLen + 1] = '\0';
|
||||
|
||||
typeId = qMetaTypeId< T* >( );
|
||||
listId = qRegisterNormalizedMetaType< QQmlListProperty< T > >( listName.constData() );
|
||||
#else
|
||||
if constexpr (std::is_base_of_v< QObject, T >)
|
||||
if ( v.isObject() )
|
||||
{
|
||||
typeId = QMetaType::fromType< T* >( );
|
||||
listId = QMetaType::fromType< QQmlListProperty< T > >( );
|
||||
if ( v.isArray() )
|
||||
{
|
||||
if ( it.name() == QStringLiteral( "stops" ) )
|
||||
{
|
||||
QskGradientStops stops;
|
||||
|
||||
const int n = v.property( QStringLiteral( "length" ) ).toInt();
|
||||
for ( int i = 0; i < n; i++ )
|
||||
stops += toGradientStop( v.property( i ) );
|
||||
|
||||
gradient.setStops( stops );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( it.name() == QStringLiteral( "linear" ) )
|
||||
{
|
||||
gradient.setLinearDirection( toLinearDirection( v ) );
|
||||
}
|
||||
else if ( it.name() == QStringLiteral( "conic" ) )
|
||||
{
|
||||
gradient.setConicDirection( toConicDirection( v ) );
|
||||
}
|
||||
else if ( it.name() == QStringLiteral( "radial" ) )
|
||||
{
|
||||
gradient.setRadialDirection( toRadialDirection( v ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
typeId = QMetaType::fromType< T >( );
|
||||
listId = QMetaType::fromType< QList< T > >( );
|
||||
}
|
||||
|
||||
createValueType = ValueType< T, void >::create;
|
||||
#endif
|
||||
|
||||
|
||||
parserStatusCast = StaticCastSelector< T,QQmlParserStatus >::cast();
|
||||
valueSourceCast = StaticCastSelector< T,QQmlPropertyValueSource >::cast();
|
||||
valueInterceptorCast = StaticCastSelector< T,QQmlPropertyValueInterceptor >::cast();
|
||||
#if QSK_STRUCT_VERSION >= 1
|
||||
finalizerCast = StaticCastSelector< T,QQmlFinalizerHook >::cast();
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
const int structVersion = QSK_STRUCT_VERSION;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
QMetaType typeId;
|
||||
QMetaType listId;
|
||||
#else
|
||||
int typeId = 0;
|
||||
int listId = 0;
|
||||
#endif
|
||||
|
||||
int objectSize = 0;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
void ( *create )( void* ) = nullptr;
|
||||
#else
|
||||
void ( *create )( void*, void* ) = nullptr;
|
||||
void* const userdata = nullptr; // unused
|
||||
#endif
|
||||
|
||||
const QString noCreationReason; // unused
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
/*
|
||||
This one was introdued with Qt 6.x, but never worked
|
||||
as expected. With Qt 6.5 it has been replaced by adding
|
||||
the creationMethod that is triggering to look for
|
||||
invokable constructors.
|
||||
Let's check if it makes any sense to initialize it below
|
||||
at all. TODO ...
|
||||
*/
|
||||
QVariant ( *createValueType )( const QJSValue& ) = nullptr;
|
||||
#endif
|
||||
|
||||
const char* const uri = QSK_MODULE_NAME;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
const QTypeRevision version =
|
||||
QTypeRevision::fromVersion( QSK_VERSION_MAJOR, QSK_VERSION_MINOR );
|
||||
#else
|
||||
const int versionMajor = QSK_VERSION_MAJOR;
|
||||
const int versionMinor = QSK_VERSION_MINOR;
|
||||
#endif
|
||||
const char* elementName = nullptr;
|
||||
const QMetaObject* metaObject = nullptr;
|
||||
|
||||
/*
|
||||
We do not use attached properties as it always comes with
|
||||
creating extra QObjects.
|
||||
*/
|
||||
QObject* (* const attachedPropertiesFunction)( QObject* ) = nullptr;
|
||||
const QMetaObject* const attachedPropertiesMetaObject = nullptr;
|
||||
|
||||
int parserStatusCast = -1;
|
||||
int valueSourceCast = -1;
|
||||
int valueInterceptorCast = -1;
|
||||
|
||||
/*
|
||||
We do not use extensions as it always comes with
|
||||
creating extra QObjects.
|
||||
*/
|
||||
QObject* (* const extensionObjectCreate )( QObject* ) = nullptr;
|
||||
const QMetaObject* const extensionMetaObject = nullptr;
|
||||
|
||||
QQmlCustomParser* const customParser = nullptr; // unused
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
const QTypeRevision revision = QTypeRevision::zero();
|
||||
#else
|
||||
const int revision = 0;
|
||||
#endif
|
||||
int finalizerCast = -1;
|
||||
|
||||
const int creationMethod = 2; // ValueTypeCreationMethod::Structured
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
inline int registerType( const char* qmlName )
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
ClassInfo type;
|
||||
|
||||
type.setTypeInfo< T >();
|
||||
|
||||
type.objectSize = sizeof( T );
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
type.create = Constructors< T >::createInto;
|
||||
#else
|
||||
type.create = createInto< T >;
|
||||
#endif
|
||||
|
||||
type.elementName = qmlName;
|
||||
type.metaObject = & T::staticMetaObject;
|
||||
|
||||
return qmlregister( TypeRegistration, & type );
|
||||
return gradient;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline int registerUncreatableType( const char* qmlName )
|
||||
void registerJSConverters()
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
ClassInfo type;
|
||||
|
||||
type.setTypeInfo< T >( );
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
type.objectSize = sizeof( T );
|
||||
type.create = Constructors< T >::createInto;
|
||||
#endif
|
||||
|
||||
type.elementName = qmlName;
|
||||
type.metaObject = & T::staticMetaObject;
|
||||
|
||||
return qmlregister( TypeRegistration, & type );
|
||||
}
|
||||
|
||||
int registerUncreatableMetaObject(
|
||||
const QMetaObject& staticMetaObject, const char* qmlName )
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
ClassInfo type;
|
||||
|
||||
type.elementName = qmlName;
|
||||
type.metaObject = & staticMetaObject;
|
||||
|
||||
return qmlregister( TypeRegistration, & type );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void registerObject( const char* qmlName = nullptr )
|
||||
{
|
||||
// the class name without the "Qsk" prefix
|
||||
if ( qmlName == nullptr )
|
||||
qmlName = classNameQml( T::staticMetaObject );
|
||||
|
||||
( void ) registerType< T >( qmlName );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void registerGadget()
|
||||
{
|
||||
auto className = classNameQml( T::staticMetaObject );
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
registerUncreatableType< T >( className );
|
||||
#else
|
||||
/*
|
||||
According to the QML naming rules uncreatables have to
|
||||
start with a lowercase letter ( since Qt6 ), while namespaces
|
||||
and creatable items usually start with a upper letter.
|
||||
This results in an odd naming scheme for the enums defined inside of gadgets.
|
||||
|
||||
To work around this we register the gadget twice - starting with
|
||||
upper or lower letter.
|
||||
|
||||
Maybe it would make sense to only pass stripped metaObjects, where all
|
||||
enums are removed from the first and everything else than the enums from
|
||||
the second. TODO ...
|
||||
*/
|
||||
|
||||
if ( T::staticMetaObject.enumeratorCount() > 0 )
|
||||
{
|
||||
registerUncreatableMetaObject( T::staticMetaObject, className );
|
||||
}
|
||||
|
||||
QByteArray name = className;
|
||||
name.data()[0] = std::tolower( name.data()[0] );
|
||||
registerUncreatableType< T >( name.constData() );
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int registerNamespace( const QMetaObject& metaObject )
|
||||
{
|
||||
return registerUncreatableMetaObject( metaObject, classNameQml( metaObject ) );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline int registerSingleton( QObject* singleton )
|
||||
{
|
||||
const auto name = classNameQml( T::staticMetaObject );
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 )
|
||||
auto callback =
|
||||
[]( QQmlEngine*, QJSEngine* )
|
||||
{
|
||||
QQmlEngine::setObjectOwnership( singleton, QQmlEngine::CppOwnership );
|
||||
return singleton;
|
||||
};
|
||||
|
||||
return qmlRegisterSingletonType< T >( QSK_MODULE_NAME,
|
||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, callback );
|
||||
#else
|
||||
return qmlRegisterSingletonInstance( QSK_MODULE_NAME,
|
||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, singleton );
|
||||
#endif
|
||||
QMetaType::registerConverter< QJSValue, QskGradient >( toGradient );
|
||||
QMetaType::registerConverter< QJSValue, QskLinearDirection >( toLinearDirection );
|
||||
QMetaType::registerConverter< QJSValue, QskConicDirection >( toConicDirection );
|
||||
QMetaType::registerConverter< QJSValue, QskRadialDirection >( toRadialDirection );
|
||||
QMetaType::registerConverter< QJSValue, QskGradientStop >( toGradientStop );
|
||||
}
|
||||
}
|
||||
|
||||
static inline QskGradientStop qskJSToGradientStop( const QJSValue& value )
|
||||
{
|
||||
return QskGradientStop(
|
||||
value.property( QStringLiteral( "position" ) ).toNumber(),
|
||||
value.property( QStringLiteral( "color" ) ).toVariant().value< QColor >()
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
void QskQml::registerTypes()
|
||||
{
|
||||
@ -420,10 +242,18 @@ void QskQml::registerTypes()
|
||||
|
||||
registerNamespace( QskStandardSymbol::staticMetaObject );
|
||||
|
||||
QMetaType::registerConverter< QJSValue, QskGradientStop >( qskJSToGradientStop );
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 5, 0 )
|
||||
registerJSConverters();
|
||||
#endif
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 )
|
||||
// how to do this with >= 6.2 TODO ...
|
||||
/*
|
||||
Since Qt 6.5 invokable constructors are accessible from QML, something
|
||||
what was possibe until Qt 6.2 with string converters. For Qt [6.2,6.4]
|
||||
we do not have any solution.
|
||||
*/
|
||||
|
||||
QQmlMetaType::registerCustomStringConverter( qMetaTypeId< QskMargins >(),
|
||||
[]( const QString& s ) { return QVariant::fromValue( QskMargins( s.toDouble() ) ); } );
|
||||
#endif
|
||||
|
293
qmlexport/QskQml.hpp
Normal file
293
qmlexport/QskQml.hpp
Normal file
@ -0,0 +1,293 @@
|
||||
/******************************************************************************
|
||||
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QSK_QML_HPP
|
||||
#define QSK_QML_HPP
|
||||
|
||||
#include <qqml.h>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 )
|
||||
#include <qqmlengine.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define QSK_MODULE_NAME "Skinny"
|
||||
#define QSK_VERSION_MAJOR 1
|
||||
#define QSK_VERSION_MINOR 0
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 3, 0 )
|
||||
#define QSK_STRUCT_VERSION 0
|
||||
#elif QT_VERSION < QT_VERSION_CHECK( 6, 5, 0 )
|
||||
#define QSK_STRUCT_VERSION 1
|
||||
#else
|
||||
#define QSK_STRUCT_VERSION 2
|
||||
#endif
|
||||
|
||||
// Required for QFlags to be constructed from an enum value
|
||||
#define QSK_REGISTER_FLAGS( Type ) \
|
||||
QMetaType::registerConverter< int, Type >( []( int value ) { return Type( value ); } )
|
||||
|
||||
namespace QskQml
|
||||
{
|
||||
inline const char* classNameQml( const QMetaObject& metaObject )
|
||||
{
|
||||
// without the "Qsk" prefix
|
||||
return metaObject.className() + 3;
|
||||
}
|
||||
|
||||
/*
|
||||
ClassInfo corresponds to the most reecent QQmlPrivate::RegisterType
|
||||
( structVersion: 2 introduced with Qt 6.5 )
|
||||
*/
|
||||
class ClassInfo
|
||||
{
|
||||
public:
|
||||
|
||||
template< typename T >
|
||||
void setTypeInfo()
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
const char* className = T::staticMetaObject.className(); \
|
||||
|
||||
const int nameLen = int(strlen(className) ); \
|
||||
const int listLen = int(strlen("QQmlListProperty<") ); \
|
||||
|
||||
QVarLengthArray< char,64 > listName(listLen + nameLen + 2); \
|
||||
memcpy(listName.data(), "QQmlListProperty<", size_t(listLen) ); \
|
||||
memcpy(listName.data() + listLen, className, size_t(nameLen) ); \
|
||||
listName[listLen + nameLen] = '>'; \
|
||||
listName[listLen + nameLen + 1] = '\0';
|
||||
|
||||
typeId = qMetaTypeId< T* >( );
|
||||
listId = qRegisterNormalizedMetaType< QQmlListProperty< T > >( listName.constData() );
|
||||
#else
|
||||
if constexpr (std::is_base_of_v< QObject, T >)
|
||||
{
|
||||
typeId = QMetaType::fromType< T* >( );
|
||||
listId = QMetaType::fromType< QQmlListProperty< T > >( );
|
||||
}
|
||||
else
|
||||
{
|
||||
typeId = QMetaType::fromType< T >( );
|
||||
listId = QMetaType::fromType< QList< T > >( );
|
||||
}
|
||||
|
||||
createValueType = ValueType< T, void >::create;
|
||||
#endif
|
||||
|
||||
|
||||
parserStatusCast = StaticCastSelector< T,QQmlParserStatus >::cast();
|
||||
valueSourceCast = StaticCastSelector< T,QQmlPropertyValueSource >::cast();
|
||||
valueInterceptorCast = StaticCastSelector< T,QQmlPropertyValueInterceptor >::cast();
|
||||
#if QSK_STRUCT_VERSION >= 1
|
||||
finalizerCast = StaticCastSelector< T,QQmlFinalizerHook >::cast();
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
const int structVersion = QSK_STRUCT_VERSION;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
QMetaType typeId;
|
||||
QMetaType listId;
|
||||
#else
|
||||
int typeId = 0;
|
||||
int listId = 0;
|
||||
#endif
|
||||
|
||||
int objectSize = 0;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
void ( *create )( void* ) = nullptr;
|
||||
#else
|
||||
void ( *create )( void*, void* ) = nullptr;
|
||||
void* const userdata = nullptr; // unused
|
||||
#endif
|
||||
|
||||
const QString noCreationReason; // unused
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
/*
|
||||
This one was introdued with Qt 6.x, but never worked
|
||||
as expected. With Qt 6.5 it has been replaced by adding
|
||||
the creationMethod that is triggering to look for
|
||||
invokable constructors.
|
||||
Let's check if it makes any sense to initialize it below
|
||||
at all. TODO ...
|
||||
*/
|
||||
QVariant ( *createValueType )( const QJSValue& ) = nullptr;
|
||||
#endif
|
||||
|
||||
const char* const uri = QSK_MODULE_NAME;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
const QTypeRevision version =
|
||||
QTypeRevision::fromVersion( QSK_VERSION_MAJOR, QSK_VERSION_MINOR );
|
||||
#else
|
||||
const int versionMajor = QSK_VERSION_MAJOR;
|
||||
const int versionMinor = QSK_VERSION_MINOR;
|
||||
#endif
|
||||
const char* elementName = nullptr;
|
||||
const QMetaObject* metaObject = nullptr;
|
||||
|
||||
/*
|
||||
We do not use attached properties as it always comes with
|
||||
creating extra QObjects.
|
||||
*/
|
||||
QObject* (* const attachedPropertiesFunction)( QObject* ) = nullptr;
|
||||
const QMetaObject* const attachedPropertiesMetaObject = nullptr;
|
||||
|
||||
int parserStatusCast = -1;
|
||||
int valueSourceCast = -1;
|
||||
int valueInterceptorCast = -1;
|
||||
|
||||
/*
|
||||
We do not use extensions as it always comes with
|
||||
creating extra QObjects.
|
||||
*/
|
||||
QObject* (* const extensionObjectCreate )( QObject* ) = nullptr;
|
||||
const QMetaObject* const extensionMetaObject = nullptr;
|
||||
|
||||
void* const customParser = nullptr; // QQmlCustomParser, unused
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
const QTypeRevision revision = QTypeRevision::zero();
|
||||
#else
|
||||
const int revision = 0;
|
||||
#endif
|
||||
int finalizerCast = -1;
|
||||
|
||||
const int creationMethod = 2; // ValueTypeCreationMethod::Structured
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
inline int registerType( const char* qmlName )
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
ClassInfo type;
|
||||
|
||||
type.setTypeInfo< T >();
|
||||
|
||||
type.objectSize = sizeof( T );
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
type.create = Constructors< T >::createInto;
|
||||
#else
|
||||
type.create = createInto< T >;
|
||||
#endif
|
||||
|
||||
type.elementName = qmlName;
|
||||
type.metaObject = &T::staticMetaObject;
|
||||
|
||||
return qmlregister( TypeRegistration, &type );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline int registerUncreatableType( const char* qmlName )
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
ClassInfo type;
|
||||
|
||||
type.setTypeInfo< T >();
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||
type.objectSize = sizeof( T );
|
||||
type.create = Constructors< T >::createInto;
|
||||
#endif
|
||||
|
||||
type.elementName = qmlName;
|
||||
type.metaObject = &T::staticMetaObject;
|
||||
|
||||
return qmlregister( TypeRegistration, &type );
|
||||
}
|
||||
|
||||
int registerUncreatableMetaObject(
|
||||
const QMetaObject& staticMetaObject, const char* qmlName )
|
||||
{
|
||||
using namespace QQmlPrivate;
|
||||
|
||||
ClassInfo type;
|
||||
|
||||
type.elementName = qmlName;
|
||||
type.metaObject = &staticMetaObject;
|
||||
|
||||
return qmlregister( TypeRegistration, &type );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void registerObject( const char* qmlName = nullptr )
|
||||
{
|
||||
// the class name without the "Qsk" prefix
|
||||
if ( qmlName == nullptr )
|
||||
qmlName = classNameQml( T::staticMetaObject );
|
||||
|
||||
( void ) registerType< T >( qmlName );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline void registerGadget()
|
||||
{
|
||||
auto className = classNameQml( T::staticMetaObject );
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||
registerUncreatableType< T >( className );
|
||||
#else
|
||||
/*
|
||||
According to the QML naming rules uncreatables have to
|
||||
start with a lowercase letter ( since Qt6 ), while namespaces
|
||||
and creatable items usually start with a upper letter.
|
||||
This results in an odd naming scheme for the enums defined inside of gadgets.
|
||||
|
||||
To work around this we register the gadget twice - starting with
|
||||
upper or lower letter.
|
||||
|
||||
Maybe it would make sense to only pass stripped metaObjects, where all
|
||||
enums are removed from the first and everything else than the enums from
|
||||
the second. TODO ...
|
||||
*/
|
||||
|
||||
if ( T::staticMetaObject.enumeratorCount() > 0 )
|
||||
{
|
||||
registerUncreatableMetaObject( T::staticMetaObject, className );
|
||||
}
|
||||
|
||||
QByteArray name = className;
|
||||
name.data()[0] = std::tolower( name.data()[0] );
|
||||
registerUncreatableType< T >( name.constData() );
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int registerNamespace( const QMetaObject& metaObject )
|
||||
{
|
||||
return registerUncreatableMetaObject( metaObject, classNameQml( metaObject ) );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline int registerSingleton( QObject* singleton )
|
||||
{
|
||||
const auto name = classNameQml( T::staticMetaObject );
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 )
|
||||
auto callback =
|
||||
[]( QQmlEngine*, QJSEngine* )
|
||||
{
|
||||
QQmlEngine::setObjectOwnership( singleton, QQmlEngine::CppOwnership );
|
||||
return singleton;
|
||||
};
|
||||
|
||||
return qmlRegisterSingletonType< T >( QSK_MODULE_NAME,
|
||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, callback );
|
||||
#else
|
||||
return qmlRegisterSingletonInstance( QSK_MODULE_NAME,
|
||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, singleton );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -6,6 +6,9 @@ CONFIG += qskinny
|
||||
|
||||
contains(QSK_CONFIG, QskDll): DEFINES += QSK_QML_MAKEDLL
|
||||
|
||||
HEADERS += \
|
||||
QskQml.hpp
|
||||
|
||||
HEADERS += \
|
||||
QskQmlGlobal.h \
|
||||
QskShortcutQml.h \
|
||||
|
@ -533,74 +533,6 @@ void QskGradient::resetDirection()
|
||||
m_values[0] = m_values[1] = m_values[2] = m_values[3] = 0.0;
|
||||
}
|
||||
|
||||
void QskGradient::setLinearAsList( const QVector< qreal >& params )
|
||||
{
|
||||
Q_ASSERT( params.size() == 4 );
|
||||
|
||||
m_type = Linear;
|
||||
|
||||
m_values[0] = params[0];
|
||||
m_values[1] = params[1];
|
||||
m_values[2] = params[2];
|
||||
m_values[3] = params[3];
|
||||
}
|
||||
|
||||
QVector< qreal > QskGradient::linearAsList() const
|
||||
{
|
||||
if ( m_type != Linear )
|
||||
return { 0.0, 0.0, 0.0, 0.0 };
|
||||
|
||||
return { m_values[0], m_values[1], m_values[2], m_values[3] };
|
||||
}
|
||||
|
||||
void QskGradient::setRadialAsList( const QVector< qreal >& params )
|
||||
{
|
||||
Q_ASSERT( params.size() == 3 );
|
||||
|
||||
m_type = Radial;
|
||||
|
||||
m_values[0] = params[0];
|
||||
m_values[1] = params[1];
|
||||
m_values[2] = params[2];
|
||||
m_values[3] = 0.0;
|
||||
}
|
||||
|
||||
QVector< qreal > QskGradient::radialAsList() const
|
||||
{
|
||||
if ( m_type != Radial )
|
||||
return { 0.5, 0.5, 0.0 };
|
||||
|
||||
return { m_values[0], m_values[1], m_values[2] };
|
||||
}
|
||||
|
||||
void QskGradient::setConicAsList( const QVector< qreal >& params )
|
||||
{
|
||||
Q_ASSERT( params.size() >= 2 && params.size() <= 4 );
|
||||
|
||||
m_type = Conic;
|
||||
|
||||
m_values[0] = params[0];
|
||||
m_values[1] = params[1];
|
||||
|
||||
if ( params.size() > 2 )
|
||||
m_values[2] = params[2];
|
||||
else
|
||||
m_values[2] = 0.0;
|
||||
|
||||
if ( params.size() == 4 )
|
||||
m_values[3] = params[3];
|
||||
else
|
||||
m_values[2] = 360.0;
|
||||
}
|
||||
|
||||
QVector< qreal > QskGradient::conicAsList() const
|
||||
{
|
||||
if ( m_type != Conic )
|
||||
return { 0.5, 0.5, 0.0, 0.0 };
|
||||
|
||||
return { m_values[0], m_values[1], m_values[2], m_values[3] };
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
||||
#include <qdebug.h>
|
||||
|
@ -28,6 +28,10 @@ class QSK_EXPORT QskGradient
|
||||
|
||||
Q_PROPERTY( Type type READ type )
|
||||
|
||||
Q_PROPERTY( QskLinearDirection linear READ linearDirection WRITE setLinearDirection )
|
||||
Q_PROPERTY( QskConicDirection conic READ conicDirection WRITE setConicDirection )
|
||||
Q_PROPERTY( QskRadialDirection radial READ radialDirection WRITE setRadialDirection )
|
||||
|
||||
Q_PROPERTY( QVector< QskGradientStop > stops READ stops WRITE setStops )
|
||||
|
||||
Q_PROPERTY( bool valid READ isValid )
|
||||
@ -134,27 +138,6 @@ class QSK_EXPORT QskGradient
|
||||
private:
|
||||
void updateStatusBits() const;
|
||||
|
||||
private:
|
||||
|
||||
#if 1
|
||||
Q_PROPERTY( QVector< qreal > linear READ linearAsList WRITE setLinearAsList )
|
||||
Q_PROPERTY( QVector< qreal > conic READ conicAsList WRITE setConicAsList )
|
||||
Q_PROPERTY( QVector< qreal > radial READ radialAsList WRITE setRadialAsList )
|
||||
#else
|
||||
Q_PROPERTY( QskLinearDirection linear READ linearDirection WRITE setLinearDirection )
|
||||
Q_PROPERTY( QskConicDirection conic READ conicDirection WRITE setConicDirection )
|
||||
Q_PROPERTY( QskRadialDirection radial READ radialDirection WRITE setRadialDirection )
|
||||
#endif
|
||||
|
||||
QVector< qreal > linearAsList() const;
|
||||
void setLinearAsList( const QVector< qreal >& );
|
||||
|
||||
QVector< qreal > radialAsList() const;
|
||||
void setRadialAsList( const QVector< qreal >& );
|
||||
|
||||
QVector< qreal > conicAsList() const;
|
||||
void setConicAsList( const QVector< qreal >& );
|
||||
|
||||
private:
|
||||
QVector< QskGradientStop > m_stops;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user