aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/imports/controls/default/qtquickcontrols2defaultstyleplugin.cpp12
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc44
-rw-r--r--src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc8
-rw-r--r--src/imports/controls/fusion/qmldir2
-rw-r--r--src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp18
-rw-r--r--src/imports/controls/imagine/qmldir2
-rw-r--r--src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp20
-rw-r--r--src/imports/controls/material/qmldir2
-rw-r--r--src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp17
-rw-r--r--src/imports/controls/qtquickcontrols2plugin.cpp160
-rw-r--r--src/imports/controls/universal/qmldir2
-rw-r--r--src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp18
-rw-r--r--src/quickcontrols2/qquickstyle.cpp350
-rw-r--r--src/quickcontrols2/qquickstyle.h4
-rw-r--r--src/quickcontrols2/qquickstyle_p.h8
-rw-r--r--src/quickcontrols2/qquickstyleplugin.cpp16
-rw-r--r--src/quickcontrols2/qquickstyleplugin_p.h2
17 files changed, 254 insertions, 431 deletions
diff --git a/src/imports/controls/default/qtquickcontrols2defaultstyleplugin.cpp b/src/imports/controls/default/qtquickcontrols2defaultstyleplugin.cpp
index 0ed33d12..a486658e 100644
--- a/src/imports/controls/default/qtquickcontrols2defaultstyleplugin.cpp
+++ b/src/imports/controls/default/qtquickcontrols2defaultstyleplugin.cpp
@@ -38,6 +38,7 @@
#include "qquickdefaulttheme_p.h"
#include <QtQuickControls2/private/qquickstyleplugin_p.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
QT_BEGIN_NAMESPACE
@@ -50,7 +51,10 @@ public:
QtQuickControls2DefaultStylePlugin(QObject *parent = nullptr);
QString name() const override;
- void initializeTheme(QQuickTheme *theme) override;
+
+ void registerTypes(const char *uri) override;
+
+ QQuickDefaultTheme theme;
};
QtQuickControls2DefaultStylePlugin::QtQuickControls2DefaultStylePlugin(QObject *parent) : QQuickStylePlugin(parent)
@@ -62,9 +66,11 @@ QString QtQuickControls2DefaultStylePlugin::name() const
return QStringLiteral("Default");
}
-void QtQuickControls2DefaultStylePlugin::initializeTheme(QQuickTheme *theme)
+void QtQuickControls2DefaultStylePlugin::registerTypes(const char *uri)
{
- QQuickDefaultTheme::initialize(theme);
+ QQuickStylePlugin::registerTypes(uri);
+
+ theme.initialize(QQuickTheme::instance());
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
index 6ab649d0..58138a07 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-customize.qdoc
@@ -112,7 +112,7 @@
\section2 Definition of a Style
In Qt Quick Controls, a style is essentially an interchangeable set of
- QML files within a single directory. There are three requirements for a style
+ QML files within a single directory. There are four requirements for a style
to be \l {Using Styles in Qt Quick Controls}{usable}:
\list
@@ -125,21 +125,37 @@
If we instead used the corresponding type from the \l {Qt Quick Controls}
{QtQuick.Controls} import as we did in the previous section, it would not work:
the control we were defining would try to derive from itself.
- \li The files must be in a directory in the filesystem or in the
- \l {The Qt Resource System}{resource system}.
+ \li A \l {Module Definition qmldir Files}{qmldir} file must exist alongside
+ the QML file(s). Below is an example of a simple \c qmldir file for a style that
+ provides a button:
- For example, these are all valid paths to a style:
+ \badcode
+ module MyStyle
+ Button 2.15 Button.qml
+ \endcode
+
+ The directory structure for such a style looks like this:
+
+ \badcode
+ MyStyle
+ ├─── Button.qml
+ └─── qmldir
+ \endcode
+ \li The files must be in a directory that is findable via the \l {QML Import Path}.
+
+ For example, if the path to \e MyStyle directory mentioned above was
+ \c /home/user/MyApp/MyStyle, then \c /home/user/MyApp must be added to
+ the QML import path.
+
+ To \l {Using Styles in Qt Quick Controls}{use} \e MyStyle in \e MyApp,
+ refer to it by name:
\list
- \li \c {./myapp -style /home/absolute/path/to/my/style}
- \li \c {./myapp -style :/mystyle}
- \li \c {./myapp -style relative/path/to/my/style}
- \li \c {./myapp -style MyStyle}
+ \li \c {./MyApp -style MyStyle}
\endlist
- The third and fourth paths will be looked up within the QML engine's import path
- list. This is the same as what happens when you pass \c Material as the style,
- for example.
+ The style name must match the casing of the style directory; passing
+ \e mystyle or \e MYSTYLE is not supported.
\endlist
By default, the styling system uses the Default style as a fallback for
@@ -302,7 +318,7 @@
style will illustrate the elevation with a drop shadow; the higher the
elevation, the larger the shadow.
- The first step is to \l {Qt Creator: Creating Qt Quick Projects}{create a new Qt Quick
+ The first step is to \l {Creating Qt Quick Projects}{create a new Qt Quick
Controls 2 application} in Qt Creator. After that, we
\l {Qt Creator: Creating C++ Classes}{add a C++ type} that stores the elevation. Since
the type will be used for every control supported by our style, and because
@@ -390,6 +406,8 @@
qmlRegisterUncreatableType<MyStyle>("MyStyle", 1, 0, "MyStyle", "MyStyle is an attached property");
QQmlApplicationEngine engine;
+ // Make the directory containing our style known to the QML engine.
+ engine.addImportPath(":/");
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
@@ -465,7 +483,7 @@
One button has no elevation, and the other has an elevation of \c 10.
With that in place, we can run our example. To tell the application to
- use our new style, we pass \c {-style :/mystyle} as an application
+ use our new style, we pass \c {-style MyStyle} as an application
argument, but there are \l {Using Styles in Qt Quick Controls}{many
ways} to specify the style to use.
diff --git a/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc b/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc
index e1461ee4..4484acf3 100644
--- a/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc
+++ b/src/imports/controls/doc/src/qtquickcontrols2-environment.qdoc
@@ -41,18 +41,12 @@
\li \c QT_QUICK_CONTROLS_STYLE
\li Specifies the default \l {Styling Qt Quick Controls}{Qt Quick Controls style}.
The value can be either one of the built-in styles, for example \c "Material",
- or the path to a custom style such as \c ":/mystyle".
+ or a custom style such as \c "MyStyle".
\row
\li \c QT_QUICK_CONTROLS_FALLBACK_STYLE
\li Specifies a fallback style for \l {Creating a Custom Style}{custom styles}.
The value can be one of the built-in styles, for example \c "Material",
\row
- \li \c QT_QUICK_CONTROLS_STYLE_PATH
- \li Specifies a list of additional paths that are used to lookup \l {Styling Qt Quick Controls}
- {Qt Quick Controls styles}. Multiple path entries must be \l {QDir::listSeparator}{separated}
- by \c ':' under Unix and \c ';' under Windows. By default, styles are looked up from
- \c $QML2_IMPORT_PATH/QtQuick/Controls.
- \row
\li \c QT_QUICK_CONTROLS_CONF
\li Specifies the location of the \l {Qt Quick Controls configuration file}.
By default, the configuration file is loaded from the application's
diff --git a/src/imports/controls/fusion/qmldir b/src/imports/controls/fusion/qmldir
index 572a6dd2..84c0b211 100644
--- a/src/imports/controls/fusion/qmldir
+++ b/src/imports/controls/fusion/qmldir
@@ -1,7 +1,7 @@
module QtQuick.Controls.Fusion
plugin qtquickcontrols2fusionstyleplugin
classname QtQuickControls2FusionStylePlugin
-depends QtQuick.Controls 2.5
+import QtQuick.Controls.Default auto
# QtQuick.Controls 2.0 (originally introduced in Qt 5.7)
ApplicationWindow 2.0 ApplicationWindow.qml
diff --git a/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp b/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp
index b9df2e7d..c70c9602 100644
--- a/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp
+++ b/src/imports/controls/fusion/qtquickcontrols2fusionstyleplugin.cpp
@@ -34,12 +34,13 @@
**
****************************************************************************/
-#include <QtQuickControls2/private/qquickstyleplugin_p.h>
-#include <QtQml/qqml.h>
-
#include "qquickfusionstyle_p.h"
#include "qquickfusiontheme_p.h"
+#include <QtQml/qqml.h>
+#include <QtQuickControls2/private/qquickstyleplugin_p.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
+
QT_BEGIN_NAMESPACE
class QtQuickControls2FusionStylePlugin : public QQuickStylePlugin
@@ -51,7 +52,10 @@ public:
QtQuickControls2FusionStylePlugin(QObject *parent = nullptr);
QString name() const override;
- void initializeTheme(QQuickTheme *theme) override;
+
+ void registerTypes(const char *uri) override;
+
+ QQuickFusionTheme theme;
};
QtQuickControls2FusionStylePlugin::QtQuickControls2FusionStylePlugin(QObject *parent) : QQuickStylePlugin(parent)
@@ -63,9 +67,11 @@ QString QtQuickControls2FusionStylePlugin::name() const
return QStringLiteral("Fusion");
}
-void QtQuickControls2FusionStylePlugin::initializeTheme(QQuickTheme *theme)
+void QtQuickControls2FusionStylePlugin::registerTypes(const char *uri)
{
- QQuickFusionTheme::initialize(theme);
+ QQuickStylePlugin::registerTypes(uri);
+
+ theme.initialize(QQuickTheme::instance());
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/imagine/qmldir b/src/imports/controls/imagine/qmldir
index 380a0dc3..e3d7d8d5 100644
--- a/src/imports/controls/imagine/qmldir
+++ b/src/imports/controls/imagine/qmldir
@@ -1,7 +1,7 @@
module QtQuick.Controls.Imagine
plugin qtquickcontrols2imaginestyleplugin
classname QtQuickControls2ImagineStylePlugin
-depends QtQuick.Controls 2.5
+import QtQuick.Controls.Default auto
# QtQuick.Controls 2.0 (originally introduced in Qt 5.7)
ApplicationWindow 2.0 ApplicationWindow.qml
diff --git a/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp b/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp
index d59cf555..0c864254 100644
--- a/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp
+++ b/src/imports/controls/imagine/qtquickcontrols2imaginestyleplugin.cpp
@@ -34,13 +34,14 @@
**
****************************************************************************/
-#include <QtQuickControls2/private/qquickstyleplugin_p.h>
-#include <QtCore/qloggingcategory.h>
-#include <QtQml/qqml.h>
-
#include "qquickimaginestyle_p.h"
#include "qquickimaginetheme_p.h"
+#include <QtCore/qloggingcategory.h>
+#include <QtQml/qqml.h>
+#include <QtQuickControls2/private/qquickstyleplugin_p.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
+
QT_BEGIN_NAMESPACE
class QtQuickControls2ImagineStylePlugin : public QQuickStylePlugin
@@ -52,7 +53,10 @@ public:
QtQuickControls2ImagineStylePlugin(QObject *parent = nullptr);
QString name() const override;
- void initializeTheme(QQuickTheme *theme) override;
+
+ void registerTypes(const char *uri) override;
+
+ QQuickImagineTheme theme;
};
QtQuickControls2ImagineStylePlugin::QtQuickControls2ImagineStylePlugin(QObject *parent) : QQuickStylePlugin(parent)
@@ -64,9 +68,11 @@ QString QtQuickControls2ImagineStylePlugin::name() const
return QStringLiteral("Imagine");
}
-void QtQuickControls2ImagineStylePlugin::initializeTheme(QQuickTheme *theme)
+void QtQuickControls2ImagineStylePlugin::registerTypes(const char *uri)
{
- QQuickImagineTheme::initialize(theme);
+ QQuickStylePlugin::registerTypes(uri);
+
+ theme.initialize(QQuickTheme::instance());
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/material/qmldir b/src/imports/controls/material/qmldir
index a1064229..39dae48a 100644
--- a/src/imports/controls/material/qmldir
+++ b/src/imports/controls/material/qmldir
@@ -1,7 +1,7 @@
module QtQuick.Controls.Material
plugin qtquickcontrols2materialstyleplugin
classname QtQuickControls2MaterialStylePlugin
-depends QtQuick.Controls 2.5
+import QtQuick.Controls.Default auto
# QtQuick.Controls 2.0 (originally introduced in Qt 5.7)
ApplicationWindow 2.0 ApplicationWindow.qml
diff --git a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
index dc6873bb..6066d3f5 100644
--- a/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
+++ b/src/imports/controls/material/qtquickcontrols2materialstyleplugin.cpp
@@ -34,12 +34,12 @@
**
****************************************************************************/
-#include <QtQuickControls2/private/qquickstyleplugin_p.h>
-
#include "qquickmaterialstyle_p.h"
#include "qquickmaterialtheme_p.h"
+#include <QtQuickControls2/private/qquickstyleplugin_p.h>
#include <QtQuickControls2Impl/private/qquickpaddedrectangle_p.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
QT_BEGIN_NAMESPACE
@@ -52,12 +52,14 @@ public:
QtQuickControls2MaterialStylePlugin(QObject *parent = nullptr);
QString name() const override;
- void initializeTheme(QQuickTheme *theme) override;
+
+ void registerTypes(const char *uri) override;
+
+ QQuickMaterialTheme theme;
};
QtQuickControls2MaterialStylePlugin::QtQuickControls2MaterialStylePlugin(QObject *parent) : QQuickStylePlugin(parent)
{
- QQuickMaterialStyle::initGlobals();
}
QString QtQuickControls2MaterialStylePlugin::name() const
@@ -65,9 +67,12 @@ QString QtQuickControls2MaterialStylePlugin::name() const
return QStringLiteral("Material");
}
-void QtQuickControls2MaterialStylePlugin::initializeTheme(QQuickTheme *theme)
+void QtQuickControls2MaterialStylePlugin::registerTypes(const char *uri)
{
- QQuickMaterialTheme::initialize(theme);
+ QQuickStylePlugin::registerTypes(uri);
+
+ QQuickMaterialStyle::initGlobals();
+ theme.initialize(QQuickTheme::instance());
}
QT_END_NAMESPACE
diff --git a/src/imports/controls/qtquickcontrols2plugin.cpp b/src/imports/controls/qtquickcontrols2plugin.cpp
index 17eb2be9..ef642905 100644
--- a/src/imports/controls/qtquickcontrols2plugin.cpp
+++ b/src/imports/controls/qtquickcontrols2plugin.cpp
@@ -37,6 +37,7 @@
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
#include <QtCore/qfileinfo.h>
+#include <QtCore/qloggingcategory.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/private/qfileselector_p.h>
#include <QtQml/qqmlfile.h>
@@ -50,6 +51,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQtQuickControlsStylePlugin, "qt.quick.controls.qtquickcontrols2plugin")
+
class QtQuickControls2Plugin : public QQmlExtensionPlugin
{
Q_OBJECT
@@ -59,17 +62,41 @@ public:
QtQuickControls2Plugin(QObject *parent = nullptr);
~QtQuickControls2Plugin();
- void initializeEngine(QQmlEngine *engine, const char *uri) override;
void registerTypes(const char *uri) override;
void unregisterTypes() override;
private:
- void init();
-
- QList<QQuickStylePlugin *> loadStylePlugins();
QQuickTheme *createTheme(const QString &name);
+
+ bool registeredFallbackImport = false;
};
+static const char *qtQuickControlsUri = "QtQuick.Controls";
+
+QString styleUri()
+{
+ const QString style = QQuickStyle::name();
+ if (!QQuickStylePrivate::isCustomStyle()) {
+ // The style set is a built-in style.
+ const QString styleName = QQuickStylePrivate::effectiveStyleName(style);
+ return QString::fromLatin1("QtQuick.Controls.%1").arg(styleName);
+ }
+
+ // This is a custom style, so just use the name as the import uri.
+ QString styleName = style;
+ if (styleName.startsWith(QLatin1String(":/")))
+ styleName.remove(0, 2);
+ return styleName;
+}
+
+QString fallbackStyleUri()
+{
+ // The fallback style must be a built-in style, so we don't need to check for custom styles here.
+ const QString fallbackStyle = QQuickStylePrivate::fallbackStyle();
+ const QString fallbackStyleName = QQuickStylePrivate::effectiveStyleName(fallbackStyle);
+ return QString::fromLatin1("QtQuick.Controls.%1").arg(fallbackStyleName);
+}
+
QtQuickControls2Plugin::QtQuickControls2Plugin(QObject *parent) : QQmlExtensionPlugin(parent)
{
}
@@ -80,88 +107,83 @@ QtQuickControls2Plugin::~QtQuickControls2Plugin()
// initialization and cleanup, as plugins are not unloaded on macOS.
}
-void QtQuickControls2Plugin::initializeEngine(QQmlEngine *engine, const char */*uri*/)
+void QtQuickControls2Plugin::registerTypes(const char *uri)
{
- engine->addUrlInterceptor(&QQuickStylePrivate::urlInterceptor);
- init();
-}
+ qCDebug(lcQtQuickControlsStylePlugin) << "registerTypes() called with uri" << uri;
+
+ // It's OK that the style is resolved more than once; some accessors like name() cause it to be called, for example.
+ QQuickStylePrivate::init();
+
+ const QString styleName = QQuickStylePrivate::effectiveStyleName(QQuickStyle::name());
+ const QString fallbackStyleName = QQuickStylePrivate::effectiveStyleName(QQuickStylePrivate::fallbackStyle());
+ qCDebug(lcQtQuickControlsStylePlugin) << "style:" << QQuickStyle::name() << "effective style:" << styleName
+ << "fallback style:" << QQuickStylePrivate::fallbackStyle() << "effective fallback style:" << fallbackStyleName;
+
+ createTheme(styleName);
+
+ // If the style is Default, we don't need to register the fallback because the Default style
+ // provides all controls. Also, if we didn't return early here, we can get an infinite import loop
+ // when the style is set to Default.
+ if (styleName != fallbackStyleName && styleName != QLatin1String("Default")) {
+ const QString fallbackstyleUri = ::fallbackStyleUri();
+ qCDebug(lcQtQuickControlsStylePlugin) << "calling qmlRegisterModuleImport() to register fallback style with"
+ << "uri \"" << qtQuickControlsUri << "\" moduleMajor" << QQmlModuleImportModuleAny << "import" << fallbackstyleUri
+ << "importMajor" << QQmlModuleImportAuto;
+ // The fallback style must be a built-in style, so we match the version number.
+ qmlRegisterModuleImport(qtQuickControlsUri, QQmlModuleImportModuleAny, fallbackstyleUri.toUtf8().constData(),
+ QQmlModuleImportAuto, QQmlModuleImportAuto);
+ registeredFallbackImport = true;
+ }
-void QtQuickControls2Plugin::registerTypes(const char */*uri*/)
-{
- QQuickStylePrivate::init(baseUrl());
+ const QString styleUri = ::styleUri();
+ // If the user imports QtQuick.Controls 2.15, and they're using the Material style, we should import version 2.15.
+ // However, if they import QtQuick.Controls 2.15, but are using a custom style, we want to use the latest version
+ // number of their style.
+ const int importMajor = !QQuickStylePrivate::isCustomStyle() ? QQmlModuleImportAuto : QQmlModuleImportLatest;
+ qCDebug(lcQtQuickControlsStylePlugin).nospace() << "calling qmlRegisterModuleImport() to register primary style with"
+ << " uri \"" << qtQuickControlsUri << "\" moduleMajor " << importMajor << " import " << styleUri
+ << " importMajor " << importMajor;
+ qmlRegisterModuleImport(qtQuickControlsUri, QQmlModuleImportModuleAny, styleUri.toUtf8().constData(), importMajor);
const QString style = QQuickStyle::name();
if (!style.isEmpty())
- QFileSelectorPrivate::addStatics(QStringList() << style.toLower());
+ QFileSelectorPrivate::addStatics(QStringList() << style);
}
void QtQuickControls2Plugin::unregisterTypes()
{
+ qCDebug(lcQtQuickControlsStylePlugin) << "unregisterTypes() called";
+
+ if (registeredFallbackImport) {
+ const QString fallbackStyleUri = ::fallbackStyleUri();
+ qmlUnregisterModuleImport(qtQuickControlsUri, QQmlModuleImportModuleAny, fallbackStyleUri.toUtf8().constData(),
+ QQmlModuleImportAuto, QQmlModuleImportAuto);
+ }
+
+ const QString primary = QQuickStylePrivate::effectiveStyleName(QQuickStyle::name());
+ const QString styleUri = ::styleUri();
+ const int importMajor = !QQuickStylePrivate::isCustomStyle() ? QQmlModuleImportAuto : QQmlModuleImportLatest;
+ qmlUnregisterModuleImport(qtQuickControlsUri, QQmlModuleImportModuleAny, styleUri.toUtf8().constData(), importMajor);
+
QQuickStylePrivate::reset();
}
-void QtQuickControls2Plugin::init()
-{
- const QString style = QQuickStyle::name();
- QQuickTheme *theme = createTheme(style.isEmpty() ? QLatin1String("Default") : style);
+/*!
+ \internal
- // load the style's plugins to get access to its resources and initialize the theme
- QList<QQuickStylePlugin *> stylePlugins = loadStylePlugins();
- for (QQuickStylePlugin *stylePlugin : stylePlugins)
- stylePlugin->initializeTheme(theme);
- qDeleteAll(stylePlugins);
-}
+ Responsible for setting the font and palette settings that were specified in the
+ qtquickcontrols2.conf file.
-QList<QQuickStylePlugin *> QtQuickControls2Plugin::loadStylePlugins()
-{
- QList<QQuickStylePlugin *> 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<QQuickStylePlugin *>(instance);
- if (!stylePlugin || !parser.classNames().contains(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");
-#endif // Q_OS_MACOS && QT_DEBUG
-#if defined(Q_OS_WIN) && defined(QT_DEBUG)
- // Debug versions of plugins have a "d" prefix on Windows.
- filePath += QLatin1Char('d');
-#endif // Q_OS_WIN && QT_DEBUG
- loader.setFileName(filePath);
- QQuickStylePlugin *stylePlugin = qobject_cast<QQuickStylePlugin *>(loader.instance());
- if (stylePlugin)
- stylePlugins += stylePlugin;
- }
-#endif
- }
- }
- }
- return stylePlugins;
-}
+ 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 *QtQuickControls2Plugin::createTheme(const QString &name)
{
+ qCDebug(lcQtQuickControlsStylePlugin) << "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);
diff --git a/src/imports/controls/universal/qmldir b/src/imports/controls/universal/qmldir
index 28bd5706..e2faf020 100644
--- a/src/imports/controls/universal/qmldir
+++ b/src/imports/controls/universal/qmldir
@@ -1,7 +1,7 @@
module QtQuick.Controls.Universal
plugin qtquickcontrols2universalstyleplugin
classname QtQuickControls2UniversalStylePlugin
-depends QtQuick.Controls 2.5
+import QtQuick.Controls.Default auto
# QtQuick.Controls 2.0 (originally introduced in Qt 5.7)
ApplicationWindow 2.0 ApplicationWindow.qml
diff --git a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
index ac154911..d6f7746d 100644
--- a/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
+++ b/src/imports/controls/universal/qtquickcontrols2universalstyleplugin.cpp
@@ -34,11 +34,12 @@
**
****************************************************************************/
-#include <QtQuickControls2/private/qquickstyleplugin_p.h>
-
#include "qquickuniversalstyle_p.h"
#include "qquickuniversaltheme_p.h"
+#include <QtQuickControls2/private/qquickstyleplugin_p.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
+
QT_BEGIN_NAMESPACE
class QtQuickControls2UniversalStylePlugin : public QQuickStylePlugin
@@ -50,12 +51,14 @@ public:
QtQuickControls2UniversalStylePlugin(QObject *parent = nullptr);
QString name() const override;
- void initializeTheme(QQuickTheme *theme) override;
+
+ void registerTypes(const char *uri) override;
+
+ QQuickUniversalTheme theme;
};
QtQuickControls2UniversalStylePlugin::QtQuickControls2UniversalStylePlugin(QObject *parent) : QQuickStylePlugin(parent)
{
- QQuickUniversalStyle::initGlobals();
}
QString QtQuickControls2UniversalStylePlugin::name() const
@@ -63,9 +66,12 @@ QString QtQuickControls2UniversalStylePlugin::name() const
return QStringLiteral("Universal");
}
-void QtQuickControls2UniversalStylePlugin::initializeTheme(QQuickTheme *theme)
+void QtQuickControls2UniversalStylePlugin::registerTypes(const char *uri)
{
- QQuickUniversalTheme::initialize(theme);
+ QQuickStylePlugin::registerTypes(uri);
+
+ QQuickUniversalStyle::initGlobals();
+ theme.initialize(QQuickTheme::instance());
}
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp
index 836eb2f4..72078a0e 100644
--- a/src/quickcontrols2/qquickstyle.cpp
+++ b/src/quickcontrols2/qquickstyle.cpp
@@ -92,54 +92,23 @@ Q_LOGGING_CATEGORY(lcQtQuickControlsStyle, "qt.quick.controls.style")
Qt Quick Controls. It is not possible to change the style after the QML
types have been registered.
- The style can also be specified as a path to a custom style, such as
- \c ":/mystyle". See \l {Creating a Custom Style} for more details about
- building custom styles. Custom styles do not need to implement all controls.
- By default, the styling system uses the \l {Default style} as a fallback
- for controls that a custom style does not provide. It is possible to
- specify a different fallback style to customize or extend one of the
- built-in styles.
+ To create your own custom style, see \l {Creating a Custom Style}. Custom
+ styles do not need to implement all controls. By default, the styling
+ system uses the \l {Default style} as a fallback for controls that a custom
+ style does not provide. It is possible to specify a different fallback
+ style to customize or extend one of the built-in styles.
\code
- QQuickStyle::setStyle(":/mystyle");
+ QQuickStyle::setStyle("MyStyle");
QQuickStyle::setFallbackStyle("Material");
\endcode
\sa {Styling Qt Quick Controls}
*/
-static QStringList envPathList(const QByteArray &var)
-{
- QStringList paths;
- if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty(var))) {
- const QByteArray value = qgetenv(var);
- paths += QString::fromLocal8Bit(value).split(QDir::listSeparator(), Qt::SkipEmptyParts);
- }
- return paths;
-}
-
-static QStringList defaultImportPathList()
-{
- QStringList importPaths;
- importPaths.reserve(3);
-#ifdef Q_OS_ANDROID
- // androiddeployqt puts the QML files inside a resource file and they are not
- // showing up in the Qml2ImportsPath as a result
- importPaths += QStringLiteral(":/android_rcc_bundle/qml");
-#else
-# ifndef QT_STATIC
- importPaths += QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
-# endif
-#endif
- importPaths += envPathList("QML2_IMPORT_PATH");
- importPaths += QStringLiteral(":/qt-project.org/imports");
- importPaths += QCoreApplication::applicationDirPath();
- return importPaths;
-}
-
struct QQuickStyleSpec
{
- QQuickStyleSpec() : custom(false), resolved(false) { }
+ QQuickStyleSpec() { }
QString name()
{
@@ -160,6 +129,13 @@ struct QQuickStyleSpec
void setStyle(const QString &s)
{
+ qCDebug(lcQtQuickControlsStyle) << "style" << s << "set on QQuickStyleSpec";
+ if (s.contains(QLatin1Char('/'))) {
+ qWarning() << "Style names must not contain paths; see the \"Definition of a Style\" documentation for more information";
+ return;
+ }
+
+ qCDebug(lcQtQuickControlsStyle) << "clearing resolved flag and resolving";
style = s;
resolved = false;
resolve();
@@ -171,27 +147,9 @@ struct QQuickStyleSpec
fallbackMethod = method;
}
- static QString findStyle(const QString &path, const QString &name)
+ void resolve()
{
- QDir dir(path);
- if (!dir.exists())
- return QString();
-
- if (name.isEmpty())
- return dir.absolutePath() + QLatin1Char('/');
-
- const QStringList entries = dir.entryList(QStringList(), QDir::Dirs | QDir::NoDotAndDotDot);
- for (const QString &entry : entries) {
- if (entry.compare(name, Qt::CaseInsensitive) == 0)
- return dir.absoluteFilePath(entry);
- }
-
- return QString();
- }
-
- void resolve(const QUrl &baseUrl = QUrl())
- {
- qCDebug(lcQtQuickControlsStyle) << "resolving style with baseUrl" << baseUrl;
+ qCDebug(lcQtQuickControlsStyle) << "resolving style";
if (style.isEmpty())
style = QGuiApplicationPrivate::styleOverride;
@@ -211,53 +169,33 @@ struct QQuickStyleSpec
}
#endif
- // resolve a path relative to the config
- QString configPath = QFileInfo(resolveConfigFilePath()).path();
- QString stylePath = findStyle(configPath, style);
- if (!stylePath.isEmpty()) {
- style = stylePath;
- resolved = true;
+ auto builtInStyleList = QQuickStylePrivate::builtInStyles();
+ if (!fallbackStyle.isEmpty() && !builtInStyleList.contains(fallbackStyle)) {
+ qWarning().nospace().noquote() << fallbackMethod << ": the specified fallback style \"" <<
+ fallbackStyle << "\" is not one of the built-in Qt Quick Controls 2 styles";
+ fallbackStyle.clear();
}
- custom = style.contains(QLatin1Char('/'));
+ // Find the config file.
+ resolveConfigFilePath();
- if (baseUrl.isValid()) {
- QString path = QQmlFile::urlToLocalFileOrQrc(baseUrl);
- QString stylePath = findStyle(path, style);
- if (!stylePath.isEmpty()) {
- style = stylePath;
- resolved = true;
- }
- }
+ custom = !builtInStyleList.contains(QQuickStylePrivate::effectiveStyleName(style));
- if (QGuiApplication::instance()) {
- if (!custom) {
- const QStringList stylePaths = QQuickStylePrivate::stylePaths();
- for (const QString &path : stylePaths) {
- QString stylePath = findStyle(path, style);
- if (!stylePath.isEmpty()) {
- custom = !stylePath.startsWith(QQmlFile::urlToLocalFileOrQrc(baseUrl));
- style = stylePath;
- resolved = true;
- break;
- }
- }
- }
- resolved = true;
- }
+ resolved = true;
qCDebug(lcQtQuickControlsStyle).nospace() << "done resolving:"
+ << "\n style=" << style
<< "\n custom=" << custom
<< "\n resolved=" << resolved
- << "\n style=" << style
<< "\n fallbackStyle=" << fallbackStyle
<< "\n fallbackMethod=" << fallbackMethod
- << "\n configFilePath=" << configFilePath
- << "\n customStylePaths=" << customStylePaths;
+ << "\n configFilePath=" << configFilePath;
}
void reset()
{
+ qCDebug(lcQtQuickControlsStyle) << "resetting values to their defaults";
+
custom = false;
resolved = false;
style.clear();
@@ -281,10 +219,10 @@ struct QQuickStyleSpec
}
// Is this a custom style defined by the user and not "built-in" style?
- bool custom;
- // Did we manage to find a valid style path?
- bool resolved;
- // The full path to the style.
+ bool custom = false;
+ // Have we resolved the style yet?
+ bool resolved = false;
+ // The name of the style.
QString style;
// The built-in style to use if the requested style cannot be found.
QString fallbackStyle;
@@ -292,102 +230,13 @@ struct QQuickStyleSpec
QByteArray fallbackMethod;
// The path to the qtquickcontrols2.conf file.
QString configFilePath;
- // An extra list of directories where we search for available styles before any other directories.
- QStringList customStylePaths;
};
Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec)
-static QStringList parseStylePathsWithColon(const QString &var)
+QString QQuickStylePrivate::effectiveStyleName(const QString &styleName)
{
- QStringList paths;
- const QChar colon = QLatin1Char(':');
- int currentIndex = 0;
-
- do {
- int nextColonIndex = -1;
- QString path;
-
- if (var.at(currentIndex) == colon) {
- // This is either a list separator, or a qrc path.
- if (var.at(currentIndex + 1) == colon) {
- // It's a double colon (list separator followed by qrc path);
- // find the end of the path.
- nextColonIndex = var.indexOf(colon, currentIndex + 2);
- path = var.mid(currentIndex + 1,
- nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex - 1);
- } else {
- // It's a single colon.
- nextColonIndex = var.indexOf(colon, currentIndex + 1);
- if (currentIndex == 0) {
- // If we're at the start of the string, then it's a qrc path.
- path = var.mid(currentIndex,
- nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex);
- } else {
- // Otherwise, it's a separator.
- path = var.mid(currentIndex + 1,
- nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex - 1);
- }
- }
- } else {
- // It's a file path.
- nextColonIndex = var.indexOf(colon, currentIndex);
- path = var.mid(currentIndex,
- nextColonIndex == -1 ? -1 : nextColonIndex - currentIndex);
- }
-
- paths += path;
- currentIndex = nextColonIndex;
-
- // Keep going until we can't find any more colons,
- // or we're at the last character.
- } while (currentIndex != -1 && currentIndex < var.size() - 1);
-
- return paths;
-}
-
-QStringList QQuickStylePrivate::stylePaths(bool resolve)
-{
- // user-requested style path
- QStringList paths;
- if (resolve) {
- QString path = styleSpec()->path();
- if (path.endsWith(QLatin1Char('/')))
- path.chop(1);
- if (!path.isEmpty())
- paths += path;
- }
-
- if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE_PATH"))) {
- const QString value = QString::fromLocal8Bit(qgetenv("QT_QUICK_CONTROLS_STYLE_PATH"));
- const QChar listSeparator = QDir::listSeparator();
- if (listSeparator == QLatin1Char(':')) {
- // Split manually to avoid breaking paths on systems where : is the list separator,
- // since it's also used for qrc paths.
- paths += parseStylePathsWithColon(value);
- } else {
- // Fast/simpler path for systems where something other than : is used as
- // the list separator (such as ';').
- const QStringList customPaths = value.split(listSeparator, Qt::SkipEmptyParts);
- paths += customPaths;
- }
- }
-
- // system/custom style paths
- paths += styleSpec()->customStylePaths;
- paths += envPathList("QT_QUICK_CONTROLS_STYLE_PATH");
-
- // built-in import paths
- const QString targetPath = QStringLiteral("QtQuick/Controls");
- const QStringList importPaths = defaultImportPathList();
- for (const QString &importPath : importPaths) {
- QDir dir(importPath);
- if (dir.cd(targetPath))
- paths += dir.absolutePath();
- }
-
- paths.removeDuplicates();
- return paths;
+ return !styleName.isEmpty() ? styleName : QLatin1String("Default");
}
QString QQuickStylePrivate::fallbackStyle()
@@ -400,27 +249,15 @@ bool QQuickStylePrivate::isCustomStyle()
return styleSpec()->custom;
}
-void QQuickStylePrivate::init(const QUrl &baseUrl)
+bool QQuickStylePrivate::isResolved()
+{
+ return styleSpec()->resolved;
+}
+
+void QQuickStylePrivate::init()
{
QQuickStyleSpec *spec = styleSpec();
- spec->resolve(baseUrl);
-
- if (!spec->fallbackStyle.isEmpty()) {
- QString fallbackStyle;
- const QStringList stylePaths = QQuickStylePrivate::stylePaths();
- for (const QString &path : stylePaths) {
- fallbackStyle = spec->findStyle(path, spec->fallbackStyle);
- if (!fallbackStyle.isEmpty())
- break;
- }
- if (fallbackStyle.isEmpty()) {
- if (spec->fallbackStyle.compare(QStringLiteral("Default")) != 0) {
- qWarning() << "ERROR: unable to locate fallback style" << spec->fallbackStyle;
- qInfo().nospace().noquote() << spec->fallbackMethod << ": the fallback style must be the name of one of the built-in Qt Quick Controls 2 styles.";
- }
- spec->fallbackStyle.clear();
- }
- }
+ spec->resolve();
}
void QQuickStylePrivate::reset()
@@ -541,6 +378,12 @@ bool QQuickStylePrivate::isDarkSystemTheme()
return dark;
}
+QStringList QQuickStylePrivate::builtInStyles()
+{
+ return { QLatin1String("Default"), QLatin1String("Fusion"),
+ QLatin1String("Imagine"), QLatin1String("Material"), QLatin1String("Universal") };
+}
+
/*!
Returns the name of the application style.
@@ -554,19 +397,6 @@ QString QQuickStyle::name()
}
/*!
- Returns the path of an overridden application style, or an empty
- string if the style is one of the built-in Qt Quick Controls 2 styles.
-
- \note The application style can be specified by passing a \c -style command
- line argument. Therefore \c path() may not return a fully resolved
- value if called before constructing a QGuiApplication.
-*/
-QString QQuickStyle::path()
-{
- return styleSpec()->path();
-}
-
-/*!
Sets the application style to \a style.
\note The style must be configured \b before loading QML that imports Qt Quick Controls.
@@ -612,88 +442,4 @@ void QQuickStyle::setFallbackStyle(const QString &style)
styleSpec()->setFallbackStyle(style, "QQuickStyle::setFallbackStyle()");
}
-/*!
- \since 5.9
- Returns the names of the available styles.
-
- \note The method must be called \b after creating an instance of QGuiApplication.
-
- \sa stylePathList(), addStylePath()
-*/
-QStringList QQuickStyle::availableStyles()
-{
- QStringList styles;
- if (!QGuiApplication::instance()) {
- qWarning() << "ERROR: QQuickStyle::availableStyles() must be called after creating an instance of QGuiApplication.";
- return styles;
- }
-
- const QStringList stylePaths = QQuickStylePrivate::stylePaths();
- for (const QString &path : stylePaths) {
- const QList<QFileInfo> entries = QDir(path).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
- for (const QFileInfo &entry : entries) {
- const QString name = entry.fileName();
- if (!name.endsWith(QLatin1String(".dSYM")) && name != QLatin1String("designer"))
- styles += name;
- }
- }
- styles.prepend(QStringLiteral("Default"));
- styles.removeDuplicates();
- return styles;
-}
-
-/*!
- \since 5.12
-
- Returns the list of directories where Qt Quick Controls 2 searches for available styles.
-
- By default, the list contains paths specified in the \c QT_QUICK_CONTROLS_STYLE_PATH
- environment variable, and any existing \c QtQuick/Controls sub-directories in
- \l QQmlEngine::importPathList().
-
- \sa addStylePath(), availableStyles()
-*/
-QStringList QQuickStyle::stylePathList()
-{
- return QQuickStylePrivate::stylePaths();
-}
-
-/*!
- \since 5.12
-
- Adds \a path as a directory where Qt Quick Controls 2 searches for available styles.
-
- The \a path may be any local filesystem directory or \l {The Qt Resource System}{Qt Resource} directory.
- For example, the following paths are all valid:
-
- \list
- \li \c {/path/to/styles/}
- \li \c {file:///path/to/styles/}
- \li \c {:/path/to/styles/}
- \li \c {qrc:/path/to/styles/})
- \endlist
-
- The \a path will be converted into \l {QDir::canonicalPath}{canonical form} before it is added to
- the style path list.
-
- The newly added \a path will be first in the stylePathList().
-
- \sa stylePathList(), availableStyles()
-*/
-void QQuickStyle::addStylePath(const QString &path)
-{
- if (path.isEmpty())
- return;
-
- const QUrl url = QUrl(path);
- if (url.isRelative() || url.scheme() == QLatin1String("file")
- || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path
- styleSpec()->customStylePaths.prepend(QDir(path).canonicalPath());
- } else if (url.scheme() == QLatin1String("qrc")) {
- styleSpec()->customStylePaths.prepend(QLatin1Char(':') + url.path());
- } else {
- styleSpec()->customStylePaths.prepend(path);
- }
-}
-
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyle.h b/src/quickcontrols2/qquickstyle.h
index ce55b76b..e26ec90b 100644
--- a/src/quickcontrols2/qquickstyle.h
+++ b/src/quickcontrols2/qquickstyle.h
@@ -47,12 +47,8 @@ class Q_QUICKCONTROLS2_EXPORT QQuickStyle
{
public:
static QString name();
- static QString path();
static void setStyle(const QString &style);
static void setFallbackStyle(const QString &style);
- static QStringList availableStyles();
- static QStringList stylePathList();
- static void addStylePath(const QString &path);
};
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyle_p.h b/src/quickcontrols2/qquickstyle_p.h
index 7c837423..e2db35d7 100644
--- a/src/quickcontrols2/qquickstyle_p.h
+++ b/src/quickcontrols2/qquickstyle_p.h
@@ -48,7 +48,6 @@
// We mean it.
//
-#include <QtCore/qurl.h>
#include <QtCore/qsharedpointer.h>
#include <QtQuickControls2/qtquickcontrols2global.h>
@@ -59,16 +58,19 @@ class QSettings;
class Q_QUICKCONTROLS2_EXPORT QQuickStylePrivate
{
public:
- static QStringList stylePaths(bool resolve = false);
+ static QString effectiveStyleName(const QString &styleName);
static QString fallbackStyle();
static bool isCustomStyle();
- static void init(const QUrl &baseUrl);
+ static bool isResolved();
+ static bool exists();
+ static void init();
static void reset();
static QString configFilePath();
static QSharedPointer<QSettings> settings(const QString &group = QString());
static const QFont *readFont(const QSharedPointer<QSettings> &settings);
static const QPalette *readPalette(const QSharedPointer<QSettings> &settings);
static bool isDarkSystemTheme();
+ static QStringList builtInStyles();
};
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyleplugin.cpp b/src/quickcontrols2/qquickstyleplugin.cpp
index 18f0d485..1f1c3875 100644
--- a/src/quickcontrols2/qquickstyleplugin.cpp
+++ b/src/quickcontrols2/qquickstyleplugin.cpp
@@ -34,14 +34,20 @@
**
****************************************************************************/
+#include "qquickstyle.h"
#include "qquickstyle_p.h"
#include "qquickstyleplugin_p.h"
+#include <QtCore/qloggingcategory.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlfile.h>
+#include <QtQuickTemplates2/private/qquicktheme_p_p.h>
+
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcStylePlugin, "qt.quick.controls.styleplugin")
+
QQuickStylePlugin::QQuickStylePlugin(QObject *parent)
: QQmlExtensionPlugin(parent)
{
@@ -56,4 +62,14 @@ QString QQuickStylePlugin::name() const
return QString();
}
+void QQuickStylePlugin::registerTypes(const char *uri)
+{
+ qCDebug(lcStylePlugin).nospace() << "registerTypes called with uri " << uri << "; plugin name is " << name();
+}
+
+void QQuickStylePlugin::unregisterTypes()
+{
+ qCDebug(lcStylePlugin) << "unregisterTypes called; plugin name is" << name();
+}
+
QT_END_NAMESPACE
diff --git a/src/quickcontrols2/qquickstyleplugin_p.h b/src/quickcontrols2/qquickstyleplugin_p.h
index 7ae129d9..37d070db 100644
--- a/src/quickcontrols2/qquickstyleplugin_p.h
+++ b/src/quickcontrols2/qquickstyleplugin_p.h
@@ -64,9 +64,9 @@ public:
~QQuickStylePlugin();
virtual QString name() const;
- virtual void initializeTheme(QQuickTheme *theme) = 0;
void registerTypes(const char *uri) override;
+ void unregisterTypes() override;
private:
Q_DISABLE_COPY(QQuickStylePlugin)