diff --git a/qmlexport/QskQml.cpp b/qmlexport/QskQml.cpp index daac2815..509d3a79 100644 --- a/qmlexport/QskQml.cpp +++ b/qmlexport/QskQml.cpp @@ -53,116 +53,128 @@ #include #endif +#if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 ) QSK_QT_PRIVATE_BEGIN #include QSK_QT_PRIVATE_END +#endif + +#include #define QSK_MODULE_NAME "Skinny" #define QSK_VERSION_MAJOR 1 #define QSK_VERSION_MINOR 0 -#define QSK_REGISTER( className, typeName ) \ - registerType< className >( typeName ); - -#define QSK_REGISTER_GADGET( className, typeName ) \ - registerGadget< className >( typeName ) - -#define QSK_REGISTER_NAMESPACE( className, typeName ) \ - registerStaticMetaObject( className::staticMetaObject, typeName ) - -#define QSK_REGISTER_SINGLETON( className, typeName, singleton ) \ - registerSingleton< className >( typeName, singleton ); - // Required for QFlags to be constructed from an enum value #define QSK_REGISTER_FLAGS( Type ) \ - QMetaType::registerConverter< int, Type >([] ( int value ) { return Type( value ); }) + QMetaType::registerConverter< int, Type >( []( int value ) { return Type( value ); } ) namespace { - template < typename T > - inline int registerType( const char *qmlName ) + inline const char* classNameQml( const QMetaObject& metaObject ) { - return qmlRegisterType< T >( QSK_MODULE_NAME, - QSK_VERSION_MAJOR, QSK_VERSION_MINOR, qmlName ); + // without the "Qsk" prefix + return metaObject.className() + 3; } - template < typename T > - inline int registerGadget( const char *qmlName ) + /* + There are several undocumented methods for QML registrations in qqml.h + f.e qmlRegisterCustomType, where you can pass your own parser. TODO .. + */ + + template< typename T > + inline int registerType( const char* qmlName ) { - return qmlRegisterUncreatableType< T >( QSK_MODULE_NAME, - QSK_VERSION_MAJOR, QSK_VERSION_MINOR, qmlName, QString() ); + return qmlRegisterType< T >( + QSK_MODULE_NAME, QSK_VERSION_MAJOR, QSK_VERSION_MINOR, + qmlName ); } - inline int registerStaticMetaObject( const QMetaObject &metaObject, const char *qmlName ) + template< typename T > + inline int registerUncreatableType( const char* qmlName ) { - return qmlRegisterUncreatableMetaObject( metaObject, QSK_MODULE_NAME, - QSK_VERSION_MAJOR, QSK_VERSION_MINOR, qmlName, QString() ); + return qmlRegisterUncreatableType< T >( + QSK_MODULE_NAME, QSK_VERSION_MAJOR, QSK_VERSION_MINOR, + qmlName, QString() ); } + int registerUncreatableMetaObject( + const QMetaObject& staticMetaObject, const char* qmlName ) + { + return qmlRegisterUncreatableMetaObject( + staticMetaObject, + QSK_MODULE_NAME, QSK_VERSION_MAJOR, QSK_VERSION_MINOR, + qmlName, QString() ); + } + + 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 + // the class name without the "Qsk" prefix + + /* + 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 ... + */ + 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 ) - template < typename T > - inline int registerSingleton( const char *typeName, QObject* singleton ) - { auto callback = - [] ( QQmlEngine*, QJSEngine* ) + []( QQmlEngine*, QJSEngine* ) { QQmlEngine::setObjectOwnership( singleton, QQmlEngine::CppOwnership ); return singleton; }; return qmlRegisterSingletonType< T >( QSK_MODULE_NAME, - QSK_VERSION_MAJOR, QSK_VERSION_MINOR, typeName, callback ); - } + QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, callback ); #else - template < typename T > - inline int registerSingleton( const char *typeName, QObject* singleton ) - { return qmlRegisterSingletonInstance( QSK_MODULE_NAME, - QSK_VERSION_MAJOR, QSK_VERSION_MINOR, typeName, singleton ); + QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, singleton ); +#endif } -#endif } -#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) - -#include - -namespace -{ - class WarningBlocker - { - public: - WarningBlocker() - { - m_oldFilter = QLoggingCategory::installFilter( &WarningBlocker::filter ); - } - - ~WarningBlocker() - { - QLoggingCategory::installFilter( m_oldFilter ); - } - - private: - - static void filter( QLoggingCategory* category ) - { - if ( qstrcmp( category->categoryName(), "qt.qml.typeregistration" ) == 0 ) - { - category->setEnabled( QtWarningMsg, false); - return; - } - - m_oldFilter(category); - } - - static QLoggingCategory::CategoryFilter m_oldFilter; - }; - - QLoggingCategory::CategoryFilter WarningBlocker::m_oldFilter; -} - -#endif - static inline QskGradientStop qskJSToGradientStop( const QJSValue& value ) { return QskGradientStop( @@ -183,44 +195,47 @@ void QskQml::registerTypes() qmlRegisterUncreatableType< QskSkin >( QSK_MODULE_NAME, 1, 0, "Skin", QString() ); qRegisterMetaType< QskSkin* >(); - QSK_REGISTER( QskMain, "Main" ); - QSK_REGISTER( QskShortcutQml, "Shortcut" ); + registerObject< QskMain >(); + registerObject< QskShortcutQml >( "Shortcut" ); - QSK_REGISTER( QskWindow, "Window" ); + registerObject< QskWindow >(); - QSK_REGISTER( QskDialogWindow, "DialogWindow" ); - QSK_REGISTER( QskMessageWindow, "MessageWindow" ); - QSK_REGISTER( QskSelectionWindow, "SelectionWindow" ); + registerObject< QskDialogWindow >(); + registerObject< QskMessageWindow >(); + registerObject< QskSelectionWindow >(); - QSK_REGISTER( QskGridBoxQml, "GridBox" ); - QSK_REGISTER( QskLinearBoxQml, "LinearBox" ); + registerObject< QskGridBoxQml >( "GridBox" ); + registerObject< QskLinearBoxQml >( "LinearBox" ); - QSK_REGISTER( QskControl, "Control" ); - QSK_REGISTER( QskGraphicLabel, "GraphicLabel" ); - QSK_REGISTER( QskVirtualKeyboard, "VirtualKeyboard" ); - QSK_REGISTER( QskTextLabel, "TextLabel" ); - QSK_REGISTER( QskTabButton, "TabButton" ); - QSK_REGISTER( QskTabBar, "TabBar" ); - QSK_REGISTER( QskTabView, "TabView" ); - QSK_REGISTER( QskFocusIndicator, "FocusIndicator" ); - QSK_REGISTER( QskSeparator, "Separator" ); - QSK_REGISTER( QskProgressBar, "ProgressBar" ); - QSK_REGISTER( QskPushButton, "PushButton" ); - QSK_REGISTER( QskScrollView, "ScrollView" ); - QSK_REGISTER( QskScrollArea, "ScrollArea" ); - QSK_REGISTER( QskSlider, "Slider" ); - QSK_REGISTER( QskSimpleListBox, "SimpleListBox" ); - QSK_REGISTER( QskDialogButton, "DialogButton" ); - QSK_REGISTER( QskDialogButtonBox, "DialogButtonBox" ); - QSK_REGISTER( QskPopup, "Popup" ); - QSK_REGISTER( QskStatusIndicator, "StatusIndicator" ); - QSK_REGISTER( QskSubWindow, "SubWindow" ); - QSK_REGISTER( QskSubWindowArea, "SubWindowArea" ); - QSK_REGISTER( QskDialogSubWindow, "DialogSubWindow" ); + registerObject< QskControl >(); + registerObject< QskGraphicLabel >(); + registerObject< QskVirtualKeyboard >(); + registerObject< QskTextLabel >(); + registerObject< QskTabButton >(); + registerObject< QskTabBar >(); + registerObject< QskTabView >(); + registerObject< QskFocusIndicator >(); + registerObject< QskSeparator >(); + registerObject< QskProgressBar >(); + registerObject< QskPushButton >(); + registerObject< QskScrollView >(); + registerObject< QskScrollArea >(); + registerObject< QskSlider >(); + registerObject< QskSimpleListBox >(); + registerObject< QskDialogButton >(); + registerObject< QskDialogButtonBox >(); + registerObject< QskPopup >(); + registerObject< QskStatusIndicator >(); + registerObject< QskSubWindow >(); + registerObject< QskSubWindowArea >(); + registerObject< QskDialogSubWindow >(); - QSK_REGISTER_SINGLETON( QskDialog, "Dialog", QskDialog::instance() ); + registerSingleton< QskDialog >( QskDialog::instance() ); - qmlRegisterUncreatableType< QskSkin >( "Skinny.Skins", 1, 0, "Skin", QString() ); +#if 0 + qmlRegisterUncreatableType< QskSkin >( "Skinny.Skins", + QSK_VERSION_MAJOR, QSK_VERSION_MINOR, "Skin", QString() ); +#endif QSK_REGISTER_FLAGS( QskQuickItem::UpdateFlag ); QSK_REGISTER_FLAGS( QskQuickItem::UpdateFlags ); @@ -228,37 +243,21 @@ void QskQml::registerTypes() QSK_REGISTER_FLAGS( QskDialog::Actions ); - { -#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) - /* - The QML engine warns about registering uncreatables with names starting with - a capital letter. But as those classes usually appear only as scope for - local enums in QML, we do want to have capitals. f.e.: + registerGadget< QskBoxBorderMetrics >(); + registerGadget< QskBoxShapeMetrics >(); + registerGadget< QskShadowMetrics >(); + registerGadget< QskIntervalF >(); + registerGadget< QskLayoutMetrics >(); + registerGadget< QskMargins >(); - - "policy.horizonalPolicy : SizePolicy::Minimum". + registerGadget< QskAspect >(); + registerGadget< QskGradient >(); + registerGadget< QskGradientStop >(); + registerGadget< QskPlacementPolicy >(); + registerGadget< QskSizePolicy >(); + registerGadget< QskTextOptions >(); - Maybe we need to introduce some dummy gadgets exposing the enums - in capital letters by using QML_FOREIGN_NAMESPACE, while the - original gadget is exposed in lower letters. TODO ... - */ - WarningBlocker warningBlocker; -#endif - - QSK_REGISTER_GADGET( QskBoxBorderMetrics, "BorderMetrics" ); - QSK_REGISTER_GADGET( QskBoxShapeMetrics, "Shape" ); - QSK_REGISTER_GADGET( QskShadowMetrics, "ShadowMetrics" ); - QSK_REGISTER_GADGET( QskGradient, "Gradient" ); - QSK_REGISTER_GADGET( QskGradientStop, "GradientStop" ); - QSK_REGISTER_GADGET( QskPlacementPolicy, "PlacementPolicy" ); - QSK_REGISTER_GADGET( QskIntervalF, "IntervalF" ); - QSK_REGISTER_GADGET( QskLayoutMetrics, "LayoutMetrics" ); - QSK_REGISTER_GADGET( QskSizePolicy, "SizePolicy" ); - QSK_REGISTER_GADGET( QskTextOptions, "TextOptions" ); - QSK_REGISTER_GADGET( QskMargins, "Margins" ); - QSK_REGISTER_GADGET( QskAspect, "Aspect" ); - } - - QSK_REGISTER_NAMESPACE( QskStandardSymbol, "StandardSymbol" ); + registerNamespace( QskStandardSymbol::staticMetaObject ); QMetaType::registerConverter< QJSValue, QskGradientStop >( qskJSToGradientStop ); diff --git a/src/common/QskGradient.h b/src/common/QskGradient.h index 47a655f8..42c32f60 100644 --- a/src/common/QskGradient.h +++ b/src/common/QskGradient.h @@ -142,8 +142,10 @@ class QSK_EXPORT QskGradient Couldn't find a way how to assign a struct to another struct that is used as proprty from QML without creating extra QObjects. So for the moment we are using lists, that are more - error prone and less intuitive. Let's see if some day we will have - the QML system being capable of this. TODO ... + error prone and less intuitive. + + Maybe we can do something better using qmlRegisterCustomType, where we + can register our own QQmlCustomParser. TODO ... */ Q_PROPERTY( QVector< qreal > linear READ linearAsList WRITE setLinearAsList ) Q_PROPERTY( QVector< qreal > conic READ conicAsList WRITE setConicAsList )