QML registration using templates instead of macros. lower/uppercase
definitions for gadgets solved ( defining then twice to have the enums with uppercase prefix )
This commit is contained in:
parent
2aaaa4ecb1
commit
ea8f426d67
|
@ -53,116 +53,128 @@
|
||||||
#include <qqmlengine.h>
|
#include <qqmlengine.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 )
|
||||||
QSK_QT_PRIVATE_BEGIN
|
QSK_QT_PRIVATE_BEGIN
|
||||||
#include <private/qqmlmetatype_p.h>
|
#include <private/qqmlmetatype_p.h>
|
||||||
QSK_QT_PRIVATE_END
|
QSK_QT_PRIVATE_END
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#define QSK_MODULE_NAME "Skinny"
|
#define QSK_MODULE_NAME "Skinny"
|
||||||
#define QSK_VERSION_MAJOR 1
|
#define QSK_VERSION_MAJOR 1
|
||||||
#define QSK_VERSION_MINOR 0
|
#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
|
// Required for QFlags to be constructed from an enum value
|
||||||
#define QSK_REGISTER_FLAGS( Type ) \
|
#define QSK_REGISTER_FLAGS( Type ) \
|
||||||
QMetaType::registerConverter< int, Type >([] ( int value ) { return Type( value ); })
|
QMetaType::registerConverter< int, Type >( []( int value ) { return Type( value ); } )
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template < typename T >
|
inline const char* classNameQml( const QMetaObject& metaObject )
|
||||||
inline int registerType( const char *qmlName )
|
|
||||||
{
|
{
|
||||||
return qmlRegisterType< T >( QSK_MODULE_NAME,
|
// without the "Qsk" prefix
|
||||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, qmlName );
|
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,
|
return qmlRegisterType< T >(
|
||||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, qmlName, QString() );
|
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,
|
return qmlRegisterUncreatableType< T >(
|
||||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, qmlName, QString() );
|
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 )
|
#if QT_VERSION < QT_VERSION_CHECK( 5, 14, 0 )
|
||||||
template < typename T >
|
|
||||||
inline int registerSingleton( const char *typeName, QObject* singleton )
|
|
||||||
{
|
|
||||||
auto callback =
|
auto callback =
|
||||||
[] ( QQmlEngine*, QJSEngine* )
|
[]( QQmlEngine*, QJSEngine* )
|
||||||
{
|
{
|
||||||
QQmlEngine::setObjectOwnership( singleton, QQmlEngine::CppOwnership );
|
QQmlEngine::setObjectOwnership( singleton, QQmlEngine::CppOwnership );
|
||||||
return singleton;
|
return singleton;
|
||||||
};
|
};
|
||||||
|
|
||||||
return qmlRegisterSingletonType< T >( QSK_MODULE_NAME,
|
return qmlRegisterSingletonType< T >( QSK_MODULE_NAME,
|
||||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, typeName, callback );
|
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, callback );
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
template < typename T >
|
|
||||||
inline int registerSingleton( const char *typeName, QObject* singleton )
|
|
||||||
{
|
|
||||||
return qmlRegisterSingletonInstance( QSK_MODULE_NAME,
|
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 <qloggingcategory.h>
|
|
||||||
|
|
||||||
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 )
|
static inline QskGradientStop qskJSToGradientStop( const QJSValue& value )
|
||||||
{
|
{
|
||||||
return QskGradientStop(
|
return QskGradientStop(
|
||||||
|
@ -183,44 +195,47 @@ void QskQml::registerTypes()
|
||||||
qmlRegisterUncreatableType< QskSkin >( QSK_MODULE_NAME, 1, 0, "Skin", QString() );
|
qmlRegisterUncreatableType< QskSkin >( QSK_MODULE_NAME, 1, 0, "Skin", QString() );
|
||||||
qRegisterMetaType< QskSkin* >();
|
qRegisterMetaType< QskSkin* >();
|
||||||
|
|
||||||
QSK_REGISTER( QskMain, "Main" );
|
registerObject< QskMain >();
|
||||||
QSK_REGISTER( QskShortcutQml, "Shortcut" );
|
registerObject< QskShortcutQml >( "Shortcut" );
|
||||||
|
|
||||||
QSK_REGISTER( QskWindow, "Window" );
|
registerObject< QskWindow >();
|
||||||
|
|
||||||
QSK_REGISTER( QskDialogWindow, "DialogWindow" );
|
registerObject< QskDialogWindow >();
|
||||||
QSK_REGISTER( QskMessageWindow, "MessageWindow" );
|
registerObject< QskMessageWindow >();
|
||||||
QSK_REGISTER( QskSelectionWindow, "SelectionWindow" );
|
registerObject< QskSelectionWindow >();
|
||||||
|
|
||||||
QSK_REGISTER( QskGridBoxQml, "GridBox" );
|
registerObject< QskGridBoxQml >( "GridBox" );
|
||||||
QSK_REGISTER( QskLinearBoxQml, "LinearBox" );
|
registerObject< QskLinearBoxQml >( "LinearBox" );
|
||||||
|
|
||||||
QSK_REGISTER( QskControl, "Control" );
|
registerObject< QskControl >();
|
||||||
QSK_REGISTER( QskGraphicLabel, "GraphicLabel" );
|
registerObject< QskGraphicLabel >();
|
||||||
QSK_REGISTER( QskVirtualKeyboard, "VirtualKeyboard" );
|
registerObject< QskVirtualKeyboard >();
|
||||||
QSK_REGISTER( QskTextLabel, "TextLabel" );
|
registerObject< QskTextLabel >();
|
||||||
QSK_REGISTER( QskTabButton, "TabButton" );
|
registerObject< QskTabButton >();
|
||||||
QSK_REGISTER( QskTabBar, "TabBar" );
|
registerObject< QskTabBar >();
|
||||||
QSK_REGISTER( QskTabView, "TabView" );
|
registerObject< QskTabView >();
|
||||||
QSK_REGISTER( QskFocusIndicator, "FocusIndicator" );
|
registerObject< QskFocusIndicator >();
|
||||||
QSK_REGISTER( QskSeparator, "Separator" );
|
registerObject< QskSeparator >();
|
||||||
QSK_REGISTER( QskProgressBar, "ProgressBar" );
|
registerObject< QskProgressBar >();
|
||||||
QSK_REGISTER( QskPushButton, "PushButton" );
|
registerObject< QskPushButton >();
|
||||||
QSK_REGISTER( QskScrollView, "ScrollView" );
|
registerObject< QskScrollView >();
|
||||||
QSK_REGISTER( QskScrollArea, "ScrollArea" );
|
registerObject< QskScrollArea >();
|
||||||
QSK_REGISTER( QskSlider, "Slider" );
|
registerObject< QskSlider >();
|
||||||
QSK_REGISTER( QskSimpleListBox, "SimpleListBox" );
|
registerObject< QskSimpleListBox >();
|
||||||
QSK_REGISTER( QskDialogButton, "DialogButton" );
|
registerObject< QskDialogButton >();
|
||||||
QSK_REGISTER( QskDialogButtonBox, "DialogButtonBox" );
|
registerObject< QskDialogButtonBox >();
|
||||||
QSK_REGISTER( QskPopup, "Popup" );
|
registerObject< QskPopup >();
|
||||||
QSK_REGISTER( QskStatusIndicator, "StatusIndicator" );
|
registerObject< QskStatusIndicator >();
|
||||||
QSK_REGISTER( QskSubWindow, "SubWindow" );
|
registerObject< QskSubWindow >();
|
||||||
QSK_REGISTER( QskSubWindowArea, "SubWindowArea" );
|
registerObject< QskSubWindowArea >();
|
||||||
QSK_REGISTER( QskDialogSubWindow, "DialogSubWindow" );
|
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::UpdateFlag );
|
||||||
QSK_REGISTER_FLAGS( QskQuickItem::UpdateFlags );
|
QSK_REGISTER_FLAGS( QskQuickItem::UpdateFlags );
|
||||||
|
@ -228,37 +243,21 @@ void QskQml::registerTypes()
|
||||||
|
|
||||||
QSK_REGISTER_FLAGS( QskDialog::Actions );
|
QSK_REGISTER_FLAGS( QskDialog::Actions );
|
||||||
|
|
||||||
{
|
registerGadget< QskBoxBorderMetrics >();
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
registerGadget< QskBoxShapeMetrics >();
|
||||||
/*
|
registerGadget< QskShadowMetrics >();
|
||||||
The QML engine warns about registering uncreatables with names starting with
|
registerGadget< QskIntervalF >();
|
||||||
a capital letter. But as those classes usually appear only as scope for
|
registerGadget< QskLayoutMetrics >();
|
||||||
local enums in QML, we do want to have capitals. f.e.:
|
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
|
registerNamespace( QskStandardSymbol::staticMetaObject );
|
||||||
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" );
|
|
||||||
|
|
||||||
QMetaType::registerConverter< QJSValue, QskGradientStop >( qskJSToGradientStop );
|
QMetaType::registerConverter< QJSValue, QskGradientStop >( qskJSToGradientStop );
|
||||||
|
|
||||||
|
|
|
@ -142,8 +142,10 @@ class QSK_EXPORT QskGradient
|
||||||
Couldn't find a way how to assign a struct to another struct
|
Couldn't find a way how to assign a struct to another struct
|
||||||
that is used as proprty from QML without creating extra QObjects.
|
that is used as proprty from QML without creating extra QObjects.
|
||||||
So for the moment we are using lists, that are more
|
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
|
error prone and less intuitive.
|
||||||
the QML system being capable of this. TODO ...
|
|
||||||
|
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 > linear READ linearAsList WRITE setLinearAsList )
|
||||||
Q_PROPERTY( QVector< qreal > conic READ conicAsList WRITE setConicAsList )
|
Q_PROPERTY( QVector< qreal > conic READ conicAsList WRITE setConicAsList )
|
||||||
|
|
Loading…
Reference in New Issue