diff --git a/examples/layouts/layouts.qml b/examples/layouts/layouts.qml index f32286e2..48a4dd2a 100644 --- a/examples/layouts/layouts.qml +++ b/examples/layouts/layouts.qml @@ -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 { diff --git a/qmlexport/QskQml.cpp b/qmlexport/QskQml.cpp index 1e21a800..0b6a0cc2 100644 --- a/qmlexport/QskQml.cpp +++ b/qmlexport/QskQml.cpp @@ -4,6 +4,8 @@ *****************************************************************************/ #include "QskQml.h" +#include "QskQml.hpp" + #include "QskLayoutQml.h" #include "QskShortcutQml.h" #include "QskMainQml.h" @@ -50,301 +52,121 @@ #include #include -#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 ) -#include -#endif - #if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 ) -QSK_QT_PRIVATE_BEGIN -#include -QSK_QT_PRIVATE_END + QSK_QT_PRIVATE_BEGIN + #include + QSK_QT_PRIVATE_END #endif -#include +#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 +#include 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 diff --git a/qmlexport/QskQml.hpp b/qmlexport/QskQml.hpp new file mode 100644 index 00000000..d1576d9d --- /dev/null +++ b/qmlexport/QskQml.hpp @@ -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 + +#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 ) + #include +#endif + +#include + +#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 diff --git a/qmlexport/qmlexport.pro b/qmlexport/qmlexport.pro index 24857af7..12c44dd9 100644 --- a/qmlexport/qmlexport.pro +++ b/qmlexport/qmlexport.pro @@ -6,6 +6,9 @@ CONFIG += qskinny contains(QSK_CONFIG, QskDll): DEFINES += QSK_QML_MAKEDLL +HEADERS += \ + QskQml.hpp + HEADERS += \ QskQmlGlobal.h \ QskShortcutQml.h \ diff --git a/src/common/QskGradient.cpp b/src/common/QskGradient.cpp index 8bf8ef72..027367ae 100644 --- a/src/common/QskGradient.cpp +++ b/src/common/QskGradient.cpp @@ -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 diff --git a/src/common/QskGradient.h b/src/common/QskGradient.h index e400a4e7..26dacfb7 100644 --- a/src/common/QskGradient.h +++ b/src/common/QskGradient.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;