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 | |
14 | namespace Kirigami |
15 | { |
16 | namespace Platform |
17 | { |
18 | |
19 | QString StyleSelector::style() |
20 | { |
21 | if (qEnvironmentVariableIntValue(varName: "KIRIGAMI_FORCE_STYLE" ) == 1) { |
22 | return QQuickStyle::name(); |
23 | } else { |
24 | return styleChain().first(); |
25 | } |
26 | } |
27 | |
28 | QStringList 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 | |
71 | QUrl 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 | |
87 | void StyleSelector::setBaseUrl(const QUrl &baseUrl) |
88 | { |
89 | s_baseUrl = baseUrl; |
90 | } |
91 | |
92 | QString 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 | |
105 | QString 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 | |