1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
3 | |
4 | #include "qqmltoolingsettings_p.h" |
5 | |
6 | #include <QtCore/qdebug.h> |
7 | #include <QtCore/qdir.h> |
8 | #include <QtCore/qfileinfo.h> |
9 | #include <QtCore/qset.h> |
10 | #if QT_CONFIG(settings) |
11 | #include <QtCore/qsettings.h> |
12 | #endif |
13 | #include <QtCore/qstandardpaths.h> |
14 | |
15 | using namespace Qt::StringLiterals; |
16 | |
17 | void QQmlToolingSettings::addOption(const QString &name, QVariant defaultValue) |
18 | { |
19 | if (defaultValue.isValid()) { |
20 | m_values[name] = defaultValue; |
21 | } |
22 | } |
23 | |
24 | bool QQmlToolingSettings::read(const QString &settingsFilePath) |
25 | { |
26 | #if QT_CONFIG(settings) |
27 | if (!QFileInfo::exists(file: settingsFilePath)) |
28 | return false; |
29 | |
30 | if (m_currentSettingsPath == settingsFilePath) |
31 | return true; |
32 | |
33 | QSettings settings(settingsFilePath, QSettings::IniFormat); |
34 | |
35 | for (const QString &key : settings.allKeys()) |
36 | m_values[key] = settings.value(key).toString(); |
37 | |
38 | m_currentSettingsPath = settingsFilePath; |
39 | |
40 | return true; |
41 | #else |
42 | Q_UNUSED(settingsFilePath); |
43 | return false; |
44 | #endif |
45 | } |
46 | |
47 | bool QQmlToolingSettings::writeDefaults() const |
48 | { |
49 | #if QT_CONFIG(settings) |
50 | const QString path = QFileInfo(u".%1.ini"_s .arg(a: m_toolName)).absoluteFilePath(); |
51 | |
52 | QSettings settings(path, QSettings::IniFormat); |
53 | for (auto it = m_values.constBegin(); it != m_values.constEnd(); ++it) { |
54 | settings.setValue(key: it.key(), value: it.value().isNull() ? QString() : it.value()); |
55 | } |
56 | |
57 | settings.sync(); |
58 | |
59 | if (settings.status() != QSettings::NoError) { |
60 | qWarning() << "Failed to write default settings to" << path |
61 | << "Error:" << settings.status(); |
62 | return false; |
63 | } |
64 | |
65 | qInfo() << "Wrote default settings to" << path; |
66 | return true; |
67 | #else |
68 | return false; |
69 | #endif |
70 | } |
71 | |
72 | bool QQmlToolingSettings::search(const QString &path) |
73 | { |
74 | #if QT_CONFIG(settings) |
75 | QFileInfo fileInfo(path); |
76 | QDir dir(fileInfo.isDir() ? path : fileInfo.dir()); |
77 | |
78 | QSet<QString> dirs; |
79 | |
80 | const QString settingsFileName = u".%1.ini"_s .arg(a: m_toolName); |
81 | |
82 | while (dir.exists() && dir.isReadable()) { |
83 | const QString dirPath = dir.absolutePath(); |
84 | |
85 | if (m_seenDirectories.contains(key: dirPath)) { |
86 | const QString cachedIniPath = m_seenDirectories[dirPath]; |
87 | if (cachedIniPath.isEmpty()) |
88 | return false; |
89 | |
90 | return read(settingsFilePath: cachedIniPath); |
91 | } |
92 | |
93 | dirs << dirPath; |
94 | |
95 | const QString iniFile = dir.absoluteFilePath(fileName: settingsFileName); |
96 | |
97 | if (read(settingsFilePath: iniFile)) { |
98 | for (const QString &dir : std::as_const(t&: dirs)) |
99 | m_seenDirectories[dir] = iniFile; |
100 | return true; |
101 | } |
102 | |
103 | if (!dir.cdUp()) |
104 | break; |
105 | } |
106 | |
107 | if (const QString iniFile = QStandardPaths::locate(type: QStandardPaths::GenericConfigLocation, fileName: u"%1.ini"_s .arg(a: m_toolName)); |
108 | !iniFile.isEmpty()) { |
109 | if (read(settingsFilePath: iniFile)) { |
110 | for (const QString &dir : std::as_const(t&: dirs)) |
111 | m_seenDirectories[dir] = iniFile; |
112 | return true; |
113 | } |
114 | } |
115 | |
116 | // No INI file found anywhere, record the failure so we won't have to traverse the entire |
117 | // filesystem again |
118 | for (const QString &dir : std::as_const(t&: dirs)) |
119 | m_seenDirectories[dir] = QString(); |
120 | |
121 | #endif |
122 | Q_UNUSED(path); |
123 | return false; |
124 | } |
125 | |
126 | QVariant QQmlToolingSettings::value(QString name) const |
127 | { |
128 | return m_values.value(key: name); |
129 | } |
130 | |
131 | bool QQmlToolingSettings::isSet(QString name) const |
132 | { |
133 | if (!m_values.contains(key: name)) |
134 | return false; |
135 | |
136 | QVariant variant = m_values[name]; |
137 | |
138 | // Unset is encoded as an empty string |
139 | return !(variant.canConvert(targetType: QMetaType(QMetaType::QString)) && variant.toString().isEmpty()); |
140 | } |
141 | |