File indexing completed on 2024-04-28 15:27:42

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Alan Alpert <alan.alpert@nokia.com>
0003  *  SPDX-FileCopyrightText: 2010 Ménard Alexis <menard@kde.org>
0004  *  SPDX-FileCopyrightText: 2010 Marco Martin <mart@kde.org>
0005  *
0006  *  SPDX-License-Identifier: LGPL-2.0-or-later
0007  */
0008 
0009 #include "kirigamiplugin.h"
0010 #include "avatar.h"
0011 #include "colorutils.h"
0012 #include "columnview.h"
0013 #include "delegaterecycler.h"
0014 #include "enums.h"
0015 #include "formlayoutattached.h"
0016 #include "icon.h"
0017 #include "imagecolors.h"
0018 #include "inputmethod.h"
0019 #include "mnemonicattached.h"
0020 #include "pagepool.h"
0021 #include "pagerouter.h"
0022 #include "scenepositionattached.h"
0023 #include "settings.h"
0024 #include "shadowedrectangle.h"
0025 #include "shadowedtexture.h"
0026 #include "sizegroup.h"
0027 #include "spellcheckinghint.h"
0028 #include "toolbarlayout.h"
0029 #include "units.h"
0030 #include "wheelhandler.h"
0031 
0032 #include <QClipboard>
0033 #include <QGuiApplication>
0034 #if defined(Q_OS_ANDROID)
0035 #include <QResource>
0036 #endif
0037 #include <QQmlContext>
0038 #include <QQuickItem>
0039 #include <QQuickStyle>
0040 
0041 #include "libkirigami/basictheme_p.h"
0042 #include "libkirigami/platformtheme.h"
0043 #include "libkirigami/styleselector_p.h"
0044 #include "loggingcategory.h"
0045 #include "libkirigami/basictheme_p.h"
0046 #include "libkirigami/kirigamipluginfactory.h"
0047 
0048 static QString s_selectedStyle;
0049 
0050 #ifdef KIRIGAMI_BUILD_TYPE_STATIC
0051 #include "loggingcategory.h"
0052 #include <QDebug>
0053 #endif
0054 
0055 class CopyHelperPrivate : public QObject
0056 {
0057     Q_OBJECT
0058 public:
0059     Q_INVOKABLE static void copyTextToClipboard(const QString &text)
0060     {
0061         qGuiApp->clipboard()->setText(text);
0062     }
0063 };
0064 
0065 // we can't do this in the plugin object directly, as that can live in a different thread
0066 // and event filters are only allowed in the same thread as the filtered object
0067 class LanguageChangeEventFilter : public QObject
0068 {
0069     Q_OBJECT
0070 public:
0071     bool eventFilter(QObject *receiver, QEvent *event) override
0072     {
0073         if (event->type() == QEvent::LanguageChange && receiver == QCoreApplication::instance()) {
0074             Q_EMIT languageChangeEvent();
0075         }
0076         return QObject::eventFilter(receiver, event);
0077     }
0078 
0079 Q_SIGNALS:
0080     void languageChangeEvent();
0081 };
0082 
0083 KirigamiPlugin::KirigamiPlugin(QObject *parent)
0084     : QQmlExtensionPlugin(parent)
0085 {
0086     auto filter = new LanguageChangeEventFilter;
0087     filter->moveToThread(QCoreApplication::instance()->thread());
0088     QCoreApplication::instance()->installEventFilter(filter);
0089     connect(filter, &LanguageChangeEventFilter::languageChangeEvent, this, &KirigamiPlugin::languageChangeEvent);
0090 }
0091 
0092 QUrl KirigamiPlugin::componentUrl(const QString &fileName) const
0093 {
0094     return Kirigami::StyleSelector::componentUrl(fileName);
0095 }
0096 
0097 using SingletonCreationFunction = QObject *(*)(QQmlEngine *, QJSEngine *);
0098 
0099 template<class T>
0100 inline SingletonCreationFunction singleton()
0101 {
0102     static_assert(std::is_base_of<QObject, T>::value);
0103     return [](QQmlEngine *engine, QJSEngine *) -> QObject * {
0104         auto x = new T;
0105         x->setParent(engine);
0106         return x;
0107     };
0108 }
0109 
0110 void KirigamiPlugin::registerTypes(const char *uri)
0111 {
0112 #if defined(Q_OS_ANDROID)
0113     QResource::registerResource(QStringLiteral("assets:/android_rcc_bundle.rcc"));
0114 #endif
0115 
0116     Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.kirigami"));
0117 
0118     Kirigami::StyleSelector::setBaseUrl(baseUrl());
0119 
0120     if (QIcon::themeName().isEmpty() && !qEnvironmentVariableIsSet("XDG_CURRENT_DESKTOP")) {
0121         QIcon::setThemeSearchPaths({Kirigami::StyleSelector::resolveFilePath(QStringLiteral(".")), QStringLiteral(":/icons")});
0122         QIcon::setThemeName(QStringLiteral("breeze-internal"));
0123     } else {
0124         QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() << Kirigami::StyleSelector::resolveFilePath(QStringLiteral("icons")));
0125     }
0126 
0127     qmlRegisterSingletonType<Settings>(uri, 2, 0, "Settings", [](QQmlEngine *e, QJSEngine *) -> QObject * {
0128         Settings *settings = Settings::self();
0129         // singleton managed internally, qml should never delete it
0130         e->setObjectOwnership(settings, QQmlEngine::CppOwnership);
0131         settings->setStyle(Kirigami::StyleSelector::style());
0132         return settings;
0133     });
0134 
0135     qmlRegisterUncreatableType<ApplicationHeaderStyle>(uri,
0136                                                        2,
0137                                                        0,
0138                                                        "ApplicationHeaderStyle",
0139                                                        QStringLiteral("Cannot create objects of type ApplicationHeaderStyle"));
0140 
0141     // old legacy retrocompatible Theme
0142     qmlRegisterSingletonType<Kirigami::BasicThemeDefinition>(uri, 2, 0, "Theme", [](QQmlEngine *, QJSEngine *) {
0143         qCWarning(KirigamiLog) << "The Theme singleton is deprecated (since 5.39). Import Kirigami 2.2 or higher and use the attached property instead.";
0144         return new Kirigami::BasicThemeDefinition{};
0145     });
0146 
0147     qmlRegisterSingletonType<Kirigami::Units>(uri, 2, 0, "Units", [] (QQmlEngine *engine, QJSEngine *) {
0148 #ifndef KIRIGAMI_BUILD_TYPE_STATIC
0149         auto plugin = Kirigami::KirigamiPluginFactory::findPlugin();
0150         if (plugin) {
0151             // Check if the plugin implements units
0152             auto pluginV2 = qobject_cast<Kirigami::KirigamiPluginFactoryV2 *>(plugin);
0153             if (pluginV2) {
0154                 auto units = pluginV2->createUnits(engine);
0155                 if (units) {
0156                     return units;
0157                 } else {
0158                     qWarning(KirigamiLog) << "The style returned a nullptr Units*, falling back to defaults";
0159                 }
0160             } else {
0161                 qWarning(KirigamiLog) << "The style does not provide a C++ Units implementation."
0162                                       << "QML Units implementations are no longer supported.";
0163             }
0164         } else {
0165             qWarning(KirigamiLog) << "Failed to find a Kirigami platform plugin";
0166         }
0167 #endif
0168         // Fall back to the default units implementation
0169         return new Kirigami::Units(engine);
0170     });
0171 
0172     qmlRegisterType(componentUrl(QStringLiteral("Action.qml")), uri, 2, 0, "Action");
0173     qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationHeader.qml")), uri, 2, 0, "AbstractApplicationHeader");
0174     qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationWindow.qml")), uri, 2, 0, "AbstractApplicationWindow");
0175     qmlRegisterType(componentUrl(QStringLiteral("AbstractListItem.qml")), uri, 2, 0, "AbstractListItem");
0176     qmlRegisterType(componentUrl(QStringLiteral("ApplicationHeader.qml")), uri, 2, 0, "ApplicationHeader");
0177     qmlRegisterType(componentUrl(QStringLiteral("ToolBarApplicationHeader.qml")), uri, 2, 0, "ToolBarApplicationHeader");
0178     qmlRegisterType(componentUrl(QStringLiteral("ApplicationWindow.qml")), uri, 2, 0, "ApplicationWindow");
0179     qmlRegisterType(componentUrl(QStringLiteral("BasicListItem.qml")), uri, 2, 0, "BasicListItem");
0180     qmlRegisterType(componentUrl(QStringLiteral("OverlayDrawer.qml")), uri, 2, 0, "OverlayDrawer");
0181     qmlRegisterType(componentUrl(QStringLiteral("ContextDrawer.qml")), uri, 2, 0, "ContextDrawer");
0182     qmlRegisterType(componentUrl(QStringLiteral("GlobalDrawer.qml")), uri, 2, 0, "GlobalDrawer");
0183     qmlRegisterType(componentUrl(QStringLiteral("Heading.qml")), uri, 2, 0, "Heading");
0184     qmlRegisterType(componentUrl(QStringLiteral("Separator.qml")), uri, 2, 0, "Separator");
0185     qmlRegisterType(componentUrl(QStringLiteral("PageRow.qml")), uri, 2, 0, "PageRow");
0186 
0187     qmlRegisterType<Icon>(uri, 2, 0, "Icon");
0188 
0189     qmlRegisterType(componentUrl(QStringLiteral("Label.qml")), uri, 2, 0, "Label");
0190     // TODO: uncomment for 2.3 release
0191     // qmlRegisterTypeNotAvailable(uri, 2, 3, "Label", "Label type not supported anymore, use QtQuick.Controls.Label 2.0 instead");
0192     qmlRegisterType(componentUrl(QStringLiteral("OverlaySheet.qml")), uri, 2, 0, "OverlaySheet");
0193     qmlRegisterType(componentUrl(QStringLiteral("Page.qml")), uri, 2, 0, "Page");
0194     qmlRegisterType(componentUrl(QStringLiteral("ScrollablePage.qml")), uri, 2, 0, "ScrollablePage");
0195     qmlRegisterType(componentUrl(QStringLiteral("SplitDrawer.qml")), uri, 2, 0, "SplitDrawer");
0196     qmlRegisterType(componentUrl(QStringLiteral("SwipeListItem.qml")), uri, 2, 0, "SwipeListItem");
0197 
0198     // 2.1
0199     qmlRegisterType(componentUrl(QStringLiteral("AbstractItemViewHeader.qml")), uri, 2, 1, "AbstractItemViewHeader");
0200     qmlRegisterType(componentUrl(QStringLiteral("ItemViewHeader.qml")), uri, 2, 1, "ItemViewHeader");
0201     qmlRegisterType(componentUrl(QStringLiteral("AbstractApplicationItem.qml")), uri, 2, 1, "AbstractApplicationItem");
0202     qmlRegisterType(componentUrl(QStringLiteral("ApplicationItem.qml")), uri, 2, 1, "ApplicationItem");
0203 
0204     // 2.2
0205     // Theme changed from a singleton to an attached property
0206     qmlRegisterUncreatableType<Kirigami::PlatformTheme>(uri,
0207                                                         2,
0208                                                         2,
0209                                                         "Theme",
0210                                                         QStringLiteral("Cannot create objects of type Theme, use it as an attached property"));
0211 
0212     // 2.3
0213     qmlRegisterType(componentUrl(QStringLiteral("FormLayout.qml")), uri, 2, 3, "FormLayout");
0214     qmlRegisterUncreatableType<FormLayoutAttached>(uri,
0215                                                    2,
0216                                                    3,
0217                                                    "FormData",
0218                                                    QStringLiteral("Cannot create objects of type FormData, use it as an attached property"));
0219     qmlRegisterUncreatableType<MnemonicAttached>(uri,
0220                                                  2,
0221                                                  3,
0222                                                  "MnemonicData",
0223                                                  QStringLiteral("Cannot create objects of type MnemonicData, use it as an attached property"));
0224 
0225     // 2.4
0226     qmlRegisterType(componentUrl(QStringLiteral("AbstractCard.qml")), uri, 2, 4, "AbstractCard");
0227     qmlRegisterType(componentUrl(QStringLiteral("Card.qml")), uri, 2, 4, "Card");
0228     qmlRegisterType(componentUrl(QStringLiteral("CardsListView.qml")), uri, 2, 4, "CardsListView");
0229     qmlRegisterType(componentUrl(QStringLiteral("CardsGridView.qml")), uri, 2, 4, "CardsGridView");
0230     qmlRegisterType(componentUrl(QStringLiteral("CardsLayout.qml")), uri, 2, 4, "CardsLayout");
0231     qmlRegisterType(componentUrl(QStringLiteral("InlineMessage.qml")), uri, 2, 4, "InlineMessage");
0232     qmlRegisterUncreatableType<MessageType>(uri, 2, 4, "MessageType", QStringLiteral("Cannot create objects of type MessageType"));
0233     qmlRegisterType<DelegateRecycler>(uri, 2, 4, "DelegateRecycler");
0234 
0235     // 2.5
0236     qmlRegisterType(componentUrl(QStringLiteral("ListItemDragHandle.qml")), uri, 2, 5, "ListItemDragHandle");
0237     qmlRegisterType(componentUrl(QStringLiteral("ActionToolBar.qml")), uri, 2, 5, "ActionToolBar");
0238     qmlRegisterUncreatableType<ScenePositionAttached>(uri,
0239                                                       2,
0240                                                       5,
0241                                                       "ScenePosition",
0242                                                       QStringLiteral("Cannot create objects of type ScenePosition, use it as an attached property"));
0243 
0244     // 2.6
0245     qmlRegisterType(componentUrl(QStringLiteral("AboutPage.qml")), uri, 2, 6, "AboutPage");
0246     qmlRegisterType(componentUrl(QStringLiteral("LinkButton.qml")), uri, 2, 6, "LinkButton");
0247     qmlRegisterType(componentUrl(QStringLiteral("UrlButton.qml")), uri, 2, 6, "UrlButton");
0248     qmlRegisterSingletonType<CopyHelperPrivate>("org.kde.kirigami.private", 2, 6, "CopyHelperPrivate", singleton<CopyHelperPrivate>());
0249 
0250     // 2.7
0251     qmlRegisterType<ColumnView>(uri, 2, 7, "ColumnView");
0252     qmlRegisterType(componentUrl(QStringLiteral("ActionTextField.qml")), uri, 2, 7, "ActionTextField");
0253 
0254     // 2.8
0255     qmlRegisterType(componentUrl(QStringLiteral("SearchField.qml")), uri, 2, 8, "SearchField");
0256     qmlRegisterType(componentUrl(QStringLiteral("PasswordField.qml")), uri, 2, 8, "PasswordField");
0257 
0258     // 2.9
0259     qmlRegisterType<WheelHandler>(uri, 2, 9, "WheelHandler");
0260     qmlRegisterUncreatableType<KirigamiWheelEvent>(uri, 2, 9, "WheelEvent", QStringLiteral("Cannot create objects of type WheelEvent."));
0261 
0262     // 2.10
0263     qmlRegisterType(componentUrl(QStringLiteral("ListSectionHeader.qml")), uri, 2, 10, "ListSectionHeader");
0264 
0265     // 2.11
0266     qmlRegisterType<PagePool>(uri, 2, 11, "PagePool");
0267     qmlRegisterType(componentUrl(QStringLiteral("PagePoolAction.qml")), uri, 2, 11, "PagePoolAction");
0268 
0269     // TODO: remove
0270     qmlRegisterType(componentUrl(QStringLiteral("SwipeListItem2.qml")), uri, 2, 11, "SwipeListItem2");
0271 
0272     // 2.12
0273     qmlRegisterType<ShadowedRectangle>(uri, 2, 12, "ShadowedRectangle");
0274     qmlRegisterType<ShadowedTexture>(uri, 2, 12, "ShadowedTexture");
0275     qmlRegisterType(componentUrl(QStringLiteral("ShadowedImage.qml")), uri, 2, 12, "ShadowedImage");
0276     qmlRegisterType(componentUrl(QStringLiteral("PlaceholderMessage.qml")), uri, 2, 12, "PlaceholderMessage");
0277 
0278     qmlRegisterUncreatableType<BorderGroup>(uri, 2, 12, "BorderGroup", QStringLiteral("Used as grouped property"));
0279     qmlRegisterUncreatableType<ShadowGroup>(uri, 2, 12, "ShadowGroup", QStringLiteral("Used as grouped property"));
0280     qmlRegisterSingletonType<ColorUtils>(uri, 2, 12, "ColorUtils", singleton<ColorUtils>());
0281 
0282     qmlRegisterUncreatableType<CornersGroup>(uri, 2, 12, "CornersGroup", QStringLiteral("Used as grouped property"));
0283     qmlRegisterType<PageRouter>(uri, 2, 12, "PageRouter");
0284     qmlRegisterType<PageRoute>(uri, 2, 12, "PageRoute");
0285     qmlRegisterUncreatableType<PageRouterAttached>(uri, 2, 12, "PageRouterAttached", QStringLiteral("PageRouterAttached cannot be created"));
0286     qmlRegisterType(componentUrl(QStringLiteral("RouterWindow.qml")), uri, 2, 12, "RouterWindow");
0287 
0288     // 2.13
0289     qmlRegisterType<ImageColors>(uri, 2, 13, "ImageColors");
0290     qmlRegisterType(componentUrl(QStringLiteral("Avatar.qml")), uri, 2, 13, "Avatar");
0291     qmlRegisterType(componentUrl(QStringLiteral("swipenavigator/SwipeNavigator.qml")), uri, 2, 13, "SwipeNavigator");
0292 
0293     // 2.14
0294     qmlRegisterUncreatableType<PreloadRouteGroup>(uri, 2, 14, "PreloadRouteGroup", QStringLiteral("PreloadRouteGroup cannot be created"));
0295     qmlRegisterType(componentUrl(QStringLiteral("FlexColumn.qml")), uri, 2, 14, "FlexColumn");
0296     qmlRegisterType<ToolBarLayout>(uri, 2, 14, "ToolBarLayout");
0297     qmlRegisterSingletonType<DisplayHint>(uri, 2, 14, "DisplayHint", singleton<DisplayHint>());
0298     qmlRegisterType<SizeGroup>(uri, 2, 14, "SizeGroup");
0299     qmlRegisterType<AvatarGroup>("org.kde.kirigami.private", 2, 14, "AvatarGroup");
0300     qmlRegisterType(componentUrl(QStringLiteral("CheckableListItem.qml")), uri, 2, 14, "CheckableListItem");
0301     qmlRegisterSingletonType<NameUtils>(uri, 2, 14, "NameUtils", singleton<NameUtils>());
0302 
0303     qmlRegisterType(componentUrl(QStringLiteral("Hero.qml")), uri, 2, 15, "Hero");
0304 
0305     // 2.16
0306     qmlRegisterType<Kirigami::BasicThemeDefinition>(uri, 2, 16, "BasicThemeDefinition");
0307 
0308     // 2.17
0309     qmlRegisterType(componentUrl(QStringLiteral("swipenavigator/TabViewLayout.qml")), uri, 2, 17, "TabViewLayout");
0310     qmlRegisterType(componentUrl(QStringLiteral("swipenavigator/PageTab.qml")), uri, 2, 17, "PageTab");
0311 
0312     // 2.18
0313     qmlRegisterType<SpellCheckingAttached>(uri, 2, 18, "SpellChecking");
0314     qmlRegisterType(componentUrl(QStringLiteral("settingscomponents/CategorizedSettings.qml")), uri, 2, 18, "CategorizedSettings");
0315     qmlRegisterType(componentUrl(QStringLiteral("settingscomponents/GenericSettingsPage.qml")), uri, 2, 18, "GenericSettingsPage");
0316     qmlRegisterType(componentUrl(QStringLiteral("settingscomponents/SettingAction.qml")), uri, 2, 18, "SettingAction");
0317     
0318     // 2.19
0319     qmlRegisterType(componentUrl(QStringLiteral("AboutItem.qml")), uri, 2, 19, "AboutItem");
0320     qmlRegisterType(componentUrl(QStringLiteral("NavigationTabBar.qml")), uri, 2, 19, "NavigationTabBar");
0321     qmlRegisterType(componentUrl(QStringLiteral("NavigationTabButton.qml")), uri, 2, 19, "NavigationTabButton");
0322     qmlRegisterType(componentUrl(QStringLiteral("Dialog.qml")), uri, 2, 19, "Dialog");
0323     qmlRegisterType(componentUrl(QStringLiteral("MenuDialog.qml")), uri, 2, 19, "MenuDialog");
0324     qmlRegisterType(componentUrl(QStringLiteral("PromptDialog.qml")), uri, 2, 19, "PromptDialog");
0325     qmlRegisterType(componentUrl(QStringLiteral("AbstractChip.qml")), uri, 2, 19, "AbstractChip");
0326     qmlRegisterType(componentUrl(QStringLiteral("Chip.qml")), uri, 2, 19, "Chip");
0327     qmlRegisterType(componentUrl(QStringLiteral("LoadingPlaceholder.qml")), uri, 2, 19, "LoadingPlaceholder");
0328 
0329     qmlRegisterSingletonType<InputMethod>(uri, 2, 19, "InputMethod", [](QQmlEngine *, QJSEngine *) {
0330         return new InputMethod{};
0331     });
0332 
0333     // 2.20
0334     qmlRegisterType(componentUrl(QStringLiteral("SelectableLabel.qml")), uri, 2, 20, "SelectableLabel");
0335 
0336     qmlProtectModule(uri, 2);
0337 }
0338 
0339 void KirigamiPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
0340 {
0341     Q_UNUSED(uri);
0342     connect(this, &KirigamiPlugin::languageChangeEvent, engine, &QQmlEngine::retranslate);
0343 }
0344 
0345 #ifdef KIRIGAMI_BUILD_TYPE_STATIC
0346 KirigamiPlugin& KirigamiPlugin::getInstance()
0347 {
0348     static KirigamiPlugin instance;
0349     return instance;
0350 }
0351 
0352 void KirigamiPlugin::registerTypes(QQmlEngine* engine)
0353 {
0354     Q_INIT_RESOURCE(shaders);
0355     Q_INIT_RESOURCE(KirigamiPlugin);
0356 
0357     if (engine) {
0358         engine->addImportPath(QLatin1String(":/"));
0359     }
0360     else {
0361         qCWarning(KirigamiLog)
0362             << "Registering Kirigami on a null QQmlEngine instance - you likely want to pass a valid engine, or you will want to manually add the "
0363             "qrc root path :/ to your import paths list so the engine is able to load the plugin";
0364     }
0365 }
0366 #endif
0367 
0368 #include "kirigamiplugin.moc"
0369 #include "moc_kirigamiplugin.cpp"