1/*
2 * SPDX-FileCopyrightText: 2021 Arjen Hiemstra <ahiemstra@heimr.nl>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "styleselector.h"
8
9#include <QDir>
10#include <QFile>
11#include <QQuickStyle>
12#include <kirigamiplatform_logging.h>
13
14namespace Kirigami
15{
16namespace Platform
17{
18
19QString StyleSelector::style()
20{
21 if (qEnvironmentVariableIntValue(varName: "KIRIGAMI_FORCE_STYLE") == 1) {
22 return QQuickStyle::name();
23 } else {
24 return styleChain().first();
25 }
26}
27
28QStringList StyleSelector::styleChain()
29{
30 if (qEnvironmentVariableIntValue(varName: "KIRIGAMI_FORCE_STYLE") == 1) {
31 return {QQuickStyle::name()};
32 }
33
34 if (!s_styleChain.isEmpty()) {
35 return s_styleChain;
36 }
37
38 auto style = QQuickStyle::name();
39
40#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
41 // org.kde.desktop.plasma is a couple of files that fall back to desktop by purpose
42 if (style.isEmpty() || style == QStringLiteral("org.kde.desktop.plasma")) {
43 auto path = resolveFilePath(QStringLiteral("/styles/org.kde.desktop"));
44 if (QFile::exists(fileName: path)) {
45 s_styleChain.prepend(QStringLiteral("org.kde.desktop"));
46 }
47 }
48#elif defined(Q_OS_ANDROID)
49 s_styleChain.prepend(QStringLiteral("Material"));
50#else // do we have an iOS specific style?
51 s_styleChain.prepend(QStringLiteral("Material"));
52#endif
53
54 auto stylePath = resolveFilePath(QStringLiteral("/styles/") + style);
55 if (!style.isEmpty() && QFile::exists(fileName: stylePath) && !s_styleChain.contains(str: style)) {
56 s_styleChain.prepend(t: style);
57 // if we have plasma deps installed, use them for extra integration
58 auto plasmaPath = resolveFilePath(QStringLiteral("/styles/org.kde.desktop.plasma"));
59 if (style == QStringLiteral("org.kde.desktop") && QFile::exists(fileName: plasmaPath)) {
60 s_styleChain.prepend(QStringLiteral("org.kde.desktop.plasma"));
61 }
62 } else {
63#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
64 s_styleChain.prepend(QStringLiteral("org.kde.desktop"));
65#endif
66 }
67
68 return s_styleChain;
69}
70
71QUrl StyleSelector::componentUrl(const QString &fileName)
72{
73 const auto chain = styleChain();
74 for (const QString &style : chain) {
75 const QString candidate = QStringLiteral("styles/") + style + QLatin1Char('/') + fileName;
76 if (QFile::exists(fileName: resolveFilePath(path: candidate))) {
77 return QUrl(resolveFileUrl(path: candidate));
78 }
79 }
80
81 if (!QFile::exists(fileName: resolveFilePath(path: fileName))) {
82 qCWarning(KirigamiPlatform) << "Requested an unexisting component" << fileName;
83 }
84 return QUrl(resolveFileUrl(path: fileName));
85}
86
87void StyleSelector::setBaseUrl(const QUrl &baseUrl)
88{
89 s_baseUrl = baseUrl;
90}
91
92QString StyleSelector::resolveFilePath(const QString &path)
93{
94#if defined(KIRIGAMI_BUILD_TYPE_STATIC) || defined(Q_OS_ANDROID)
95 return QStringLiteral(":/qt/qml/org/kde/kirigami/") + path;
96#else
97 if (s_baseUrl.isValid()) {
98 return s_baseUrl.toLocalFile() + QLatin1Char('/') + path;
99 } else {
100 return QDir::currentPath() + QLatin1Char('/') + path;
101 }
102#endif
103}
104
105QString StyleSelector::resolveFileUrl(const QString &path)
106{
107#if defined(KIRIGAMI_BUILD_TYPE_STATIC) || defined(Q_OS_ANDROID)
108 return QStringLiteral("qrc:/qt/qml/org/kde/kirigami/") + path;
109#else
110 return s_baseUrl.toString() + QLatin1Char('/') + path;
111#endif
112}
113
114}
115}
116

source code of kirigami/src/platform/styleselector.cpp