questionable shadow class removed, using QQmlPrivate::RegisterType
again. Qt5 is using public APIs only - too many #ifdefs otherwise
This commit is contained in:
parent
5ecb85c725
commit
2b629123f9
|
@ -3,16 +3,25 @@
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
set(HEADERS
|
list(APPEND HEADERS
|
||||||
QskQmlGlobal.h
|
QskQmlGlobal.h
|
||||||
QskShortcutQml.h
|
QskShortcutQml.h
|
||||||
QskLayoutQml.h
|
QskLayoutQml.h
|
||||||
QskQml.h)
|
QskQmlModule.h
|
||||||
|
QskQmlRegister.h
|
||||||
|
QskQml.h
|
||||||
|
)
|
||||||
|
|
||||||
set(SOURCES
|
list(APPEND SOURCES
|
||||||
QskShortcutQml.cpp
|
QskShortcutQml.cpp
|
||||||
QskLayoutQml.cpp
|
QskLayoutQml.cpp
|
||||||
QskQml.cpp)
|
QskQml.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if (QT_VERSION_MAJOR GREATER_EQUAL 6)
|
||||||
|
list(APPEND HEADERS QskQmlClassInfo.h)
|
||||||
|
list(APPEND SOURCES QskQmlClassInfo.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(target qskqmlexport)
|
set(target qskqmlexport)
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskQml.h"
|
#include "QskQml.h"
|
||||||
#include "QskQml.hpp"
|
|
||||||
|
|
||||||
|
#include "QskQmlRegister.h"
|
||||||
#include "QskLayoutQml.h"
|
#include "QskLayoutQml.h"
|
||||||
#include "QskShortcutQml.h"
|
#include "QskShortcutQml.h"
|
||||||
|
|
||||||
|
@ -44,8 +44,6 @@
|
||||||
#include <QskSeparator.h>
|
#include <QskSeparator.h>
|
||||||
#include <QskShadowMetrics.h>
|
#include <QskShadowMetrics.h>
|
||||||
#include <QskSimpleListBox.h>
|
#include <QskSimpleListBox.h>
|
||||||
#include <QskSkin.h>
|
|
||||||
#include <QskSkinManager.h>
|
|
||||||
#include <QskSlider.h>
|
#include <QskSlider.h>
|
||||||
#include <QskSpinBox.h>
|
#include <QskSpinBox.h>
|
||||||
#include <QskStandardSymbol.h>
|
#include <QskStandardSymbol.h>
|
||||||
|
@ -61,9 +59,9 @@
|
||||||
#include <QskWindow.h>
|
#include <QskWindow.h>
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 2, 0 )
|
#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
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 5, 0 )
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 5, 0 )
|
||||||
|
@ -191,9 +189,6 @@ namespace
|
||||||
|
|
||||||
void QskQml::registerTypes()
|
void QskQml::registerTypes()
|
||||||
{
|
{
|
||||||
qmlRegisterUncreatableType< QskSkin >( QSK_MODULE_NAME, 1, 0, "Skin", QString() );
|
|
||||||
qRegisterMetaType< QskSkin* >();
|
|
||||||
|
|
||||||
registerObject< QskShortcutQml >( "Shortcut" );
|
registerObject< QskShortcutQml >( "Shortcut" );
|
||||||
|
|
||||||
registerObject< QskWindow >();
|
registerObject< QskWindow >();
|
||||||
|
|
|
@ -1,288 +0,0 @@
|
||||||
/******************************************************************************
|
|
||||||
* QSkinny - Copyright (C) The authors
|
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QSK_QML_HPP
|
|
||||||
#define QSK_QML_HPP
|
|
||||||
|
|
||||||
#include <qqml.h>
|
|
||||||
#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;
|
|
||||||
|
|
||||||
constexpr bool isObject = std::is_base_of_v< QObject, T >;
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
|
||||||
typeId = qMetaTypeId< T* >( );
|
|
||||||
#else
|
|
||||||
if ( isObject )
|
|
||||||
typeId = QMetaType::fromType< T* >();
|
|
||||||
else
|
|
||||||
typeId = QMetaType::fromType< T >();
|
|
||||||
|
|
||||||
createValueType = ValueType< T, void >::create;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
For the moment we do not export lists - QMetaType::fromType< QList< T > >()
|
|
||||||
creates so many symbols, that we would have to enable -mbig-obj for mingw
|
|
||||||
TODO ...
|
|
||||||
*/
|
|
||||||
#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';
|
|
||||||
|
|
||||||
listId = qRegisterNormalizedMetaType< QQmlListProperty< T > >( listName.constData() );
|
|
||||||
#else
|
|
||||||
if ( isObject );
|
|
||||||
listId = QMetaType::fromType< QQmlListProperty< T > >( );
|
|
||||||
else
|
|
||||||
listId = QMetaType::fromType< QList< T > >( );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline 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 );
|
|
||||||
|
|
||||||
return qmlRegisterSingletonInstance( QSK_MODULE_NAME,
|
|
||||||
QSK_VERSION_MAJOR, QSK_VERSION_MINOR, name, singleton );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "QskQmlClassInfo.h"
|
||||||
|
#include "QskQmlModule.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace QskQml;
|
||||||
|
|
||||||
|
ClassInfo::ClassInfo( const char* qmlName, const QMetaObject* metaObject )
|
||||||
|
{
|
||||||
|
m_info.structVersion = QSK_STRUCT_VERSION;
|
||||||
|
|
||||||
|
m_info.objectSize = 0;
|
||||||
|
m_info.create = nullptr;
|
||||||
|
m_info.userdata = nullptr; // unused
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 ...
|
||||||
|
*/
|
||||||
|
m_info.createValueType = nullptr;
|
||||||
|
|
||||||
|
m_info.uri = QskQmlModule::name;
|
||||||
|
m_info.version = QTypeRevision::fromVersion( QskQmlModule::name[0], QskQmlModule::name[1] );
|
||||||
|
|
||||||
|
m_info.elementName = qmlName;
|
||||||
|
m_info.metaObject = metaObject;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We do not use attached properties as it always comes with
|
||||||
|
creating extra QObjects.
|
||||||
|
*/
|
||||||
|
m_info.attachedPropertiesFunction = nullptr;
|
||||||
|
m_info.attachedPropertiesMetaObject = nullptr;
|
||||||
|
|
||||||
|
m_info.parserStatusCast = m_info.valueSourceCast = m_info.valueInterceptorCast = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We do not use extensions as it always comes with
|
||||||
|
creating extra QObjects.
|
||||||
|
*/
|
||||||
|
m_info.extensionObjectCreate = nullptr;
|
||||||
|
m_info.extensionMetaObject = nullptr;
|
||||||
|
|
||||||
|
m_info.customParser = nullptr; // QQmlCustomParser, unused
|
||||||
|
|
||||||
|
m_info.revision = QTypeRevision::zero();
|
||||||
|
m_info.finalizerCast = -1;
|
||||||
|
|
||||||
|
m_info.creationMethod = QQmlPrivate::ValueTypeCreationMethod::Structured;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray ClassInfo::normalizedListName(
|
||||||
|
const char* containerName, const QMetaObject& metaObject )
|
||||||
|
{
|
||||||
|
static QByteArray name;
|
||||||
|
name.reserve( 256 );
|
||||||
|
|
||||||
|
const int length1 = strlen( containerName );
|
||||||
|
const int length2 = strlen( metaObject.className() );
|
||||||
|
|
||||||
|
name.resize( length1 + length2 + 3 );
|
||||||
|
|
||||||
|
auto p = name.data();
|
||||||
|
|
||||||
|
memcpy( p, containerName, size_t( length1 ) );
|
||||||
|
p += length1;
|
||||||
|
|
||||||
|
*p++ = '<';
|
||||||
|
|
||||||
|
memcpy( p, metaObject.className(), size_t( length2 ) );
|
||||||
|
p += length2;
|
||||||
|
|
||||||
|
*p++ = '>';
|
||||||
|
*p++ = '\0';
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_QML_CLASSINFO_H
|
||||||
|
#define QSK_QML_CLASSINFO_H
|
||||||
|
|
||||||
|
#include <qqml.h>
|
||||||
|
|
||||||
|
class QByteArray;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
namespace QskQml
|
||||||
|
{
|
||||||
|
class ClassInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClassInfo( const char* qmlName, const QMetaObject* );
|
||||||
|
template< typename T > void setTypeInfo();
|
||||||
|
|
||||||
|
int registerType();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static QByteArray normalizedListName(
|
||||||
|
const char* containerName, const QMetaObject& );
|
||||||
|
|
||||||
|
QQmlPrivate::RegisterType m_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
inline void ClassInfo::setTypeInfo()
|
||||||
|
{
|
||||||
|
using namespace QQmlPrivate;
|
||||||
|
|
||||||
|
constexpr bool isObject = std::is_base_of_v< QObject, T >;
|
||||||
|
|
||||||
|
if ( isObject )
|
||||||
|
m_info.typeId = QMetaType::fromType< T* >();
|
||||||
|
else
|
||||||
|
m_info.typeId = QMetaType::fromType< T >();
|
||||||
|
|
||||||
|
m_info.objectSize = sizeof( T );
|
||||||
|
m_info.create = Constructors< T >::createInto;
|
||||||
|
|
||||||
|
m_info.createValueType = ValueType< T, void >::create;
|
||||||
|
|
||||||
|
const auto name = normalizedListName(
|
||||||
|
isObject ? "QQmlListProperty" : "QList", T::staticMetaObject );
|
||||||
|
|
||||||
|
/*
|
||||||
|
QMetaType::fromType< QList< T >() creates a lot of symbols
|
||||||
|
that end up in QskQml.o for all gadgets. So we export only
|
||||||
|
registered lists. Registration might be done in the qskinny library
|
||||||
|
itself - or in QskQml.cpp.
|
||||||
|
|
||||||
|
As we do not design plain data being a QObject I'm not sure
|
||||||
|
if we need to have QQmlListProperty< T > at all ...
|
||||||
|
*/
|
||||||
|
m_info.listId = QMetaType::fromName( name.constData() );
|
||||||
|
|
||||||
|
m_info.parserStatusCast = StaticCastSelector< T, QQmlParserStatus >::cast();
|
||||||
|
m_info.valueSourceCast = StaticCastSelector< T, QQmlPropertyValueSource >::cast();
|
||||||
|
m_info.valueInterceptorCast = StaticCastSelector< T, QQmlPropertyValueInterceptor >::cast();
|
||||||
|
|
||||||
|
#if QSK_STRUCT_VERSION >= 1
|
||||||
|
m_info.finalizerCast = StaticCastSelector< T, QQmlFinalizerHook >::cast();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int ClassInfo::registerType()
|
||||||
|
{
|
||||||
|
return qmlregister( QQmlPrivate::TypeRegistration, &m_info );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,17 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_QML_MODULE_H
|
||||||
|
#define QSK_QML_MODULE_H
|
||||||
|
|
||||||
|
namespace QskQmlModule
|
||||||
|
{
|
||||||
|
const char name[] = "Skinny";
|
||||||
|
|
||||||
|
// major, minor
|
||||||
|
const int version[] = { 1, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,131 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) The authors
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef QSK_QML_REGISTER_H
|
||||||
|
#define QSK_QML_REGISTER_H
|
||||||
|
|
||||||
|
#include "QskQmlModule.h"
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
#include "QskQmlClassInfo.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <qqml.h>
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
||||||
|
#define QSK_QML_REGISTER 0
|
||||||
|
#else
|
||||||
|
#define QSK_QML_REGISTER 1
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
inline int registerUncreatableType( const char* qmlName )
|
||||||
|
{
|
||||||
|
#if QSK_QML_REGISTER
|
||||||
|
ClassInfo typeInfo( qmlName, &T::staticMetaObject );
|
||||||
|
typeInfo.setTypeInfo< T >();
|
||||||
|
|
||||||
|
return typeInfo.registerType();
|
||||||
|
#else
|
||||||
|
return qmlRegisterUncreatableType< T >( QskQmlModule::name,
|
||||||
|
QskQmlModule::version[0], QskQmlModule::version[1], qmlName, QString() );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int registerUncreatableMetaObject(
|
||||||
|
const QMetaObject& staticMetaObject, const char* qmlName )
|
||||||
|
{
|
||||||
|
#if QSK_QML_REGISTER
|
||||||
|
ClassInfo typeInfo( qmlName, &staticMetaObject );
|
||||||
|
return typeInfo.registerType();
|
||||||
|
#else
|
||||||
|
return qmlRegisterUncreatableMetaObject( staticMetaObject,
|
||||||
|
QskQmlModule::name, QskQmlModule::version[0], QskQmlModule::version[1],
|
||||||
|
qmlName, QString() );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
inline int registerObject( const char* qmlName = nullptr )
|
||||||
|
{
|
||||||
|
// the class name without the "Qsk" prefix
|
||||||
|
if ( qmlName == nullptr )
|
||||||
|
qmlName = classNameQml( T::staticMetaObject );
|
||||||
|
|
||||||
|
#if QSK_QML_REGISTER
|
||||||
|
ClassInfo typeInfo( qmlName, &T::staticMetaObject );
|
||||||
|
typeInfo.setTypeInfo< T >();
|
||||||
|
|
||||||
|
return typeInfo.registerType();
|
||||||
|
#else
|
||||||
|
return qmlRegisterType< T >( QskQmlModule::name,
|
||||||
|
QskQmlModule::version[0], QskQmlModule::version[1], qmlName );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
inline int registerGadget()
|
||||||
|
{
|
||||||
|
auto className = classNameQml( T::staticMetaObject );
|
||||||
|
|
||||||
|
#if QSK_QML_REGISTER
|
||||||
|
/*
|
||||||
|
According to the QML naming rules uncreatables have to
|
||||||
|
start with a lowercase letter, 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] );
|
||||||
|
|
||||||
|
return registerUncreatableType< T >( name.constData() );
|
||||||
|
#else
|
||||||
|
return registerUncreatableType< T >( className );
|
||||||
|
#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 );
|
||||||
|
|
||||||
|
return qmlRegisterSingletonInstance( QskQmlModule::name,
|
||||||
|
QskQmlModule::version[0], QskQmlModule::version[1], name, singleton );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef QSK_QML_REGISTER
|
||||||
|
#undef QSK_QML_REGISTER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue