// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qquickstyle.h" #include "qquickstyle_p.h" #include "qquickstyleplugin_p.h" #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcStylePlugin, "qt.quick.controls.styleplugin") QQuickStylePlugin::QQuickStylePlugin(QObject *parent) : QQmlExtensionPlugin(parent) { } QQuickStylePlugin::~QQuickStylePlugin() { } void QQuickStylePlugin::registerTypes(const char *uri) { qCDebug(lcStylePlugin).nospace() << "registerTypes called with uri " << uri << "; plugin name is " << name(); const QTypeRevision latestControlsRevision = QQmlMetaType::latestModuleVersion(QLatin1String("QtQuick.Controls")); // Use the private function because we don't want to cause resolve() to be called, // as the logic that assigns a default style if one wasn't set would interfere with compile-time style selection. QString styleName = QQuickStylePrivate::style(); if (!latestControlsRevision.isValid() && styleName.isEmpty()) { // The user hasn't imported QtQuick.Controls, nor set a style via the runtime methods. qCDebug(lcStylePlugin).nospace() << uri << " imported before QtQuick.Controls; using compile-time style selection"; QQuickStyle::setStyle(name()); styleName = name(); } // Even if this style plugin isn't for the style set by the user, // we still want to create the theme object, because that function // is also responsible for reading values from qtquickcontrols2.conf. // So, even if a style doesn't have a QQuickTheme, it can still have // values set for (e.g. fonts and palettes) in qtquickcontrols2.conf. const QString effectiveCurrentStyleName = QQuickStylePrivate::effectiveStyleName(styleName); auto theme = QQuickTheme::instance(); if (!theme) { qCDebug(lcStylePlugin) << "creating theme"; theme = createTheme(effectiveCurrentStyleName); } // The primary fallback is the style set by the user. We need to check for that here // so that we can ensure that fallback styles' themes are initialized (QTBUG-117403) // without also allowing the Basic style to be initialized, as it is a secondary fallback // for every built-in style (and only built-in styles can be fallbacks). const bool thisPluginBelongsToCurrentStyle = name() == effectiveCurrentStyleName; const bool isPrimaryFallback = name() == QQuickStylePrivate::fallbackStyle(); if (!thisPluginBelongsToCurrentStyle && !isPrimaryFallback) { qCDebug(lcStylePlugin).nospace() << "this style plugin does not belong to the current (" << effectiveCurrentStyleName << ") or fallback (" << QQuickStylePrivate::fallbackStyle() << ") style; not calling initializeTheme()"; return; } if (thisPluginBelongsToCurrentStyle) { qCDebug(lcStylePlugin).nospace() << "this style plugin belongs to the current style " << effectiveCurrentStyleName << "; calling initializeTheme()"; } else { qCDebug(lcStylePlugin).nospace() << "this style plugin belongs to the fallback style " << QQuickStylePrivate::fallbackStyle() << "; calling initializeTheme()"; } initializeTheme(theme); connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &QQuickStylePlugin::updateTheme); if (!isPrimaryFallback && !styleName.isEmpty()) QFileSelectorPrivate::addStatics(QStringList() << styleName); } void QQuickStylePlugin::unregisterTypes() { qCDebug(lcStylePlugin) << "unregisterTypes called; plugin name is" << name(); if (!QQuickThemePrivate::instance) return; disconnect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &QQuickStylePlugin::updateTheme); // Not every style has a plugin - some styles are QML-only. So, we clean this // stuff up when the first style plugin is unregistered rather than when the // plugin for the current style is unregistered. QQuickThemePrivate::instance.reset(); QQuickStylePrivate::reset(); } /*! \internal Responsible for setting the font and palette settings that were specified in the qtquickcontrols2.conf file. Style-specific settings (e.g. Variant=Dense) are read in the constructor of the appropriate style plugin (e.g. QtQuickControls2MaterialStylePlugin). Implicit style-specific font and palette values are assigned in the relevant theme (e.g. QQuickMaterialTheme). */ QQuickTheme *QQuickStylePlugin::createTheme(const QString &name) { qCDebug(lcStylePlugin) << "creating QQuickTheme instance to be initialized by style-specific theme of" << name; QQuickTheme *theme = new QQuickTheme; #if QT_CONFIG(settings) QQuickThemePrivate *p = QQuickThemePrivate::get(theme); QSharedPointer settings = QQuickStylePrivate::settings(name); if (settings) { p->defaultFont.reset(QQuickStylePrivate::readFont(settings)); // Set the default font as the System scope, because that's what // QQuickControlPrivate::parentFont() uses as its fallback if no // parent item has a font explicitly set. QQuickControlPrivate::parentFont() // is used as the starting point for font inheritance/resolution. // The same goes for palettes below. theme->setFont(QQuickTheme::System, *p->defaultFont); p->defaultPalette.reset(QQuickStylePrivate::readPalette(settings)); theme->setPalette(QQuickTheme::System, *p->defaultPalette); } #endif QQuickThemePrivate::instance.reset(theme); return theme; } QT_END_NAMESPACE #include "moc_qquickstyleplugin_p.cpp"