From 9478053838ae2d950b162c2b93a2a400c82d9bf7 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sun, 13 May 2018 19:34:29 +0200 Subject: Create and init QQuickTheme from QtQuickControls2Plugin Instead of creating and setting the QQuickTheme instance from each style plugin (e.g. QtQuickControls2MaterialStylePlugin), create the QQuickTheme instance in QtQuickControls2Plugin when the style is being resolved, and just pass the instance to be initialized by the style plugin(s). This avoids the problem that QQuickTheme API was virtual, and sub-classes created from plugins would have vtables destroyed before the QQuickTheme was destroyed. Task-number: QTBUG-67062 Task-number: QTBUG-68087 Change-Id: I19e9ced5296b708c2668c30163389cb3da6be7cf Reviewed-by: Mitch Curtis --- src/imports/controls/fusion/qquickfusiontheme.cpp | 5 +- src/imports/controls/fusion/qquickfusiontheme_p.h | 10 +- .../fusion/qtquickcontrols2fusionstyleplugin.cpp | 6 +- .../controls/imagine/qquickimaginetheme.cpp | 12 +-- .../controls/imagine/qquickimaginetheme_p.h | 11 +- .../imagine/qtquickcontrols2imaginestyleplugin.cpp | 6 +- .../controls/material/qquickmaterialtheme.cpp | 33 +++--- .../controls/material/qquickmaterialtheme_p.h | 13 +-- .../qtquickcontrols2materialstyleplugin.cpp | 6 +- src/imports/controls/qquickdefaulttheme.cpp | 10 +- src/imports/controls/qquickdefaulttheme_p.h | 11 +- src/imports/controls/qtquickcontrols2plugin.cpp | 117 +++++++++++++-------- .../controls/universal/qquickuniversaltheme.cpp | 14 +-- .../controls/universal/qquickuniversaltheme_p.h | 12 +-- .../qtquickcontrols2universalstyleplugin.cpp | 6 +- 15 files changed, 144 insertions(+), 128 deletions(-) (limited to 'src/imports/controls') diff --git a/src/imports/controls/fusion/qquickfusiontheme.cpp b/src/imports/controls/fusion/qquickfusiontheme.cpp index 78465b6b..ac88563a 100644 --- a/src/imports/controls/fusion/qquickfusiontheme.cpp +++ b/src/imports/controls/fusion/qquickfusiontheme.cpp @@ -36,10 +36,13 @@ #include "qquickfusiontheme_p.h" +#include + QT_BEGIN_NAMESPACE -QQuickFusionTheme::QQuickFusionTheme() +void QQuickFusionTheme::initialize(QQuickTheme *theme) { + Q_UNUSED(theme); } QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qquickfusiontheme_p.h b/src/imports/controls/fusion/qquickfusiontheme_p.h index 0cd77f77..814c1919 100644 --- a/src/imports/controls/fusion/qquickfusiontheme_p.h +++ b/src/imports/controls/fusion/qquickfusiontheme_p.h @@ -48,16 +48,16 @@ // We mean it. // -#include -#include -#include +#include QT_BEGIN_NAMESPACE -class QQuickFusionTheme : public QQuickTheme +class QQuickTheme; + +class QQuickFusionTheme { public: - explicit QQuickFusionTheme(); + static void initialize(QQuickTheme *theme); }; QT_END_NAMESPACE diff --git a/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp b/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp index 65da8cd7..107b4a2d 100644 --- a/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp +++ b/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp @@ -63,7 +63,7 @@ public: void registerTypes(const char *uri) override; QString name() const override; - QQuickTheme *createTheme() const override; + void initializeTheme(QQuickTheme *theme) override; }; QtQuickControls2FusionStylePlugin::QtQuickControls2FusionStylePlugin(QObject *parent) : QQuickStylePlugin(parent) @@ -97,9 +97,9 @@ QString QtQuickControls2FusionStylePlugin::name() const return QStringLiteral("Fusion"); } -QQuickTheme *QtQuickControls2FusionStylePlugin::createTheme() const +void QtQuickControls2FusionStylePlugin::initializeTheme(QQuickTheme *theme) { - return new QQuickFusionTheme; + QQuickFusionTheme::initialize(theme); } QT_END_NAMESPACE diff --git a/src/imports/controls/imagine/qquickimaginetheme.cpp b/src/imports/controls/imagine/qquickimaginetheme.cpp index 3499b3cd..a9722fa5 100644 --- a/src/imports/controls/imagine/qquickimaginetheme.cpp +++ b/src/imports/controls/imagine/qquickimaginetheme.cpp @@ -36,19 +36,15 @@ #include "qquickimaginetheme_p.h" -#include +#include QT_BEGIN_NAMESPACE -QQuickImagineTheme::QQuickImagineTheme() -{ -} - -void QQuickImagineTheme::resolve() +void QQuickImagineTheme::initialize(QQuickTheme *theme) { QFont systemFont; systemFont.setFamily(QLatin1String("Open Sans")); - setFont(System, systemFont); + theme->setFont(QQuickTheme::System, systemFont); const QColor accentColor = QColor::fromRgb(0x4fc1e9); const QColor windowTextColor = QColor::fromRgb(0x434a54); @@ -64,7 +60,7 @@ void QQuickImagineTheme::resolve() systemPalette.setColor(QPalette::WindowText, windowTextColor); systemPalette.setColor(QPalette::Disabled, QPalette::Text, disabledWindowTextColor); systemPalette.setColor(QPalette::Disabled, QPalette::WindowText, disabledWindowTextColor); - setPalette(System, systemPalette); + theme->setPalette(QQuickTheme::System, systemPalette); } QT_END_NAMESPACE diff --git a/src/imports/controls/imagine/qquickimaginetheme_p.h b/src/imports/controls/imagine/qquickimaginetheme_p.h index 0d569598..d3d43074 100644 --- a/src/imports/controls/imagine/qquickimaginetheme_p.h +++ b/src/imports/controls/imagine/qquickimaginetheme_p.h @@ -48,17 +48,16 @@ // We mean it. // -#include +#include QT_BEGIN_NAMESPACE -class QQuickImagineTheme : public QQuickTheme +class QQuickTheme; + +class QQuickImagineTheme { public: - explicit QQuickImagineTheme(); - -protected: - void resolve() override; + static void initialize(QQuickTheme *theme); }; QT_END_NAMESPACE diff --git a/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp b/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp index 6dc142c9..490825ff 100644 --- a/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp +++ b/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp @@ -58,7 +58,7 @@ public: void registerTypes(const char *uri) override; QString name() const override; - QQuickTheme *createTheme() const override; + void initializeTheme(QQuickTheme *theme) override; }; QtQuickControls2ImagineStylePlugin::QtQuickControls2ImagineStylePlugin(QObject *parent) : QQuickStylePlugin(parent) @@ -84,9 +84,9 @@ QString QtQuickControls2ImagineStylePlugin::name() const return QStringLiteral("Imagine"); } -QQuickTheme *QtQuickControls2ImagineStylePlugin::createTheme() const +void QtQuickControls2ImagineStylePlugin::initializeTheme(QQuickTheme *theme) { - return new QQuickImagineTheme; + QQuickImagineTheme::initialize(theme); } QT_END_NAMESPACE diff --git a/src/imports/controls/material/qquickmaterialtheme.cpp b/src/imports/controls/material/qquickmaterialtheme.cpp index 3ab07f6b..f42c0a03 100644 --- a/src/imports/controls/material/qquickmaterialtheme.cpp +++ b/src/imports/controls/material/qquickmaterialtheme.cpp @@ -40,14 +40,11 @@ #include #include #include +#include QT_BEGIN_NAMESPACE -QQuickMaterialTheme::QQuickMaterialTheme() -{ -} - -void QQuickMaterialTheme::resolve() +void QQuickMaterialTheme::initialize(QQuickTheme *theme) { QFont systemFont; QFont buttonFont; @@ -78,38 +75,38 @@ void QQuickMaterialTheme::resolve() const bool dense = QQuickMaterialStyle::variant() == QQuickMaterialStyle::Dense; systemFont.setPixelSize(dense ? 13 : 14); - setFont(System, systemFont); + theme->setFont(QQuickTheme::System, systemFont); // https://material.io/guidelines/components/buttons.html#buttons-style buttonFont.setPixelSize(dense ? 13 : 14); buttonFont.setCapitalization(QFont::AllUppercase); buttonFont.setWeight(QFont::Medium); - setFont(Button, buttonFont); - setFont(TabBar, buttonFont); - setFont(ToolBar, buttonFont); + theme->setFont(QQuickTheme::Button, buttonFont); + theme->setFont(QQuickTheme::TabBar, buttonFont); + theme->setFont(QQuickTheme::ToolBar, buttonFont); // https://material.io/guidelines/components/tooltips.html toolTipFont.setPixelSize(dense ? 10 : 14); toolTipFont.setWeight(QFont::Medium); - setFont(ToolTip, toolTipFont); + theme->setFont(QQuickTheme::ToolTip, toolTipFont); itemViewFont.setPixelSize(dense ? 13 : 14); itemViewFont.setWeight(QFont::Medium); - setFont(ItemView, itemViewFont); + theme->setFont(QQuickTheme::ItemView, itemViewFont); // https://material.io/guidelines/components/lists.html#lists-specs listViewFont.setPixelSize(dense ? 13 : 16); - setFont(ListView, listViewFont); + theme->setFont(QQuickTheme::ListView, listViewFont); menuItemFont.setPixelSize(dense ? 13 : 16); - setFont(Menu, menuItemFont); - setFont(MenuBar, menuItemFont); - setFont(ComboBox, menuItemFont); + theme->setFont(QQuickTheme::Menu, menuItemFont); + theme->setFont(QQuickTheme::MenuBar, menuItemFont); + theme->setFont(QQuickTheme::ComboBox, menuItemFont); editorFont.setPixelSize(dense ? 13 : 16); - setFont(TextArea, editorFont); - setFont(TextField, editorFont); - setFont(SpinBox, editorFont); + theme->setFont(QQuickTheme::TextArea, editorFont); + theme->setFont(QQuickTheme::TextField, editorFont); + theme->setFont(QQuickTheme::SpinBox, editorFont); } QT_END_NAMESPACE diff --git a/src/imports/controls/material/qquickmaterialtheme_p.h b/src/imports/controls/material/qquickmaterialtheme_p.h index aa50887b..9a1362b8 100644 --- a/src/imports/controls/material/qquickmaterialtheme_p.h +++ b/src/imports/controls/material/qquickmaterialtheme_p.h @@ -48,19 +48,16 @@ // We mean it. // -#include -#include -#include +#include QT_BEGIN_NAMESPACE -class QQuickMaterialTheme : public QQuickTheme +class QQuickTheme; + +class QQuickMaterialTheme { public: - explicit QQuickMaterialTheme(); - -protected: - void resolve() override; + static void initialize(QQuickTheme *theme); }; QT_END_NAMESPACE diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp index 09dda329..d407af94 100644 --- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp +++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp @@ -58,7 +58,7 @@ public: void registerTypes(const char *uri) override; QString name() const override; - QQuickTheme *createTheme() const override; + void initializeTheme(QQuickTheme *theme) override; }; QtQuickControls2MaterialStylePlugin::QtQuickControls2MaterialStylePlugin(QObject *parent) : QQuickStylePlugin(parent) @@ -92,9 +92,9 @@ QString QtQuickControls2MaterialStylePlugin::name() const return QStringLiteral("Material"); } -QQuickTheme *QtQuickControls2MaterialStylePlugin::createTheme() const +void QtQuickControls2MaterialStylePlugin::initializeTheme(QQuickTheme *theme) { - return new QQuickMaterialTheme; + QQuickMaterialTheme::initialize(theme); } QT_END_NAMESPACE diff --git a/src/imports/controls/qquickdefaulttheme.cpp b/src/imports/controls/qquickdefaulttheme.cpp index a988c10b..bc292c2f 100644 --- a/src/imports/controls/qquickdefaulttheme.cpp +++ b/src/imports/controls/qquickdefaulttheme.cpp @@ -36,13 +36,11 @@ #include "qquickdefaulttheme_p.h" -QT_BEGIN_NAMESPACE +#include -QQuickDefaultTheme::QQuickDefaultTheme() -{ -} +QT_BEGIN_NAMESPACE -void QQuickDefaultTheme::resolve() +void QQuickDefaultTheme::initialize(QQuickTheme *theme) { QPalette systemPalette; @@ -85,7 +83,7 @@ void QQuickDefaultTheme::resolve() systemPalette.setColor(QPalette::WindowText, QColor::fromRgba(0xFF26282A)); systemPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor::fromRgba(0xFFBDBEBF)); - setPalette(System, systemPalette); + theme->setPalette(QQuickTheme::System, systemPalette); } QT_END_NAMESPACE diff --git a/src/imports/controls/qquickdefaulttheme_p.h b/src/imports/controls/qquickdefaulttheme_p.h index f372b111..3a7311c7 100644 --- a/src/imports/controls/qquickdefaulttheme_p.h +++ b/src/imports/controls/qquickdefaulttheme_p.h @@ -48,17 +48,16 @@ // We mean it. // -#include +#include QT_BEGIN_NAMESPACE -class QQuickDefaultTheme : public QQuickTheme +class QQuickTheme; + +class QQuickDefaultTheme { public: - explicit QQuickDefaultTheme(); - -protected: - void resolve() override; + static void initialize(QQuickTheme *theme); }; QT_END_NAMESPACE diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp index e1b683e8..553060a1 100644 --- a/src/imports/controls/qtquickcontrols2plugin.cpp +++ b/src/imports/controls/qtquickcontrols2plugin.cpp @@ -37,10 +37,9 @@ #include #include #include -#if !defined(QT_STATIC) && QT_CONFIG(library) -#include -#endif +#include #include +#include #include #include #include @@ -59,6 +58,7 @@ #include #include #include +#include #include "qquickdefaultbusyindicator_p.h" #include "qquickdefaultdial_p.h" @@ -80,12 +80,11 @@ public: void registerTypes(const char *uri) override; QString name() const override; - QQuickTheme *createTheme() const override; + void initializeTheme(QQuickTheme *theme) override; -#if !defined(QT_STATIC) && QT_CONFIG(library) private: - void loadStylePlugin(); -#endif + QList loadStylePlugins(); + QQuickTheme *createTheme(const QString &name); }; QtQuickControls2Plugin::QtQuickControls2Plugin(QObject *parent) : QQuickStylePlugin(parent) @@ -106,6 +105,11 @@ static QUrl fixupBaseUrl(QQmlExtensionPlugin *plugin) #endif } +static bool isDefaultStyle(const QString &style) +{ + return style.isEmpty() || style.compare(QStringLiteral("Default"), Qt::CaseInsensitive) == 0; +} + void QtQuickControls2Plugin::registerTypes(const char *uri) { QQuickStylePrivate::init(fixupBaseUrl(this)); @@ -114,10 +118,15 @@ void QtQuickControls2Plugin::registerTypes(const char *uri) if (!style.isEmpty()) QFileSelectorPrivate::addStatics(QStringList() << style.toLower()); -#if !defined(QT_STATIC) && QT_CONFIG(library) - // load the style's plugin to get access to its resources - loadStylePlugin(); -#endif + QQuickTheme *theme = createTheme(style.isEmpty() ? name() : style); + if (isDefaultStyle(style)) + initializeTheme(theme); + + // load the style's plugins to get access to its resources and initialize the theme + QList stylePlugins = loadStylePlugins(); + for (QQuickStylePlugin *stylePlugin : stylePlugins) + stylePlugin->initializeTheme(theme); + qDeleteAll(stylePlugins); qmlRegisterModule(uri, 2, QT_VERSION_MINOR - 7); // Qt 5.7->2.0, 5.8->2.1, 5.9->2.2... @@ -229,45 +238,69 @@ QString QtQuickControls2Plugin::name() const return QStringLiteral("Default"); } -QQuickTheme *QtQuickControls2Plugin::createTheme() const +void QtQuickControls2Plugin::initializeTheme(QQuickTheme *theme) { - return new QQuickDefaultTheme; + QQuickDefaultTheme::initialize(theme); } -#if !defined(QT_STATIC) && QT_CONFIG(library) -void QtQuickControls2Plugin::loadStylePlugin() +QList QtQuickControls2Plugin::loadStylePlugins() { - QFileInfo fileInfo = resolvedUrl(QStringLiteral("qmldir")).toLocalFile(); - if (!fileInfo.exists() || fileInfo.path() == baseUrl().toLocalFile()) - return; - - QFile file(fileInfo.filePath()); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) - return; - - QQmlDirParser parser; - parser.parse(QString::fromUtf8(file.readAll())); - if (parser.hasError()) - return; - - QLibrary lib; - lib.setLoadHints(QLibrary::PreventUnloadHint); - const auto plugins = parser.plugins(); - for (const QQmlDirParser::Plugin &plugin : plugins) { - QDir dir = fileInfo.dir(); - if (!plugin.path.isEmpty() && !dir.cd(plugin.path)) - continue; - QString filePath = dir.filePath(plugin.name); + QList stylePlugins; + + QFileInfo fileInfo = QQmlFile::urlToLocalFileOrQrc(resolvedUrl(QStringLiteral("qmldir"))); + if (fileInfo.exists() && fileInfo.path() != QQmlFile::urlToLocalFileOrQrc(baseUrl())) { + QFile file(fileInfo.filePath()); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QQmlDirParser parser; + parser.parse(QString::fromUtf8(file.readAll())); + if (!parser.hasError()) { +#ifdef QT_STATIC + const auto plugins = QPluginLoader::staticInstances(); + for (QObject *instance : plugins) { + QQuickStylePlugin *stylePlugin = qobject_cast(instance); + if (!stylePlugin || parser.className() != QLatin1String(instance->metaObject()->className())) + continue; + stylePlugins += stylePlugin; + } +#elif QT_CONFIG(library) + QPluginLoader loader; + const auto plugins = parser.plugins(); + for (const QQmlDirParser::Plugin &plugin : plugins) { + QDir dir = fileInfo.dir(); + if (!plugin.path.isEmpty() && !dir.cd(plugin.path)) + continue; + QString filePath = dir.filePath(plugin.name); #if defined(Q_OS_MACOS) && defined(QT_DEBUG) - // Avoid mismatching plugins on macOS so that we don't end up loading both debug and - // release versions of the same Qt libraries (due to the plugin's dependencies). - filePath += QStringLiteral("_debug"); + // Avoid mismatching plugins on macOS so that we don't end up loading both debug and + // release versions of the same Qt libraries (due to the plugin's dependencies). + filePath += QStringLiteral("_debug"); #endif // Q_OS_MACOS && QT_DEBUG - lib.setFileName(filePath); - lib.load(); + loader.setFileName(filePath); + QQuickStylePlugin *stylePlugin = qobject_cast(loader.instance()); + if (stylePlugin) + stylePlugins += stylePlugin; + } +#endif + } + } } + return stylePlugins; +} + +QQuickTheme *QtQuickControls2Plugin::createTheme(const QString &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)); + p->defaultPalette.reset(QQuickStylePrivate::readPalette(settings)); + } +#endif + QQuickThemePrivate::instance.reset(theme); + return theme; } -#endif // !QT_STATIC && QT_CONFIG(library) QT_END_NAMESPACE diff --git a/src/imports/controls/universal/qquickuniversaltheme.cpp b/src/imports/controls/universal/qquickuniversaltheme.cpp index 6485afbc..041dce9e 100644 --- a/src/imports/controls/universal/qquickuniversaltheme.cpp +++ b/src/imports/controls/universal/qquickuniversaltheme.cpp @@ -36,16 +36,12 @@ #include "qquickuniversaltheme_p.h" -#include #include +#include QT_BEGIN_NAMESPACE -QQuickUniversalTheme::QQuickUniversalTheme() -{ -} - -void QQuickUniversalTheme::resolve() +void QQuickUniversalTheme::initialize(QQuickTheme *theme) { QFont systemFont; QFont groupBoxTitleFont; @@ -60,15 +56,15 @@ void QQuickUniversalTheme::resolve() } systemFont.setPixelSize(15); - setFont(System, systemFont); + theme->setFont(QQuickTheme::System, systemFont); groupBoxTitleFont.setPixelSize(15); groupBoxTitleFont.setWeight(QFont::DemiBold); - setFont(GroupBox, groupBoxTitleFont); + theme->setFont(QQuickTheme::GroupBox, groupBoxTitleFont); tabButtonFont.setPixelSize(24); tabButtonFont.setWeight(QFont::Light); - setFont(TabBar, tabButtonFont); + theme->setFont(QQuickTheme::TabBar, tabButtonFont); } QT_END_NAMESPACE diff --git a/src/imports/controls/universal/qquickuniversaltheme_p.h b/src/imports/controls/universal/qquickuniversaltheme_p.h index f0f18db5..f762d0e3 100644 --- a/src/imports/controls/universal/qquickuniversaltheme_p.h +++ b/src/imports/controls/universal/qquickuniversaltheme_p.h @@ -48,18 +48,16 @@ // We mean it. // -#include -#include +#include QT_BEGIN_NAMESPACE -class QQuickUniversalTheme : public QQuickTheme +class QQuickTheme; + +class QQuickUniversalTheme { public: - explicit QQuickUniversalTheme(); - -protected: - void resolve() override; + static void initialize(QQuickTheme *theme); }; QT_END_NAMESPACE diff --git a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp index edc14327..1265f636 100644 --- a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp +++ b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp @@ -55,7 +55,7 @@ public: void registerTypes(const char *uri) override; QString name() const override; - QQuickTheme *createTheme() const override; + void initializeTheme(QQuickTheme *theme) override; }; QtQuickControls2UniversalStylePlugin::QtQuickControls2UniversalStylePlugin(QObject *parent) : QQuickStylePlugin(parent) @@ -85,9 +85,9 @@ QString QtQuickControls2UniversalStylePlugin::name() const return QStringLiteral("Universal"); } -QQuickTheme *QtQuickControls2UniversalStylePlugin::createTheme() const +void QtQuickControls2UniversalStylePlugin::initializeTheme(QQuickTheme *theme) { - return new QQuickUniversalTheme; + QQuickUniversalTheme::initialize(theme); } QT_END_NAMESPACE -- cgit v1.2.3