qskinny/examples/iot-dashboard/src/kirigamiplugin.cpp

307 lines
15 KiB
C++

/*
* SPDX-FileCopyrightText: 2009 Alan Alpert <alan.alpert@nokia.com>
* SPDX-FileCopyrightText: 2010 Ménard Alexis <menard@kde.org>
* SPDX-FileCopyrightText: 2010 Marco Martin <mart@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "kirigamiplugin.h"
#include "columnview.h"
#include "enums.h"
#include "icon.h"
#include "settings.h"
#include "formlayoutattached.h"
#include "mnemonicattached.h"
#include "delegaterecycler.h"
#include "pagepool.h"
#include "scenepositionattached.h"
#include "wheelhandler.h"
#include "shadowedrectangle.h"
#include "shadowedtexture.h"
#include "colorutils.h"
#include "pagerouter.h"
#include "imagecolors.h"
//#include "avatar.h"
#include "toolbarlayout.h"
#include "sizegroup.h"
#include <QQmlEngine>
#include <QQmlContext>
#include <QQuickItem>
//#include <QQuickStyle>
#include <QGuiApplication>
#include <QClipboard>
#include "libkirigami/platformtheme.h"
static QString s_selectedStyle;
//Q_INIT_RESOURCE(kirigami);
#ifdef KIRIGAMI_BUILD_TYPE_STATIC
#include <qrc_kirigami.cpp>
#endif
class CopyHelperPrivate : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE static void copyTextToClipboard( const QString& text )
{
qGuiApp->clipboard()->setText( text );
}
};
// we can't do this in the plugin object directly, as that can live in a different thread
// and event filters are only allowed in the same thread as the filtered object
class LanguageChangeEventFilter : public QObject
{
Q_OBJECT
public:
bool eventFilter( QObject* receiver, QEvent* event ) override
{
if( event->type() == QEvent::LanguageChange && receiver == QCoreApplication::instance() )
{
emit languageChangeEvent();
}
return QObject::eventFilter( receiver, event );
}
Q_SIGNALS:
void languageChangeEvent();
};
KirigamiPlugin::KirigamiPlugin( QObject* parent )
: QQmlExtensionPlugin( parent )
{
auto filter = new LanguageChangeEventFilter;
filter->moveToThread( QCoreApplication::instance()->thread() );
QCoreApplication::instance()->installEventFilter( filter );
connect( filter, &LanguageChangeEventFilter::languageChangeEvent, this, &KirigamiPlugin::languageChangeEvent );
}
QUrl KirigamiPlugin::componentUrl( const QString& fileName ) const
{
for( const QString& style : qAsConst( m_stylesFallbackChain ) )
{
const QString candidate = QStringLiteral( "styles/" ) + style + QLatin1Char( '/' ) + fileName;
if( QFile::exists( resolveFilePath( candidate ) ) )
{
#ifdef KIRIGAMI_BUILD_TYPE_STATIC
return QUrl( QStringLiteral( "qrc:/org/kde/kirigami.2/styles/" ) + style + QLatin1Char( '/' ) + fileName );
#else
return QUrl( resolveFileUrl( candidate ) );
#endif
}
}
#ifdef KIRIGAMI_BUILD_TYPE_STATIC
return QUrl( QStringLiteral( "qrc:/org/kde/kirigami.2/" ) + fileName );
#else
return QUrl( resolveFileUrl( fileName ) );
#endif
}
void KirigamiPlugin::registerTypes( const char* uri )
{
#if defined(Q_OS_ANDROID) && QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QResource::registerResource( QStringLiteral( "assets:/android_rcc_bundle.rcc" ) );
#endif
Q_ASSERT( QLatin1String( uri ) == QLatin1String( "org.kde.kirigami" ) );
const QString style = QQuickStyle::name();
if( QIcon::themeName().isEmpty() && !qEnvironmentVariableIsSet( "XDG_CURRENT_DESKTOP" ) )
{
QIcon::setThemeSearchPaths( {resolveFilePath( QStringLiteral( "." ) ), QStringLiteral( ":/icons" )} );
QIcon::setThemeName( QStringLiteral( "breeze-internal" ) );
}
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
//org.kde.desktop.plasma is a couple of files that fall back to desktop by purpose
if( ( style.isEmpty() || style == QStringLiteral( "org.kde.desktop.plasma" ) ) && QFile::exists( resolveFilePath( QStringLiteral( "/styles/org.kde.desktop" ) ) ) )
{
m_stylesFallbackChain.prepend( QStringLiteral( "org.kde.desktop" ) );
}
#elif defined(Q_OS_ANDROID)
if( !m_stylesFallbackChain.contains( QLatin1String( "Material" ) ) )
{
m_stylesFallbackChain.prepend( QStringLiteral( "Material" ) );
}
#else // do we have an iOS specific style?
if( !m_stylesFallbackChain.contains( QLatin1String( "Material" ) ) )
{
m_stylesFallbackChain.prepend( QStringLiteral( "Material" ) );
}
#endif
if( !style.isEmpty() && QFile::exists( resolveFilePath( QStringLiteral( "/styles/" ) + style ) ) && !m_stylesFallbackChain.contains( style ) )
{
m_stylesFallbackChain.prepend( style );
//if we have plasma deps installed, use them for extra integration
if( style == QStringLiteral( "org.kde.desktop" ) && QFile::exists( resolveFilePath( QStringLiteral( "/styles/org.kde.desktop.plasma" ) ) ) )
{
m_stylesFallbackChain.prepend( QStringLiteral( "org.kde.desktop.plasma" ) );
}
}
else
{
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
m_stylesFallbackChain.prepend( QStringLiteral( "org.kde.desktop" ) );
#endif
}
//At this point the fallback chain will be selected->org.kde.desktop->Fallback
s_selectedStyle = m_stylesFallbackChain.first();
qmlRegisterSingletonType<Settings>( uri, 2, 0, "Settings",
[]( QQmlEngine * e, QJSEngine* ) -> QObject*
{
Settings* settings = Settings::self();
//singleton managed internally, qml should never delete it
e->setObjectOwnership( settings, QQmlEngine::CppOwnership );
settings->setStyle( s_selectedStyle );
return settings;
}
);
qmlRegisterUncreatableType<ApplicationHeaderStyle>( uri, 2, 0, "ApplicationHeaderStyle", QStringLiteral( "Cannot create objects of type ApplicationHeaderStyle" ) );
//old legacy retrocompatible Theme
qmlRegisterSingletonType( componentUrl( QStringLiteral( "Theme.qml" ) ), uri, 2, 0, "Theme" );
qmlRegisterSingletonType( componentUrl( QStringLiteral( "Units.qml" ) ), uri, 2, 0, "Units" );
qmlRegisterType( componentUrl( QStringLiteral( "Action.qml" ) ), uri, 2, 0, "Action" );
qmlRegisterType( componentUrl( QStringLiteral( "AbstractApplicationHeader.qml" ) ), uri, 2, 0, "AbstractApplicationHeader" );
qmlRegisterType( componentUrl( QStringLiteral( "AbstractApplicationWindow.qml" ) ), uri, 2, 0, "AbstractApplicationWindow" );
qmlRegisterType( componentUrl( QStringLiteral( "AbstractListItem.qml" ) ), uri, 2, 0, "AbstractListItem" );
qmlRegisterType( componentUrl( QStringLiteral( "ApplicationHeader.qml" ) ), uri, 2, 0, "ApplicationHeader" );
qmlRegisterType( componentUrl( QStringLiteral( "ToolBarApplicationHeader.qml" ) ), uri, 2, 0, "ToolBarApplicationHeader" );
qmlRegisterType( componentUrl( QStringLiteral( "ApplicationWindow.qml" ) ), uri, 2, 0, "ApplicationWindow" );
qmlRegisterType( componentUrl( QStringLiteral( "BasicListItem.qml" ) ), uri, 2, 0, "BasicListItem" );
qmlRegisterType( componentUrl( QStringLiteral( "OverlayDrawer.qml" ) ), uri, 2, 0, "OverlayDrawer" );
qmlRegisterType( componentUrl( QStringLiteral( "ContextDrawer.qml" ) ), uri, 2, 0, "ContextDrawer" );
qmlRegisterType( componentUrl( QStringLiteral( "GlobalDrawer.qml" ) ), uri, 2, 0, "GlobalDrawer" );
qmlRegisterType( componentUrl( QStringLiteral( "Heading.qml" ) ), uri, 2, 0, "Heading" );
qmlRegisterType( componentUrl( QStringLiteral( "Separator.qml" ) ), uri, 2, 0, "Separator" );
qmlRegisterType( componentUrl( QStringLiteral( "PageRow.qml" ) ), uri, 2, 0, "PageRow" );
qmlRegisterType<Icon>( uri, 2, 0, "Icon" );
qmlRegisterType( componentUrl( QStringLiteral( "Label.qml" ) ), uri, 2, 0, "Label" );
//TODO: uncomment for 2.3 release
//qmlRegisterTypeNotAvailable(uri, 2, 3, "Label", "Label type not supported anymore, use QtQuick.Controls.Label 2.0 instead");
qmlRegisterType( componentUrl( QStringLiteral( "OverlaySheet.qml" ) ), uri, 2, 0, "OverlaySheet" );
qmlRegisterType( componentUrl( QStringLiteral( "Page.qml" ) ), uri, 2, 0, "Page" );
qmlRegisterType( componentUrl( QStringLiteral( "ScrollablePage.qml" ) ), uri, 2, 0, "ScrollablePage" );
qmlRegisterType( componentUrl( QStringLiteral( "SplitDrawer.qml" ) ), uri, 2, 0, "SplitDrawer" );
qmlRegisterType( componentUrl( QStringLiteral( "SwipeListItem.qml" ) ), uri, 2, 0, "SwipeListItem" );
//2.1
qmlRegisterType( componentUrl( QStringLiteral( "AbstractItemViewHeader.qml" ) ), uri, 2, 1, "AbstractItemViewHeader" );
qmlRegisterType( componentUrl( QStringLiteral( "ItemViewHeader.qml" ) ), uri, 2, 1, "ItemViewHeader" );
qmlRegisterType( componentUrl( QStringLiteral( "AbstractApplicationItem.qml" ) ), uri, 2, 1, "AbstractApplicationItem" );
qmlRegisterType( componentUrl( QStringLiteral( "ApplicationItem.qml" ) ), uri, 2, 1, "ApplicationItem" );
//2.2
//Theme changed from a singleton to an attached property
qmlRegisterUncreatableType<Kirigami::PlatformTheme>( uri, 2, 2, "Theme", QStringLiteral( "Cannot create objects of type Theme, use it as an attached property" ) );
//2.3
qmlRegisterType( componentUrl( QStringLiteral( "FormLayout.qml" ) ), uri, 2, 3, "FormLayout" );
qmlRegisterUncreatableType<FormLayoutAttached>( uri, 2, 3, "FormData", QStringLiteral( "Cannot create objects of type FormData, use it as an attached property" ) );
qmlRegisterUncreatableType<MnemonicAttached>( uri, 2, 3, "MnemonicData", QStringLiteral( "Cannot create objects of type MnemonicData, use it as an attached property" ) );
//2.4
qmlRegisterType( componentUrl( QStringLiteral( "AbstractCard.qml" ) ), uri, 2, 4, "AbstractCard" );
qmlRegisterType( componentUrl( QStringLiteral( "Card.qml" ) ), uri, 2, 4, "Card" );
qmlRegisterType( componentUrl( QStringLiteral( "CardsListView.qml" ) ), uri, 2, 4, "CardsListView" );
qmlRegisterType( componentUrl( QStringLiteral( "CardsGridView.qml" ) ), uri, 2, 4, "CardsGridView" );
qmlRegisterType( componentUrl( QStringLiteral( "CardsLayout.qml" ) ), uri, 2, 4, "CardsLayout" );
qmlRegisterType( componentUrl( QStringLiteral( "InlineMessage.qml" ) ), uri, 2, 4, "InlineMessage" );
qmlRegisterUncreatableType<MessageType>( uri, 2, 4, "MessageType", QStringLiteral( "Cannot create objects of type MessageType" ) );
qmlRegisterType<DelegateRecycler>( uri, 2, 4, "DelegateRecycler" );
//2.5
qmlRegisterType( componentUrl( QStringLiteral( "ListItemDragHandle.qml" ) ), uri, 2, 5, "ListItemDragHandle" );
qmlRegisterType( componentUrl( QStringLiteral( "ActionToolBar.qml" ) ), uri, 2, 5, "ActionToolBar" );
qmlRegisterUncreatableType<ScenePositionAttached>( uri, 2, 5, "ScenePosition", QStringLiteral( "Cannot create objects of type ScenePosition, use it as an attached property" ) );
//2.6
qmlRegisterType( componentUrl( QStringLiteral( "AboutPage.qml" ) ), uri, 2, 6, "AboutPage" );
qmlRegisterType( componentUrl( QStringLiteral( "LinkButton.qml" ) ), uri, 2, 6, "LinkButton" );
qmlRegisterType( componentUrl( QStringLiteral( "UrlButton.qml" ) ), uri, 2, 6, "UrlButton" );
qmlRegisterSingletonType<CopyHelperPrivate>( "org.kde.kirigami.private", 2, 6, "CopyHelperPrivate", []( QQmlEngine*, QJSEngine* ) -> QObject* { return new CopyHelperPrivate; } );
//2.7
qmlRegisterType<ColumnView>( uri, 2, 7, "ColumnView" );
qmlRegisterType( componentUrl( QStringLiteral( "ActionTextField.qml" ) ), uri, 2, 7, "ActionTextField" );
//2.8
qmlRegisterType( componentUrl( QStringLiteral( "SearchField.qml" ) ), uri, 2, 8, "SearchField" );
qmlRegisterType( componentUrl( QStringLiteral( "PasswordField.qml" ) ), uri, 2, 8, "PasswordField" );
//2.9
qmlRegisterType<WheelHandler>( uri, 2, 9, "WheelHandler" );
qmlRegisterUncreatableType<KirigamiWheelEvent>( uri, 2, 9, "WheelEvent", QStringLiteral( "Cannot create objects of type WheelEvent." ) );
//2.10
qmlRegisterType( componentUrl( QStringLiteral( "ListSectionHeader.qml" ) ), uri, 2, 10, "ListSectionHeader" );
// 2.11
qmlRegisterType<PagePool>( uri, 2, 11, "PagePool" );
qmlRegisterType( componentUrl( QStringLiteral( "PagePoolAction.qml" ) ), uri, 2, 11, "PagePoolAction" );
//TODO: remove
qmlRegisterType( componentUrl( QStringLiteral( "SwipeListItem2.qml" ) ), uri, 2, 11, "SwipeListItem2" );
// 2.12
qmlRegisterType<ShadowedRectangle>( uri, 2, 12, "ShadowedRectangle" );
qmlRegisterType<ShadowedTexture>( uri, 2, 12, "ShadowedTexture" );
qmlRegisterType( componentUrl( QStringLiteral( "ShadowedImage.qml" ) ), uri, 2, 12, "ShadowedImage" );
qmlRegisterType( componentUrl( QStringLiteral( "PlaceholderMessage.qml" ) ), uri, 2, 12, "PlaceholderMessage" );
qmlRegisterUncreatableType<BorderGroup>( uri, 2, 12, "BorderGroup", QStringLiteral( "Used as grouped property" ) );
qmlRegisterUncreatableType<ShadowGroup>( uri, 2, 12, "ShadowGroup", QStringLiteral( "Used as grouped property" ) );
qmlRegisterSingletonType<ColorUtils>( uri, 2, 12, "ColorUtils", []( QQmlEngine*, QJSEngine* ) -> QObject* { return new ColorUtils; } );
qmlRegisterUncreatableType<CornersGroup>( uri, 2, 12, "CornersGroup", QStringLiteral( "Used as grouped property" ) );
qmlRegisterType<PageRouter>( uri, 2, 12, "PageRouter" );
qmlRegisterType<PageRoute>( uri, 2, 12, "PageRoute" );
qmlRegisterUncreatableType<PageRouterAttached>( uri, 2, 12, "PageRouterAttached", QStringLiteral( "PageRouterAttached cannot be created" ) );
qmlRegisterType( componentUrl( QStringLiteral( "RouterWindow.qml" ) ), uri, 2, 12, "RouterWindow" );
// 2.13
qmlRegisterType<ImageColors>( uri, 2, 13, "ImageColors" );
// qmlRegisterSingletonType<AvatarPrivate>( "org.kde.kirigami.private", 2, 13, "AvatarPrivate", []( QQmlEngine*, QJSEngine* ) -> QObject* { return new AvatarPrivate; } );
// qmlRegisterType( componentUrl( QStringLiteral( "Avatar.qml" ) ), uri, 2, 13, "Avatar" );
qmlRegisterType( componentUrl( QStringLiteral( "swipenavigator/SwipeNavigator.qml" ) ), uri, 2, 13, "SwipeNavigator" );
// 2.14
qmlRegisterUncreatableType<PreloadRouteGroup>( uri, 2, 14, "PreloadRouteGroup", QStringLiteral( "PreloadRouteGroup cannot be created" ) );
qmlRegisterType( componentUrl( QStringLiteral( "FlexColumn.qml" ) ), uri, 2, 14, "FlexColumn" );
qmlRegisterType<ToolBarLayout>( uri, 2, 14, "ToolBarLayout" );
qmlRegisterSingletonType<DisplayHint>( uri, 2, 14, "DisplayHint", []( QQmlEngine*, QJSEngine* ) -> QObject* { return new DisplayHint; } );
qmlRegisterType<SizeGroup>( uri, 2, 14, "SizeGroup" );
qmlProtectModule( uri, 2 );
}
void KirigamiPlugin::initializeEngine( QQmlEngine* engine, const char* uri )
{
Q_UNUSED( uri );
connect( this, &KirigamiPlugin::languageChangeEvent, engine, &QQmlEngine::retranslate );
}
#include "kirigamiplugin.moc"