1 | // Copyright (C) 2020 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "helpdocsettings.h" |
5 | |
6 | #include <QtHelp/QCompressedHelpInfo> |
7 | #include <QtHelp/QHelpEngineCore> |
8 | #include <QtHelp/QHelpFilterEngine> |
9 | |
10 | #include <QtCore/QVersionNumber> |
11 | |
12 | #include <QtDebug> |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | class HelpDocSettingsPrivate : public QSharedData |
17 | { |
18 | public: |
19 | HelpDocSettingsPrivate() = default; |
20 | HelpDocSettingsPrivate(const HelpDocSettingsPrivate &other) = default; |
21 | ~HelpDocSettingsPrivate() = default; |
22 | |
23 | QMap<QString, QString> m_namespaceToComponent; |
24 | QMap<QString, QStringList> m_componentToNamespace; |
25 | |
26 | QMap<QString, QVersionNumber> m_namespaceToVersion; |
27 | QMap<QVersionNumber, QStringList> m_versionToNamespace; |
28 | |
29 | QMap<QString, QString> m_namespaceToFileName; |
30 | QMap<QString, QString> m_fileNameToNamespace; |
31 | }; |
32 | |
33 | |
34 | HelpDocSettings::HelpDocSettings() |
35 | : d(new HelpDocSettingsPrivate) |
36 | { |
37 | } |
38 | |
39 | HelpDocSettings::HelpDocSettings(const HelpDocSettings &) = default; |
40 | |
41 | HelpDocSettings::HelpDocSettings(HelpDocSettings &&) = default; |
42 | |
43 | HelpDocSettings::~HelpDocSettings() = default; |
44 | |
45 | HelpDocSettings &HelpDocSettings::operator=(const HelpDocSettings &) = default; |
46 | |
47 | HelpDocSettings &HelpDocSettings::operator=(HelpDocSettings &&) = default; |
48 | |
49 | bool HelpDocSettings::addDocumentation(const QString &fileName) |
50 | { |
51 | const QCompressedHelpInfo info = QCompressedHelpInfo::fromCompressedHelpFile(documentationFileName: fileName); |
52 | |
53 | if (info.isNull()) |
54 | return false; |
55 | |
56 | const QString namespaceName = info.namespaceName(); |
57 | |
58 | if (d->m_namespaceToFileName.contains(key: namespaceName)) |
59 | return false; |
60 | |
61 | if (d->m_fileNameToNamespace.contains(key: fileName)) |
62 | return false; |
63 | |
64 | const QString component = info.component(); |
65 | const QVersionNumber version = info.version(); |
66 | |
67 | d->m_namespaceToFileName.insert(key: namespaceName, value: fileName); |
68 | d->m_fileNameToNamespace.insert(key: fileName, value: namespaceName); |
69 | |
70 | d->m_namespaceToComponent.insert(key: namespaceName, value: component); |
71 | d->m_componentToNamespace[component].append(t: namespaceName); |
72 | |
73 | d->m_namespaceToVersion.insert(key: namespaceName, value: version); |
74 | d->m_versionToNamespace[version].append(t: namespaceName); |
75 | |
76 | return true; |
77 | } |
78 | |
79 | bool HelpDocSettings::removeDocumentation(const QString &namespaceName) |
80 | { |
81 | if (namespaceName.isEmpty()) |
82 | return false; |
83 | |
84 | const QString fileName = d->m_namespaceToFileName.value(key: namespaceName); |
85 | if (fileName.isEmpty()) |
86 | return false; |
87 | |
88 | const QString component = d->m_namespaceToComponent.value(key: namespaceName); |
89 | const QVersionNumber version = d->m_namespaceToVersion.value(key: namespaceName); |
90 | |
91 | d->m_namespaceToComponent.remove(key: namespaceName); |
92 | d->m_namespaceToVersion.remove(key: namespaceName); |
93 | d->m_namespaceToFileName.remove(key: namespaceName); |
94 | d->m_fileNameToNamespace.remove(key: fileName); |
95 | d->m_componentToNamespace[component].removeOne(t: namespaceName); |
96 | if (d->m_componentToNamespace[component].isEmpty()) |
97 | d->m_componentToNamespace.remove(key: component); |
98 | d->m_versionToNamespace[version].removeOne(t: namespaceName); |
99 | if (d->m_versionToNamespace[version].isEmpty()) |
100 | d->m_versionToNamespace.remove(key: version); |
101 | |
102 | return true; |
103 | } |
104 | |
105 | QString HelpDocSettings::namespaceName(const QString &fileName) const |
106 | { |
107 | return d->m_fileNameToNamespace.value(key: fileName); |
108 | } |
109 | |
110 | QStringList HelpDocSettings::components() const |
111 | { |
112 | return d->m_componentToNamespace.keys(); |
113 | } |
114 | |
115 | QList<QVersionNumber> HelpDocSettings::versions() const |
116 | { |
117 | return d->m_versionToNamespace.keys(); |
118 | } |
119 | |
120 | QStringList HelpDocSettings::namespaces() const |
121 | { |
122 | return d->m_namespaceToFileName.keys(); |
123 | } |
124 | |
125 | QMap<QString, QString> HelpDocSettings::namespaceToFileName() const |
126 | { |
127 | return d->m_namespaceToFileName; |
128 | } |
129 | |
130 | HelpDocSettings HelpDocSettings::readSettings(QHelpEngineCore *helpEngine) |
131 | { |
132 | QHelpFilterEngine *filterEngine = helpEngine->filterEngine(); |
133 | |
134 | HelpDocSettings docSettings; |
135 | docSettings.d->m_namespaceToComponent = filterEngine->namespaceToComponent(); |
136 | docSettings.d->m_namespaceToVersion = filterEngine->namespaceToVersion(); |
137 | for (auto it = docSettings.d->m_namespaceToComponent.constBegin(); |
138 | it != docSettings.d->m_namespaceToComponent.constEnd(); ++it) { |
139 | const QString namespaceName = it.key(); |
140 | const QString namespaceFileName = helpEngine->documentationFileName(namespaceName); |
141 | docSettings.d->m_namespaceToFileName.insert(key: namespaceName, value: namespaceFileName); |
142 | docSettings.d->m_fileNameToNamespace.insert(key: namespaceFileName, value: namespaceName); |
143 | docSettings.d->m_componentToNamespace[it.value()].append(t: namespaceName); |
144 | } |
145 | for (auto it = docSettings.d->m_namespaceToVersion.constBegin(); |
146 | it != docSettings.d->m_namespaceToVersion.constEnd(); ++it) { |
147 | docSettings.d->m_versionToNamespace[it.value()].append(t: it.key()); |
148 | } |
149 | |
150 | return docSettings; |
151 | } |
152 | |
153 | static QMap<QString, QString> subtract(const QMap<QString, QString> &minuend, |
154 | const QMap<QString, QString> &subtrahend) |
155 | { |
156 | auto result = minuend; |
157 | |
158 | for (auto itSubtrahend = subtrahend.cbegin(); itSubtrahend != subtrahend.cend(); ++itSubtrahend) { |
159 | auto itResult = result.find(key: itSubtrahend.key()); |
160 | if (itResult != result.end() && itSubtrahend.value() == itResult.value()) |
161 | result.erase(it: itResult); |
162 | } |
163 | |
164 | return result; |
165 | } |
166 | |
167 | bool HelpDocSettings::applySettings(QHelpEngineCore *helpEngine, |
168 | const HelpDocSettings &settings) |
169 | { |
170 | const HelpDocSettings oldSettings = readSettings(helpEngine); |
171 | |
172 | const QMap<QString, QString> docsToRemove = subtract( |
173 | minuend: oldSettings.namespaceToFileName(), |
174 | subtrahend: settings.namespaceToFileName()); |
175 | const QMap<QString, QString> docsToAdd = subtract( |
176 | minuend: settings.namespaceToFileName(), |
177 | subtrahend: oldSettings.namespaceToFileName()); |
178 | |
179 | bool changed = false; |
180 | for (const QString &namespaceName : docsToRemove.keys()) { |
181 | if (!helpEngine->unregisterDocumentation(namespaceName)) |
182 | qWarning() << "Cannot unregister documentation:" << namespaceName; |
183 | changed = true; |
184 | } |
185 | |
186 | for (const QString &fileName : docsToAdd.values()) { |
187 | if (!helpEngine->registerDocumentation(documentationFileName: fileName)) |
188 | qWarning() << "Cannot register documentation file:" << fileName; |
189 | changed = true; |
190 | } |
191 | |
192 | return changed; |
193 | } |
194 | |
195 | QT_END_NAMESPACE |
196 | |