diff options
Diffstat (limited to 'src/quickcontrols2/qquickstyle.cpp')
-rw-r--r-- | src/quickcontrols2/qquickstyle.cpp | 177 |
1 files changed, 166 insertions, 11 deletions
diff --git a/src/quickcontrols2/qquickstyle.cpp b/src/quickcontrols2/qquickstyle.cpp index 73c604de..b4901db3 100644 --- a/src/quickcontrols2/qquickstyle.cpp +++ b/src/quickcontrols2/qquickstyle.cpp @@ -43,7 +43,9 @@ #include <QtCore/qsettings.h> #include <QtCore/qfileselector.h> #include <QtCore/qlibraryinfo.h> +#include <QtCore/qmetaobject.h> #include <QtGui/qcolor.h> +#include <QtGui/qfont.h> #include <QtGui/qpalette.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpa/qplatformtheme.h> @@ -51,6 +53,8 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlfile.h> +#include <functional> + QT_BEGIN_NAMESPACE /*! @@ -101,19 +105,25 @@ QT_BEGIN_NAMESPACE \sa {Styling Qt Quick Controls 2} */ -// TODO: QQmlImportDatabase::defaultImportPathList() +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(), QString::SkipEmptyParts); + } + return paths; +} + static QStringList defaultImportPathList() { QStringList importPaths; importPaths.reserve(3); +#ifndef QT_STATIC importPaths += QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath); - - if (Q_UNLIKELY(!qEnvironmentVariableIsEmpty("QML2_IMPORT_PATH"))) { - const QByteArray envImportPath = qgetenv("QML2_IMPORT_PATH"); - importPaths += QString::fromLocal8Bit(envImportPath).split(QDir::listSeparator(), QString::SkipEmptyParts); - } - - importPaths += QStringLiteral("qrc:/qt-project.org/imports"); +#endif + importPaths += envPathList("QML2_IMPORT_PATH"); + importPaths += QStringLiteral(":/qt-project.org/imports"); importPaths += QCoreApplication::applicationDirPath(); return importPaths; } @@ -256,6 +266,7 @@ struct QQuickStyleSpec QString fallbackStyle; QByteArray fallbackMethod; QString configFilePath; + QStringList customStylePaths; }; Q_GLOBAL_STATIC(QQuickStyleSpec, styleSpec) @@ -308,10 +319,18 @@ static QStringList parseStylePathsWithColon(const QString &var) return paths; } -QStringList QQuickStylePrivate::stylePaths() +QStringList QQuickStylePrivate::stylePaths(bool resolve) { - // system/custom style paths + // 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(); @@ -327,6 +346,10 @@ QStringList QQuickStylePrivate::stylePaths() } } + // system/custom style paths + paths += styleSpec()->customStylePaths; + paths += envPathList("QT_QUICK_CONTROLS_STYLE_PATH"); + // built-in import paths const QString targetPath = QStringLiteral("QtQuick/Controls.2"); const QStringList importPaths = defaultImportPathList(); @@ -336,6 +359,7 @@ QStringList QQuickStylePrivate::stylePaths() paths += dir.absolutePath(); } + paths.removeDuplicates(); return paths; } @@ -392,6 +416,81 @@ QSharedPointer<QSettings> QQuickStylePrivate::settings(const QString &group) return QSharedPointer<QSettings>(); } +#if QT_CONFIG(settings) +static void readValue(const QSharedPointer<QSettings> &settings, const QString &name, std::function<void(const QVariant &)> setValue) +{ + const QVariant var = settings->value(name); + if (var.isValid()) + setValue(var); +} + +template <typename Enum> +static Enum toEnumValue(const QVariant &var) +{ + // ### TODO: expose QFont enums to the meta object system using Q_ENUM + //QMetaEnum enumeration = QMetaEnum::fromType<Enum>(); + //bool ok = false; + //int value = enumeration.keyToValue(var.toByteArray(), &ok); + //if (!ok) + // value = var.toInt(); + //return static_cast<Enum>(value); + + return static_cast<Enum>(var.toInt()); +} + +const QFont *QQuickStylePrivate::readFont(const QSharedPointer<QSettings> &settings) +{ + const QVariant var = settings->value(QStringLiteral("Font")); + if (var.isValid()) + return new QFont(var.value<QFont>()); + + QFont f; + settings->beginGroup(QStringLiteral("Font")); + readValue(settings, QStringLiteral("Family"), [&f](const QVariant &var) { f.setFamily(var.toString()); }); + readValue(settings, QStringLiteral("PointSize"), [&f](const QVariant &var) { f.setPointSizeF(var.toReal()); }); + readValue(settings, QStringLiteral("PixelSize"), [&f](const QVariant &var) { f.setPixelSize(var.toInt()); }); + readValue(settings, QStringLiteral("StyleHint"), [&f](const QVariant &var) { f.setStyleHint(toEnumValue<QFont::StyleHint>(var.toInt())); }); + readValue(settings, QStringLiteral("Weight"), [&f](const QVariant &var) { f.setWeight(toEnumValue<QFont::Weight>(var)); }); + readValue(settings, QStringLiteral("Style"), [&f](const QVariant &var) { f.setStyle(toEnumValue<QFont::Style>(var.toInt())); }); + settings->endGroup(); + return new QFont(f); +} + +static void readColorGroup(const QSharedPointer<QSettings> &settings, QPalette::ColorGroup group, QPalette *palette) +{ + const QStringList keys = settings->childKeys(); + if (keys.isEmpty()) + return; + + static const int index = QPalette::staticMetaObject.indexOfEnumerator("ColorRole"); + Q_ASSERT(index != -1); + QMetaEnum metaEnum = QPalette::staticMetaObject.enumerator(index); + + for (const QString &key : keys) { + bool ok = false; + int role = metaEnum.keyToValue(key.toUtf8(), &ok); + if (ok) + palette->setColor(group, static_cast<QPalette::ColorRole>(role), settings->value(key).value<QColor>()); + } +} + +const QPalette *QQuickStylePrivate::readPalette(const QSharedPointer<QSettings> &settings) +{ + QPalette p; + settings->beginGroup(QStringLiteral("Palette")); + readColorGroup(settings, QPalette::All, &p); + + settings->beginGroup(QStringLiteral("Normal")); + readColorGroup(settings, QPalette::Normal, &p); + settings->endGroup(); + + settings->beginGroup(QStringLiteral("Disabled")); + readColorGroup(settings, QPalette::Disabled, &p); + settings->endGroup(); + return new QPalette(p); +} +#endif // QT_CONFIG(settings) + static bool qt_is_dark_system_theme() { if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { @@ -478,9 +577,11 @@ void QQuickStyle::setFallbackStyle(const QString &style) /*! \since 5.9 - Returns the names of the available built-in styles. + 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() { @@ -504,4 +605,58 @@ QStringList QQuickStyle::availableStyles() 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.2 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 |