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>
|
||||
#endif
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 )
|
||||
QSK_QT_PRIVATE_BEGIN
|
||||
#include <private/qqmlmetatype_p.h>
|
||||
QSK_QT_PRIVATE_END
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#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 <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 )
|
||||
{
|
||||
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 );
|
||||
|
||||
|
@ -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 )
|
||||
|
Loading…
x
Reference in New Issue
Block a user