Marble

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

KDE's Doxygen guidelines are available online.