diff --git a/kirigami.pri b/kirigami.pri index 70ff4145..922ca53a 100644 --- a/kirigami.pri +++ b/kirigami.pri @@ -1,70 +1,72 @@ QT += core qml quick gui svg network quickcontrols2 HEADERS += $$PWD/src/kirigamiplugin.h \ $$PWD/src/enums.h \ $$PWD/src/settings.h \ $$PWD/src/colorutils.h \ $$PWD/src/columnview_p.h \ $$PWD/src/columnview.h \ $$PWD/src/formlayoutattached.h \ $$PWD/src/mnemonicattached.h \ $$PWD/src/scenepositionattached.h \ $$PWD/src/libkirigami/basictheme_p.h \ $$PWD/src/libkirigami/platformtheme.h \ $$PWD/src/libkirigami/kirigamipluginfactory.h \ $$PWD/src/libkirigami/tabletmodewatcher.h \ $$PWD/src/scenegraph/paintedrectangleitem.h \ $$PWD/src/scenegraph/shadowedrectanglenode.h \ $$PWD/src/scenegraph/shadowedborderrectanglematerial.h \ $$PWD/src/scenegraph/shadowedbordertexturematerial.h \ $$PWD/src/scenegraph/shadowedrectanglematerial.h \ $$PWD/src/scenegraph/shadowedtexturematerial.h \ $$PWD/src/scenegraph/shadowedtexturenode.h \ $$PWD/src/icon.h \ $$PWD/src/delegaterecycler.h \ $$PWD/src/wheelhandler.h \ $$PWD/src/shadowedrectangle.h \ $$PWD/src/shadowedtexture.h \ $$PWD/src/pagerouter.h \ - $$PWD/src/pagepool.h + $$PWD/src/pagepool.h \ + $$PWD/src/avatar.h SOURCES += $$PWD/src/kirigamiplugin.cpp \ $$PWD/src/enums.cpp \ $$PWD/src/settings.cpp \ $$PWD/src/colorutils.cpp \ $$PWD/src/columnview.cpp \ $$PWD/src/formlayoutattached.cpp \ $$PWD/src/mnemonicattached.cpp \ $$PWD/src/scenepositionattached.cpp \ $$PWD/src/libkirigami/basictheme.cpp \ $$PWD/src/libkirigami/platformtheme.cpp \ $$PWD/src/libkirigami/kirigamipluginfactory.cpp \ $$PWD/src/libkirigami/tabletmodewatcher.cpp \ $$PWD/src/scenegraph/paintedrectangleitem.cpp \ $$PWD/src/scenegraph/shadowedrectanglenode.cpp \ $$PWD/src/scenegraph/shadowedborderrectanglematerial.cpp \ $$PWD/src/scenegraph/shadowedbordertexturematerial.cpp \ $$PWD/src/scenegraph/shadowedrectanglematerial.cpp \ $$PWD/src/scenegraph/shadowedtexturematerial.cpp \ $$PWD/src/scenegraph/shadowedtexturenode.cpp \ $$PWD/src/icon.cpp \ $$PWD/src/delegaterecycler.cpp \ $$PWD/src/wheelhandler.cpp \ $$PWD/src/shadowedrectangle.cpp \ $$PWD/src/shadowedtexture.cpp \ $$PWD/src/pagerouter.cpp \ - $$PWD/src/pagepool.cpp + $$PWD/src/pagepool.cpp \ + $$PWD/src/avatar.cpp INCLUDEPATH += $$PWD/src $$PWD/src/libkirigami DEFINES += KIRIGAMI_BUILD_TYPE_STATIC API_VER=1.0 RESOURCES += $$PWD/kirigami.qrc exists($$_PRO_FILE_PWD_/kirigami-icons.qrc) { message("Using icons QRC file shipped by the project") RESOURCES += $$_PRO_FILE_PWD_/kirigami-icons.qrc } else { message("Using icons QRCfile shipped in kirigami") RESOURCES += $$PWD/kirigami-icons.qrc } diff --git a/kirigami.qrc b/kirigami.qrc index 5fcf4f80..d208b57b 100644 --- a/kirigami.qrc +++ b/kirigami.qrc @@ -1,95 +1,97 @@ src/controls/AbstractApplicationWindow.qml src/controls/ContextDrawer.qml src/controls/Action.qml src/controls/Page.qml src/controls/PageRow.qml src/controls/AbstractListItem.qml src/controls/Theme.qml src/controls/AbstractCard.qml src/controls/templates/AbstractCard.qml src/controls/Card.qml src/controls/CardsLayout.qml src/controls/CardsListView.qml src/controls/CardsGridView.qml src/controls/ActionToolBar.qml src/controls/templates/InlineMessage.qml src/controls/InlineMessage.qml src/controls/ToolBarApplicationHeader.qml src/controls/ActionTextField.qml src/controls/SearchField.qml src/controls/PasswordField.qml src/controls/private/GlobalDrawerActionItem.qml src/controls/private/ContextDrawerActionItem.qml src/controls/private/RefreshableScrollView.qml src/controls/private/SwipeItemEventFilter.qml src/controls/private/PageActionPropertyGroup.qml src/controls/private/ActionIconGroup.qml src/controls/private/CornerShadow.qml src/controls/private/ActionButton.qml src/controls/private/DefaultListItemBackground.qml src/controls/private/DefaultCardBackground.qml src/controls/private/BannerImage.qml src/controls/private/EdgeShadow.qml src/controls/private/ActionToolBarLayoutDetails.qml src/controls/private/globaltoolbar/AbstractPageHeader.qml src/controls/private/globaltoolbar/PageRowGlobalToolBarStyleGroup.qml src/controls/private/globaltoolbar/PageRowGlobalToolBarUI.qml src/controls/private/PrivateActionToolButton.qml src/controls/private/globaltoolbar/TitlesPageHeader.qml src/controls/private/globaltoolbar/ToolBarPageHeader.qml src/controls/private/globaltoolbar/BreadcrumbControl.qml src/controls/private/globaltoolbar/TabBarControl.qml src/controls/private/ActionsMenu.qml src/controls/private/ActionMenuItem.qml src/controls/private/CardsGridViewPrivate.qml src/controls/private/CardsListViewPrivate.qml src/controls/Separator.qml src/controls/OverlayDrawer.qml src/controls/OverlaySheet.qml src/controls/GlobalDrawer.qml src/controls/templates/AbstractListItem.qml src/controls/templates/private/MenuIcon.qml src/controls/templates/private/GenericDrawerIcon.qml src/controls/templates/private/PassiveNotification.qml src/controls/templates/private/ContextIcon.qml src/controls/templates/private/ScrollView.qml src/controls/templates/private/BackButton.qml src/controls/templates/private/IconPropertiesGroup.qml src/controls/templates/private/ForwardButton.qml + src/controls/templates/private/BorderPropertiesGroup.qml src/controls/templates/OverlayDrawer.qml src/controls/templates/OverlaySheet.qml src/controls/templates/SwipeListItem.qml src/controls/templates/ApplicationHeader.qml src/controls/templates/AbstractApplicationHeader.qml src/controls/Units.qml src/controls/SwipeListItem.qml src/controls/ApplicationWindow.qml src/controls/AbstractApplicationItem.qml src/controls/ApplicationItem.qml src/controls/ApplicationHeader.qml src/controls/Heading.qml src/controls/ScrollablePage.qml src/controls/AboutPage.qml src/controls/UrlButton.qml src/controls/LinkButton.qml src/controls/Label.qml src/controls/BasicListItem.qml src/controls/AbstractApplicationHeader.qml src/controls/FormLayout.qml src/controls/ListItemDragHandle.qml src/controls/ShadowedImage.qml + src/controls/ShadowedImage.qml src/styles/Material/AbstractListItem.qml src/styles/Material/Theme.qml src/styles/Material/SwipeListItem.qml src/styles/Material/Label.qml src/styles/org.kde.desktop/AbstractListItem.qml src/styles/org.kde.desktop/Theme.qml src/styles/org.kde.desktop/Units.qml src/styles/org.kde.desktop/SwipeListItem.qml src/styles/org.kde.desktop/ApplicationWindow.qml src/styles/org.kde.desktop/AbstractApplicationHeader.qml src/controls/PlaceholderMessage.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c11deb97..9c153607 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,122 +1,123 @@ project(kirigami) if (BUILD_SHARED_LIBS) ecm_create_qm_loader(kirigami_QM_LOADER libkirigami2plugin_qt) else() set(KIRIGAMI_STATIC_FILES libkirigami/basictheme.cpp libkirigami/platformtheme.cpp libkirigami/tabletmodewatcher.cpp libkirigami/kirigamipluginfactory.cpp) endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libkirigami ${CMAKE_CURRENT_BINARY_DIR}/libkirigami) set(kirigami_SRCS kirigamiplugin.cpp columnview.cpp enums.cpp delegaterecycler.cpp icon.cpp settings.cpp formlayoutattached.cpp pagepool.cpp imagecolors.cpp scenepositionattached.cpp mnemonicattached.cpp wheelhandler.cpp shadowedrectangle.cpp shadowedtexture.cpp colorutils.cpp pagerouter.cpp + avatar.cpp scenegraph/shadowedrectanglenode.cpp scenegraph/shadowedrectanglematerial.cpp scenegraph/shadowedborderrectanglematerial.cpp scenegraph/paintedrectangleitem.cpp scenegraph/shadowedtexturenode.cpp scenegraph/shadowedtexturematerial.cpp scenegraph/shadowedbordertexturematerial.cpp ${kirigami_QM_LOADER} ${KIRIGAMI_STATIC_FILES} ) qt5_add_resources(SHADERS scenegraph/shaders/shaders.qrc) add_subdirectory(libkirigami) if(NOT BUILD_SHARED_LIBS) # `rcc` is a bit dumb and isn't designed to use auto generated files, to # avoid poluting the source directory, use absolute paths set(kirigami_QML_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../) # First, pre-process the QRC to add the files associated with the right Qt # version. configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../kirigami.qrc.in ${CMAKE_CURRENT_BINARY_DIR}/../kirigami.qrc @ONLY ) # When using the static library, all QML files need to be shipped within the # .a file. qt5_add_resources( RESOURCES ${CMAKE_CURRENT_BINARY_DIR}/../kirigami.qrc ) if (UNIX AND NOT ANDROID AND NOT(APPLE) AND NOT(DISABLE_DBUS)) qt5_add_dbus_interface(kirigami_SRCS libkirigami/org.kde.KWin.TabletModeManager.xml tabletmodemanager_interface) endif() endif() add_library(kirigamiplugin ${kirigami_SRCS} ${RESOURCES} ${SHADERS}) if(NOT BUILD_SHARED_LIBS) SET_TARGET_PROPERTIES(kirigamiplugin PROPERTIES AUTOMOC_MOC_OPTIONS -Muri=org.kde.kirigami) if (UNIX AND NOT ANDROID AND NOT(APPLE) AND NOT(DISABLE_DBUS)) set(Kirigami_EXTRA_LIBS Qt5::DBus) else() set(Kirigami_EXTRA_LIBS "") endif() else() set(Kirigami_EXTRA_LIBS KF5::Kirigami2) endif() target_link_libraries(kirigamiplugin PUBLIC Qt5::Core PRIVATE ${Kirigami_EXTRA_LIBS} Qt5::Qml Qt5::Quick Qt5::QuickControls2 Qt5::Concurrent ) if (BUILD_SHARED_LIBS) add_custom_target(copy_to_bin ALL COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2/ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/controls ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2/ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/styles ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2/styles COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_BINARY_DIR}/bin/org/kde/kirigami.2/ ) install(DIRECTORY controls/ DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2) if (DESKTOP_ENABLED) install(DIRECTORY styles/org.kde.desktop DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/styles) endif() install(DIRECTORY styles/Material DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2/styles) install(FILES ${platformspecific} DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2) include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME Kirigami2 LIB_NAME KF5Kirigami2 DEPS "core qml quick svg" FILENAME_VAR PRI_FILENAME ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) endif() install(TARGETS kirigamiplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/kirigami.2) diff --git a/src/avatar.cpp b/src/avatar.cpp new file mode 100644 index 00000000..1bedb2b7 --- /dev/null +++ b/src/avatar.cpp @@ -0,0 +1,107 @@ +#include "avatar.h" +#include +#include + +auto AvatarPrivate::initialsFromString(const QString& string) -> QString +{ + // "" -> "" + if (string.isEmpty()) return QStringLiteral(""); + + auto normalized = string.normalized(QString::NormalizationForm_D); + // "FirstName Name Name LastName" + if (normalized.contains(QStringLiteral(" "))) { + // "FirstName Name Name LastName" -> "FirstName" "Name" "Name" "LastName" + QStringList split = normalized.split(QStringLiteral(" ")); + // "FirstName" + auto first = split.first(); + // "LastName" + auto last = split.last(); + if (first.isEmpty()) { + // "" "LastName" -> "L" + return QString(last.front()); + } + if (last.isEmpty()) { + // "FirstName" "" -> "F" + return QString(first.front()); + } + // "FirstName" "LastName" -> "FL" + return QString(first.front())+QString(last.front()); + // "OneName" + } else { + // "OneName" -> "O" + return QString(normalized.front()); + } +} + +const QMap> c_colors = { + { + QStringLiteral("default"), + { + QColor("#e93a9a"), + QColor("#e93d58"), + QColor("#e9643a"), + QColor("#ef973c"), + QColor("#e8cb2d"), + QColor("#b6e521"), + QColor("#3dd425"), + QColor("#00d485"), + QColor("#00d3b8"), + QColor("#3daee9"), + QColor("#b875dc"), + QColor("#926ee4"), + } + }, + { + QStringLiteral("Material"), + { + QColor("#f44336"), + QColor("#e91e63"), + QColor("#9c27b0"), + QColor("#673ab7"), + QColor("#3f51b5"), + QColor("#2196f3"), + QColor("#03a9f4"), + QColor("#00bcd4"), + QColor("#009688"), + QColor("#4caf50"), + QColor("#8bc34a"), + QColor("#cddc39"), + QColor("#ffeb3b"), + QColor("#ffc107"), + QColor("#ff9800"), + QColor("#ff5722"), + } + } +}; + +QList grabColors() +{ + if (c_colors.contains(QQuickStyle::name())) { + return c_colors[QQuickStyle::name()]; + } + return c_colors[QStringLiteral("default")]; +} + +auto AvatarPrivate::colorsFromString(const QString& string) -> QColor +{ + // We use a hash to get a "random" number that's always the same for + // a given string. + auto hash = qHash(string); + // hash modulo the length of the colors list minus one will always get us a valid + // index + auto index = hash % (grabColors().length()-1); + // return a colour + return grabColors()[index]; +} + +auto AvatarPrivate::stringHasNonLatinCharacters(const QString& string) -> bool +{ + for (auto character : string) { + if (character.script() != QChar::Script_Common && + character.script() != QChar::Script_Inherited && + character.script() != QChar::Script_Latin) { + return true; + } + } + return false; +} diff --git a/src/avatar.h b/src/avatar.h new file mode 100644 index 00000000..b8ee1117 --- /dev/null +++ b/src/avatar.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +class AvatarPrivate : public QObject { + Q_OBJECT + +public: + Q_INVOKABLE QString initialsFromString(const QString& name); + Q_INVOKABLE QColor colorsFromString(const QString& name); + Q_INVOKABLE bool stringHasNonLatinCharacters(const QString& name); +}; diff --git a/src/controls/Avatar.qml b/src/controls/Avatar.qml new file mode 100644 index 00000000..775e5987 --- /dev/null +++ b/src/controls/Avatar.qml @@ -0,0 +1,160 @@ +/* + * SPDX-FileCopyrightText: 2020 Carson Black + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick 2.5 +import org.kde.kirigami 2.13 as Kirigami +import QtQuick.Controls 2.13 as QQC2 +import org.kde.kirigami.private 2.13 + +import "templates/private" as P + +/** + * An element that represents a user, either with initials, an icon, or a profile image. + */ +QQC2.Control { + id: avatarRoot + + enum ImageMode { + AlwaysShowImage, + AdaptiveImageOrInitals, + AlwaysShowInitials + } + enum InitialsMode { + UseInitials, + UseIcon + } + + /** + * The given name of a user. + * + * The user's name will be used for generating initials. + */ + property string name + + /** + * The source of the user's profile picture; an image. + */ + property alias source: avatarImage.source + + /** + * How the button should represent the user when there is no image available. + * * `UseInitials` - Use initials when the image is not available + * * `UseIcon` - Use an icon of a user when the image is not available + */ + property int initialsMode: Kirigami.Avatar.InitialsMode.UseInitials + + /** + * Whether the button should always show the image; show the image if one is + * available and show initials when it is not; or always show initials. + * * `AlwaysShowImage` - Always show the image; even if is not value + * * `AdaptiveImageOrInitals` - Show the image if it is valid; or show initials if it is not + * * `AlwaysShowInitials` - Always show initials + */ + property int imageMode: Kirigami.Avatar.ImageMode.AdaptiveImageOrInitals + + /** + * color: color + * + * The color to use for this avatar. + */ + property var color: undefined + // We use a var instead of a color here to allow setting the colour + // as undefined, which will result in a generated colour being used. + + property P.BorderPropertiesGroup border: P.BorderPropertiesGroup { + width: 2 + color: Qt.rgba(0,0,0,0.2) + } + + padding: 0 + topPadding: 0 + leftPadding: 0 + rightPadding: 0 + bottomPadding: 0 + + implicitWidth: Kirigami.Units.iconSizes.large + implicitHeight: Kirigami.Units.iconSizes.large + + background: Rectangle { + radius: parent.width / 2 + + color: __private.color + } + + QtObject { + id: __private + // This property allows us to fall back to colour generation if + // the root colour property is undefined. + property color color: { + if (!!avatarRoot.color) { + return avatarRoot.color + } + return AvatarPrivate.colorsFromString(name) + } + property bool showImage: { + return (avatarRoot.imageMode == Kirigami.Avatar.ImageMode.AlwaysShowImage) || + (avatarImage.status == Image.Ready && avatarRoot.imageMode == Kirigami.Avatar.ImageMode.AdaptiveImageOrInitals) + } + } + + contentItem: Item { + Kirigami.Heading { + visible: avatarRoot.initialsMode == Kirigami.Avatar.InitialsMode.UseInitials && + !__private.showImage && + !AvatarPrivate.stringHasNonLatinCharacters(avatarRoot.name) + + text: AvatarPrivate.initialsFromString(name) + color: Kirigami.ColorUtils.brightnessForColor(__private.color) == Kirigami.ColorUtils.Light + ? "black" + : "white" + + anchors.centerIn: parent + } + Kirigami.Icon { + visible: (avatarRoot.initialsMode == Kirigami.Avatar.InitialsMode.UseIcon && !__private.showImage) || + (AvatarPrivate.stringHasNonLatinCharacters(avatarRoot.name) && !__private.showImage) + + source: "user" + + anchors.fill: parent + anchors.margins: Kirigami.Units.smallSpacing + + Kirigami.Theme.textColor: Kirigami.ColorUtils.brightnessForColor(__private.color) == Kirigami.ColorUtils.Light + ? "black" + : "white" + } + Image { + id: avatarImage + visible: false + + mipmap: true + smooth: true + + fillMode: Image.PreserveAspectFit + anchors.fill: parent + } + Kirigami.ShadowedTexture { + visible: __private.showImage + + radius: width / 2 + anchors.fill: parent + + source: avatarImage + } + + Rectangle { + color: "transparent" + + radius: width / 2 + anchors.fill: parent + + border { + width: avatarRoot.border.width + color: avatarRoot.border.color + } + } + } +} diff --git a/src/controls/templates/private/BorderPropertiesGroup.qml b/src/controls/templates/private/BorderPropertiesGroup.qml new file mode 100644 index 00000000..89132259 --- /dev/null +++ b/src/controls/templates/private/BorderPropertiesGroup.qml @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2020 Carson Black + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick 2.5 + +QtObject { + /** + * The color of this border. + */ + property color color + + /** + * The width of this border. + */ + property real width +} diff --git a/src/kirigamiplugin.cpp b/src/kirigamiplugin.cpp index 8b120d25..5753ef5d 100644 --- a/src/kirigamiplugin.cpp +++ b/src/kirigamiplugin.cpp @@ -1,271 +1,274 @@ /* * SPDX-FileCopyrightText: 2009 Alan Alpert * SPDX-FileCopyrightText: 2010 Ménard Alexis * SPDX-FileCopyrightText: 2010 Marco Martin * * 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 #include #include #include #include #include #include "libkirigami/platformtheme.h" static QString s_selectedStyle; //Q_INIT_RESOURCE(kirigami); #ifdef KIRIGAMI_BUILD_TYPE_STATIC #include #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/styles/") + style + QLatin1Char('/') + fileName); #else return QUrl(resolveFileUrl(candidate)); #endif } } #ifdef KIRIGAMI_BUILD_TYPE_STATIC return QUrl(QStringLiteral("qrc:/org/kde/kirigami/") + 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(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(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(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(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(uri, 2, 3, "FormData", QStringLiteral("Cannot create objects of type FormData, use it as an attached property")); qmlRegisterUncreatableType(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(uri, 2, 4, "MessageType", QStringLiteral("Cannot create objects of type MessageType")); qmlRegisterType(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(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("org.kde.kirigami.private", 2, 6, "CopyHelperPrivate", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new CopyHelperPrivate; }); //2.7 qmlRegisterType(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(uri, 2, 9, "WheelHandler"); qmlRegisterUncreatableType(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(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(uri, 2, 12, "ShadowedRectangle"); qmlRegisterType(uri, 2, 12, "ShadowedTexture"); qmlRegisterType(componentUrl(QStringLiteral("ShadowedImage.qml")), uri, 2, 12, "ShadowedImage"); qmlRegisterType(componentUrl(QStringLiteral("PlaceholderMessage.qml")), uri, 2, 12, "PlaceholderMessage"); qmlRegisterUncreatableType(uri, 2, 12, "BorderGroup", QStringLiteral("Used as grouped property")); qmlRegisterUncreatableType(uri, 2, 12, "ShadowGroup", QStringLiteral("Used as grouped property")); qmlRegisterSingletonType(uri, 2, 12, "ColorUtils", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new ColorUtils; }); qmlRegisterUncreatableType(uri, 2, 12, "CornersGroup", QStringLiteral("Used as grouped property")); qmlRegisterType(uri, 2, 12, "PageRouter"); qmlRegisterType(uri, 2, 12, "PageRoute"); qmlRegisterUncreatableType(uri, 2, 12, "PageRouterAttached", QStringLiteral("PageRouterAttached cannot be created")); qmlRegisterType(componentUrl(QStringLiteral("RouterWindow.qml")), uri, 2, 12, "RouterWindow"); // 2.13 qmlRegisterType(uri, 2, 13, "ImageColors"); + qmlRegisterSingletonType("org.kde.kirigami.private", 2, 13, "AvatarPrivate", [] (QQmlEngine*, QJSEngine*) -> QObject* { return new AvatarPrivate; }); + qmlRegisterType(componentUrl(QStringLiteral("Avatar.qml")), uri, 2, 13, "Avatar"); qmlProtectModule(uri, 2); } void KirigamiPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { Q_UNUSED(uri); connect(this, &KirigamiPlugin::languageChangeEvent, engine, &QQmlEngine::retranslate); } #include "kirigamiplugin.moc"