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"