qskinny/qmlexport/QskQml.cpp

355 lines
11 KiB
C++
Raw Normal View History

2017-07-21 16:21:34 +00:00
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
2018-10-04 08:34:44 +00:00
#include "QskQml.h"
2019-05-12 11:54:22 +00:00
#include "QskLayoutQml.h"
#include "QskShortcutQml.h"
#include <QskCorner.h>
#include <QskDialog.h>
#include <QskDialogButton.h>
#include <QskDialogButtonBox.h>
#include <QskDialogSubWindow.h>
#include <QskDialogWindow.h>
#include <QskFocusIndicator.h>
#include <QskGradient.h>
#include <QskGraphicLabel.h>
2020-05-02 09:57:58 +00:00
#include <QskIntervalF.h>
2020-05-02 10:38:44 +00:00
#include <QskLayoutHint.h>
2020-10-28 14:52:55 +00:00
#include <QskMargins.h>
2019-05-12 11:54:22 +00:00
#include <QskMessageWindow.h>
#include <QskPopup.h>
2020-08-01 15:54:31 +00:00
#include <QskProgressBar.h>
2019-05-12 11:54:22 +00:00
#include <QskPushButton.h>
#include <QskRgbValue.h>
#include <QskScrollArea.h>
#include <QskScrollView.h>
#include <QskSelectionWindow.h>
#include <QskSeparator.h>
#include <QskSetup.h>
#include <QskSimpleListBox.h>
#include <QskSkin.h>
#include <QskSkinManager.h>
#include <QskSlider.h>
#include <QskStandardSymbol.h>
#include <QskStatusIndicator.h>
#include <QskSubWindow.h>
#include <QskSubWindowArea.h>
#include <QskTabBar.h>
#include <QskTabButton.h>
#include <QskTabView.h>
#include <QskTextLabel.h>
#include <QskTextOptions.h>
#include <QskVirtualKeyboard.h>
#include <QskWindow.h>
2017-07-21 16:21:34 +00:00
2018-07-19 12:10:48 +00:00
#include <qjsvalueiterator.h>
2018-08-03 06:15:28 +00:00
#include <qstringlist.h>
2017-07-21 16:21:34 +00:00
QSK_QT_PRIVATE_BEGIN
#include <private/qqmlglobal_p.h>
2018-08-03 06:15:28 +00:00
#include <private/qqmlmetatype_p.h>
2017-07-21 16:21:34 +00:00
#include <private/qvariantanimation_p.h>
QSK_QT_PRIVATE_END
#define QSK_MODULE_NAME "Skinny"
#define QSK_REGISTER( className, typeName ) \
qmlRegisterType< className >( QSK_MODULE_NAME, 1, 0, typeName );
#define QSK_REGISTER_GADGET( className, typeName ) \
qRegisterMetaType< className >(); \
qmlRegisterUncreatableType< className >( QSK_MODULE_NAME, 1, 0, typeName, QString() )
// Required for QFlags to be constructed from an enum value
#define QSK_REGISTER_FLAGS( Type ) \
QMetaType::registerConverter< int, Type >([] ( int value ) \
{ return Type( value ); })
#define QSK_REGISTER_SINGLETON( className, typeName, singleton ) \
qmlRegisterSingletonType< className >( QSK_MODULE_NAME, 1, 0, typeName, \
[] ( QQmlEngine*, QJSEngine* ) { return dynamic_cast< QObject* >( singleton ); } )
// Expose values in QskRgbValue to QML
struct QskRgbValue_Gadget
{
2018-08-03 06:15:28 +00:00
enum Enum
{
#define RGB( name, value ) name = value,
QSK_RGB_VALUES
2017-07-21 16:21:34 +00:00
#undef RGB
};
Q_ENUM( Enum )
Q_GADGET
};
// Use this pattern to provide valueOf() to any type, something which is needed
// in JS to convert a variant to a JS value. This would be a template, but moc
// doesn't support template classes.
class QskSetupFlagsProvider : public QskSetup::Flags
{
Q_GADGET
2018-08-03 06:15:28 +00:00
public:
template< typename... Args >
QskSetupFlagsProvider( Args&&... args )
: QskSetup::Flags( std::forward< Args >( args )... )
2017-07-21 16:21:34 +00:00
{
}
Q_INVOKABLE int valueOf() const { return int( *this ); }
};
class QskMain : public QObject
{
2018-08-03 06:15:28 +00:00
public:
2017-07-21 16:21:34 +00:00
Q_OBJECT
Q_PRIVATE_PROPERTY( setup(), QString skin READ skinName
WRITE setSkin NOTIFY skinChanged )
Q_PROPERTY( QStringList skinList READ skinList NOTIFY skinListChanged )
Q_PRIVATE_PROPERTY( setup(), QskSetupFlagsProvider controlFlags
READ controlFlags WRITE setControlFlags NOTIFY controlFlagsChanged )
Q_PROPERTY( QQmlListProperty< QObject > data READ data )
Q_CLASSINFO( "DefaultProperty", "data" )
2018-08-03 06:15:28 +00:00
public:
QskMain( QObject* parent = nullptr )
: QObject( parent )
2017-07-21 16:21:34 +00:00
{
// how to supress warnings about a missing skinListChanged
// as we don't have it ??
connect( setup(), &QskSetup::skinChanged,
this, &QskMain::skinChanged, Qt::QueuedConnection );
2018-04-27 11:48:51 +00:00
2017-07-21 16:21:34 +00:00
connect( setup(), &QskSetup::controlFlagsChanged,
this, &QskMain::controlFlagsChanged, Qt::QueuedConnection );
}
QStringList skinList() const
{
auto manager = QskSkinManager::instance();
return manager ? manager->skinNames() : QStringList();
2017-07-21 16:21:34 +00:00
}
QQmlListProperty< QObject > data()
{
return QQmlListProperty< QObject >(
this, nullptr,
2018-08-03 06:15:28 +00:00
[]( QQmlListProperty< QObject >* property, QObject* value )
2017-07-21 16:21:34 +00:00
{
2020-10-29 06:49:53 +00:00
auto main = static_cast< QskMain* >( property->object );
2017-07-21 16:21:34 +00:00
main->m_data.append( value );
},
2018-08-03 06:15:28 +00:00
[]( QQmlListProperty< QObject >* property )
2017-07-21 16:21:34 +00:00
{
2020-10-29 06:49:53 +00:00
auto main = static_cast< const QskMain* >( property->object );
return static_cast< int >( main->m_data.count() );
2017-07-21 16:21:34 +00:00
},
2018-08-03 06:15:28 +00:00
[]( QQmlListProperty< QObject >* property, int index )
2017-07-21 16:21:34 +00:00
{
2020-10-29 06:49:53 +00:00
auto main = static_cast< const QskMain* >( property->object );
2017-07-21 16:21:34 +00:00
return main->m_data.at( index );
},
2018-08-03 06:15:28 +00:00
[]( QQmlListProperty< QObject >* property )
2017-07-21 16:21:34 +00:00
{
2020-10-29 06:49:53 +00:00
auto main = static_cast< QskMain* >( property->object );
2017-07-21 16:21:34 +00:00
main->m_data.clear();
}
);
}
2018-08-03 06:15:28 +00:00
Q_SIGNALS:
2017-07-21 16:21:34 +00:00
void skinListChanged(); // never emitted
void skinChanged();
void inputPanelChanged();
void controlFlagsChanged();
2018-08-03 06:15:28 +00:00
private:
2017-07-21 16:21:34 +00:00
static inline QskSetup* setup() { return QskSetup::instance(); }
QObjectList m_data;
};
Q_DECLARE_METATYPE( QskSetupFlagsProvider )
2020-10-29 15:45:57 +00:00
#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
2018-10-04 08:34:44 +00:00
void QskQml::registerTypes()
2017-07-21 16:21:34 +00:00
{
qmlRegisterRevision< QQuickItem, 6 >( QSK_MODULE_NAME, 1, 0 );
qmlRegisterUncreatableType< QskSetup >( QSK_MODULE_NAME, 1, 0, "Setup", QString() );
qmlRegisterUncreatableType< QskSkin >( QSK_MODULE_NAME, 1, 0, "Skin", QString() );
qRegisterMetaType< QskSkin* >();
QSK_REGISTER( QskMain, "Main" );
2019-05-12 11:54:22 +00:00
QSK_REGISTER( QskShortcutQml, "Shortcut" );
2017-07-21 16:21:34 +00:00
QSK_REGISTER( QskWindow, "Window" );
QSK_REGISTER( QskDialogWindow, "DialogWindow" );
QSK_REGISTER( QskMessageWindow, "MessageWindow" );
QSK_REGISTER( QskSelectionWindow, "SelectionWindow" );
2019-05-12 11:54:22 +00:00
QSK_REGISTER( QskGridBoxQml, "GridBox" );
QSK_REGISTER( QskLinearBoxQml, "LinearBox" );
2017-07-21 16:21:34 +00:00
QSK_REGISTER( QskControl, "Control" );
QSK_REGISTER( QskGraphicLabel, "GraphicLabel" );
2018-04-04 08:15:59 +00:00
QSK_REGISTER( QskVirtualKeyboard, "VirtualKeyboard" );
2017-07-21 16:21:34 +00:00
QSK_REGISTER( QskTextLabel, "TextLabel" );
QSK_REGISTER( QskTabButton, "TabButton" );
QSK_REGISTER( QskTabBar, "TabBar" );
QSK_REGISTER( QskTabView, "TabView" );
QSK_REGISTER( QskFocusIndicator, "FocusIndicator" );
QSK_REGISTER( QskSeparator, "Separator" );
2020-08-01 15:54:31 +00:00
QSK_REGISTER( QskProgressBar, "ProgressBar" );
2017-07-21 16:21:34 +00:00
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" );
QSK_REGISTER_SINGLETON( QskDialog, "Dialog", QskDialog::instance() );
qmlRegisterUncreatableType< QskSkin >( "Skinny.Skins", 1, 0, "Skin", QString() );
QSK_REGISTER_FLAGS( QskControl::Flag );
QSK_REGISTER_FLAGS( QskControl::Flags );
QSK_REGISTER_FLAGS( QskSetup::Flag );
QSK_REGISTER_FLAGS( QskSetup::Flags );
QSK_REGISTER_FLAGS( QskSizePolicy::Policy );
QMetaType::registerConverter< int, QskSetupFlagsProvider >();
QSK_REGISTER_FLAGS( QskDialog::Actions );
2017-07-21 16:21:34 +00:00
QSK_REGISTER_GADGET( QskRgbValue_Gadget, "RgbValue" );
QSK_REGISTER_GADGET( QskStandardSymbol, "StandardSymbol" );
QSK_REGISTER_GADGET( QskCorner, "Corner" );
QSK_REGISTER_GADGET( QskGradient, "Gradient" );
QSK_REGISTER_GADGET( QskGradientStop, "GradientStop" );
2020-05-02 09:57:58 +00:00
QSK_REGISTER_GADGET( QskIntervalF, "IntervalF" );
2020-05-02 10:38:44 +00:00
QSK_REGISTER_GADGET( QskLayoutHint, "LayoutHint" );
2017-07-21 16:21:34 +00:00
QSK_REGISTER_GADGET( QskSizePolicy, "SizePolicy" );
QSK_REGISTER_GADGET( QskTextOptions, "TextOptions" );
QSK_REGISTER_GADGET( QskMargins, "Margins" );
2017-07-21 16:21:34 +00:00
// Support (lists of) GradientStop
QMetaType::registerConverter< QJSValue, QskGradientStop >(
2018-08-03 06:15:28 +00:00
[](const QJSValue& value) -> QskGradientStop
2017-07-21 16:21:34 +00:00
{
return
{
2018-08-03 06:15:28 +00:00
value.property( QLatin1String( "position" ) ).toNumber(),
value.property( QLatin1String( "color" ) ).toVariant().value< QColor >()
2017-07-21 16:21:34 +00:00
};
}
);
QMetaType::registerConverter< QJSValue, QVector< QskGradientStop > >(
2018-08-03 06:15:28 +00:00
[]( const QJSValue& value )
2017-07-21 16:21:34 +00:00
{
QVector< QskGradientStop > stops;
if ( value.isArray() )
{
2018-08-03 06:15:28 +00:00
QJSValueIterator it( value );
2017-07-21 16:21:34 +00:00
while ( it.next() && it.hasNext() )
{
auto source = it.value();
auto target = QskGradientStop();
2020-10-28 08:05:31 +00:00
const int sourceTypeId = qMetaTypeId< decltype( source ) >();
const int targetTypeId = qMetaTypeId< decltype( target ) >();
#if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 )
QMetaType::convert( QMetaType( sourceTypeId ), &source,
QMetaType( targetTypeId ), &target );
#else
QMetaType::convert( &source, sourceTypeId, &target, targetTypeId );
#endif
2018-08-03 06:15:28 +00:00
stops.append( target );
2017-07-21 16:21:34 +00:00
}
}
return stops;
}
);
QQmlMetaType::registerCustomStringConverter( qMetaTypeId< QskMargins >(),
[]( const QString& s ) { return QVariant::fromValue( QskMargins( s.toDouble() ) ); } );
2017-07-21 16:21:34 +00:00
// Support QskSizePolicy in QML user properties
QMetaType::registerConverter< QJSValue, QskSizePolicy >(
2018-08-03 06:15:28 +00:00
[]( const QJSValue& value )
2017-07-21 16:21:34 +00:00
{
return QskSizePolicy(
static_cast< QskSizePolicy::Policy >( value.property( 0 ).toInt() ),
static_cast< QskSizePolicy::Policy >( value.property( 1 ).toInt() ) );
}
);
QMetaType::registerConverter< int, QskSizePolicy >(
2018-08-03 06:15:28 +00:00
[]( int value )
2017-07-21 16:21:34 +00:00
{
const auto policy = static_cast< QskSizePolicy::Policy >( value );
return QskSizePolicy( policy, policy );
}
);
}
2018-10-04 08:34:44 +00:00
#include "QskQml.moc"