QJSValue converter for QskGradient added to be compatible with new Qt

6.5 features
This commit is contained in:
Uwe Rathmann 2022-11-30 17:05:37 +01:00
parent 57c25294c4
commit abf325dbde
6 changed files with 408 additions and 367 deletions

View File

@ -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
{

View File

@ -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
View 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

View File

@ -6,6 +6,9 @@ CONFIG += qskinny
contains(QSK_CONFIG, QskDll): DEFINES += QSK_QML_MAKEDLL
HEADERS += \
QskQml.hpp
HEADERS += \
QskQmlGlobal.h \
QskShortcutQml.h \

View File

@ -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>

View File

@ -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;