Marble

MarbleDirs.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2004-2007 Torsten Rahn <tackat@kde.org>
4// SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5//
6
7#include "MarbleDirs.h"
8#include "MarbleDebug.h"
9
10#include <QCoreApplication>
11#include <QFile>
12
13#include <cstdlib>
14
15#include <QStandardPaths>
16
17#ifdef Q_OS_WIN
18// for getting appdata path
19// mingw-w64 Internet Explorer 5.01
20#define _WIN32_IE 0x0501
21#include <shlobj.h>
22#endif
23
24#ifdef Q_OS_MACX
25// for getting app bundle path
26#include <ApplicationServices/ApplicationServices.h>
27#endif
28
29#include <config-marble.h>
30
31using namespace Marble;
32
33namespace
34{
35QString runTimeMarbleDataPath;
36
37QString runTimeMarblePluginPath;
38}
39
40MarbleDirs::MarbleDirs()
41 : d(nullptr)
42{
43}
44
45QString MarbleDirs::path(const QString &relativePath)
46{
47 QString localpath = localPath() + QLatin1Char('/') + relativePath; // local path
48 QString systempath = systemPath() + QLatin1Char('/') + relativePath; // system path
49
50 QString fullpath = systempath;
51 if (QFile::exists(localpath)) {
52 fullpath = localpath;
53 }
54 return QDir(fullpath).canonicalPath();
55}
56
57QString MarbleDirs::pluginPath(const QString &relativePath)
58{
59 const QString localpath = pluginLocalPath() + QDir::separator() + relativePath; // local path
60 const QString systempath = pluginSystemPath() + QDir::separator() + relativePath; // system path
61
62 QString fullpath = systempath;
63 if (QFile::exists(localpath)) {
64 fullpath = localpath;
65 }
66
67 return QDir(fullpath).canonicalPath();
68}
69
70QStringList MarbleDirs::entryList(const QString &relativePath, QDir::Filters filters)
71{
72 QStringList filesLocal = QDir(MarbleDirs::localPath() + QLatin1Char('/') + relativePath).entryList(filters);
73 QStringList filesSystem = QDir(MarbleDirs::systemPath() + QLatin1Char('/') + relativePath).entryList(filters);
74 QStringList allFiles(filesLocal);
75 allFiles << filesSystem;
76
77 // remove duplicate entries
78 allFiles.sort();
79 for (int i = 1; i < allFiles.size(); ++i) {
80 if (allFiles.at(i) == allFiles.at(i - 1)) {
81 allFiles.removeAt(i);
82 --i;
83 }
84 }
85
86 return allFiles;
87}
88
89QStringList MarbleDirs::pluginEntryList(const QString &relativePath, QDir::Filters filters)
90{
91 QStringList allFiles = QDir(MarbleDirs::pluginLocalPath() + QLatin1Char('/') + relativePath).entryList(filters);
92 auto const pluginSystemPath = MarbleDirs::pluginSystemPath();
93 if (!pluginSystemPath.isEmpty()) {
94 allFiles << QDir(pluginSystemPath + QLatin1Char('/') + relativePath).entryList(filters);
95 }
96
97 // remove duplicate entries
98 allFiles.sort();
99 for (int i = 1; i < allFiles.size(); ++i) {
100 if (allFiles.at(i) == allFiles.at(i - 1)) {
101 allFiles.removeAt(i);
102 --i;
103 }
104 }
105
106 return allFiles;
107}
108
109QString MarbleDirs::systemPath()
110{
111 if (!runTimeMarbleDataPath.isEmpty()) {
112 return runTimeMarbleDataPath;
113 }
114
115 QString systempath;
116
117#ifdef MARBLE_DATA_PATH
118 // MARBLE_DATA_PATH is a compiler define set by cmake
119 QString compileTimeMarbleDataPath(MARBLE_DATA_PATH);
120
121 if (QDir(compileTimeMarbleDataPath).exists())
122 return compileTimeMarbleDataPath;
123#endif // MARBLE_DATA_PATH
124
125#ifdef Q_OS_WIN
127#endif
128
129#ifdef Q_OS_MACX
130 //
131 // On OSX lets try to find any file first in the bundle
132 // before branching out to home and sys dirs
133 //
134 CFURLRef myBundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
135 CFStringRef myMacPath = CFURLCopyFileSystemPath(myBundleRef, kCFURLPOSIXPathStyle);
136 const char *mypPathPtr = CFStringGetCStringPtr(myMacPath, CFStringGetSystemEncoding());
137 CFRelease(myBundleRef);
138 QString myPath(mypPathPtr);
139 CFRelease(myMacPath);
140 // do some magick so that we can still find data dir if
141 // marble was not built as a bundle
142 if (myPath.contains(QLatin1StringView(".app"))) { // its a bundle!
143 systempath = myPath + QLatin1StringView("/Contents/Resources/data");
144 }
145
146 if (QFile::exists(systempath)) {
147 return systempath;
148 }
149#endif // mac bundle
150
151#ifdef Q_OS_ANDROID
152 systempath = "assets:/data";
153 return systempath;
154#endif
155
156 // This is the preferred fallback location if no marbleDataPath is set.
158
159 if (QFile::exists(systempath)) {
160 return systempath;
161 }
162
163 // This fallback location is for compatibility with KDE installations.
164 return QDir(QCoreApplication::applicationDirPath() + QLatin1StringView("/../share/apps/marble/data")).canonicalPath();
165}
166
167QString MarbleDirs::pluginSystemPath()
168{
169 if (!runTimeMarblePluginPath.isEmpty()) {
170 return runTimeMarblePluginPath;
171 }
172
173 QString systempath;
174
175#ifdef MARBLE_PLUGIN_PATH
176 // MARBLE_PLUGIN_PATH is a compiler define set by cmake
177 QString compileTimeMarblePluginPath(MARBLE_PLUGIN_PATH);
178
179 if (QDir(compileTimeMarblePluginPath).exists())
180 return compileTimeMarblePluginPath;
181#endif // MARBLE_PLUGIN_PATH
182
183#ifdef Q_OS_MACX
184 //
185 // On OSX lets try to find any file first in the bundle
186 // before branching out to home and sys dirs
187 //
188 CFURLRef myBundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
189 CFStringRef myMacPath = CFURLCopyFileSystemPath(myBundleRef, kCFURLPOSIXPathStyle);
190 const char *mypPathPtr = CFStringGetCStringPtr(myMacPath, CFStringGetSystemEncoding());
191 CFRelease(myBundleRef);
192 CFRelease(myMacPath);
193 QString myPath(mypPathPtr);
194 // do some magick so that we can still find data dir if
195 // marble was not built as a bundle
196 if (myPath.contains(QLatin1StringView(".app"))) { // its a bundle!
197 systempath = myPath + QLatin1StringView("/Contents/Resources/plugins");
198 }
199
200 if (QFile::exists(systempath)) {
201 return systempath;
202 }
203#endif // mac bundle
204
205#ifdef Q_OS_WIN
207#endif
208
209#ifdef Q_OS_ANDROID
210 return "assets:/plugins";
211#endif
212
213 // This is the preferred fallback location if no marblePluginPath is set.
215
216 if (QFile::exists(systempath)) {
217 return systempath;
218 }
219
220 // This ultimate fallback location is for compatibility with KDE installations.
221 return QDir(QCoreApplication::applicationDirPath() + QLatin1StringView("/../lib/kde4/plugins/marble")).canonicalPath();
222}
223
224QString MarbleDirs::localPath()
225{
226#ifndef Q_OS_WIN
227 QString dataHome = getenv("XDG_DATA_HOME");
228 if (dataHome.isEmpty())
229 dataHome = QDir::homePath() + QLatin1StringView("/.local/share");
230
231 return dataHome + QLatin1StringView("/marble"); // local path
232#else
234#endif
235}
236
237QStringList MarbleDirs::oldLocalPaths()
238{
239 QStringList possibleOldPaths;
240
241#ifndef Q_OS_WIN
242 const QString oldDefault = QDir::homePath() + QLatin1StringView("/.marble/data");
243 possibleOldPaths.append(oldDefault);
244
245 const QString xdgDefault = QDir::homePath() + QLatin1StringView("/.local/share/marble");
246 possibleOldPaths.append(xdgDefault);
247
248 QString xdg = getenv("XDG_DATA_HOME");
249 xdg += QLatin1StringView("/marble/");
250 possibleOldPaths.append(xdg);
251#endif
252
253#ifdef Q_OS_WIN
254 HWND hwnd = 0;
255 WCHAR *appdata_path = new WCHAR[MAX_PATH + 1];
256
257 SHGetSpecialFolderPathW(hwnd, appdata_path, CSIDL_APPDATA, 0);
258 QString appdata = QString::fromUtf16(reinterpret_cast<ushort *>(appdata_path));
259 delete[] appdata_path;
260 possibleOldPaths << QString(QDir::fromNativeSeparators(appdata) + QLatin1StringView("/.marble/data")); // local path
261#endif
262
263 QString currentLocalPath = QDir(MarbleDirs::localPath()).canonicalPath();
264 QStringList oldPaths;
265 for (const QString &possibleOldPath : possibleOldPaths) {
266 if (!QDir().exists(possibleOldPath)) {
267 continue;
268 }
269
270 QString canonicalPossibleOldPath = QDir(possibleOldPath).canonicalPath();
271 if (canonicalPossibleOldPath == currentLocalPath) {
272 continue;
273 }
274
275 oldPaths.append(canonicalPossibleOldPath);
276 }
277
278 return oldPaths;
279}
280
281QString MarbleDirs::pluginLocalPath()
282{
283#ifndef Q_OS_WIN
284 return QDir::homePath() + QLatin1StringView("/.marble/plugins"); // local path
285#else
287#endif
288}
289
290QString MarbleDirs::marbleDataPath()
291{
292 return runTimeMarbleDataPath;
293}
294
295QString MarbleDirs::marblePluginPath()
296{
297 return runTimeMarblePluginPath;
298}
299
300void MarbleDirs::setMarbleDataPath(const QString &adaptedPath)
301{
302 if (!QDir::root().exists(adaptedPath)) {
303 qWarning() << QStringLiteral("Invalid MarbleDataPath \"%1\". Using \"%2\" instead.").arg(adaptedPath, systemPath());
304 return;
305 }
306
307 runTimeMarbleDataPath = adaptedPath;
308}
309
310void MarbleDirs::setMarblePluginPath(const QString &adaptedPath)
311{
312 if (!QDir::root().exists(adaptedPath)) {
313 qWarning() << QStringLiteral("Invalid MarblePluginPath \"%1\". Using \"%2\" instead.").arg(adaptedPath, pluginSystemPath());
314 return;
315 }
316
317 runTimeMarblePluginPath = adaptedPath;
318}
319
320void MarbleDirs::debug()
321{
322 mDebug() << "=== MarbleDirs: ===";
323 mDebug() << "Local Path:" << localPath();
324 mDebug() << "Plugin Local Path:" << pluginLocalPath();
325 mDebug() << "";
326 mDebug() << "Marble Data Path (Run Time) :" << runTimeMarbleDataPath;
327 mDebug() << "Marble Data Path (Compile Time):" << QString(MARBLE_DATA_PATH);
328 mDebug() << "";
329 mDebug() << "Marble Plugin Path (Run Time) :" << runTimeMarblePluginPath;
330 mDebug() << "Marble Plugin Path (Compile Time):" << QString(MARBLE_PLUGIN_PATH);
331 mDebug() << "";
332 mDebug() << "System Path:" << systemPath();
333 mDebug() << "Plugin System Path:" << pluginSystemPath();
334 mDebug() << "===================";
335}
Binds a QML item to a specific geodetic location in screen coordinates.
QString applicationDirPath()
QString canonicalPath() const const
QStringList entryList(Filters filters, SortFlags sort) const const
QString fromNativeSeparators(const QString &pathName)
QString homePath()
QDir root()
QChar separator()
bool exists() const const
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
void removeAt(qsizetype i)
qsizetype size() const const
QString writableLocation(StandardLocation type)
QString fromUtf16(const char16_t *unicode, qsizetype size)
bool isEmpty() const const
void sort(Qt::CaseSensitivity cs)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:14:14 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.