MarbleDirs.cpp 9.66 KB
Newer Older
1
//
2
// This file is part of the Marble Virtual Globe.
3
4
5
6
7
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
8
9
// Copyright 2004-2007 Torsten Rahn <tackat@kde.org>
// Copyright 2007      Inge Wallin  <ingwa@kde.org>
10
11
12
13
//


#include "MarbleDirs.h"
14
#include "MarbleDebug.h"
15

16
17
18
19
20
#include <QDir>
#include <QFile>
#include <QString>
#include <QStringList>
#include <QApplication>
21

22
#include <stdlib.h>
23

24
25
26
27
#if QT_VERSION >= 0x050000
#include <QStandardPaths>
#else
#include <QDesktopServices>
28
29
#endif

30
31
#ifdef Q_OS_WIN
//for getting appdata path
32
33
//mingw-w64 Internet Explorer 5.01
#define _WIN32_IE 0x0501
34
35
36
#include <shlobj.h>
#endif

37
38
39
40
41
#ifdef Q_OS_MACX
//for getting app bundle path
#include <ApplicationServices/ApplicationServices.h>
#endif

42
43
#include <config-marble.h>

44
45
using namespace Marble;

46
47
namespace
{
48
    QString runTimeMarbleDataPath = "";
49
50

    QString runTimeMarblePluginPath = "";
51
52
}

Inge Wallin's avatar
Inge Wallin committed
53
54
55
56
57
58
MarbleDirs::MarbleDirs()
    : d( 0 )
{
}


59
QString MarbleDirs::path( const QString& relativePath )
60
{ 
61
62
    QString  localpath = localPath() + '/' + relativePath;	// local path
    QString  systempath  = systemPath() + '/' + relativePath;	// system path
63
64
65
66
67
68
69
70
71


    QString fullpath = systempath;
    if ( QFile::exists( localpath ) ) {
        fullpath = localpath;
    }
    return QDir( fullpath ).canonicalPath(); 
}

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

QString MarbleDirs::pluginPath( const QString& relativePath )
{ 
    QString  localpath = pluginLocalPath() + QDir::separator() + relativePath;    // local path
    QString  systempath  = pluginSystemPath() + QDir::separator() + relativePath; // system path


    QString fullpath = systempath;
    if ( QFile::exists( localpath ) ) {
        fullpath = localpath;
    }

    return QDir( fullpath ).canonicalPath(); 
}

Torsten Rahn's avatar
Torsten Rahn committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
QStringList MarbleDirs::entryList( const QString& relativePath, QDir::Filters filters )
{
    QStringList filesLocal = QDir( MarbleDirs::localPath() + '/' + relativePath ).entryList(filters);
    QStringList filesSystem = QDir( MarbleDirs::systemPath() + '/' + relativePath ).entryList(filters);
    QStringList allFiles( filesLocal );
    allFiles << filesSystem;

    // remove duplicate entries
    allFiles.sort();
    for ( int i = 1; i < allFiles.size(); ++i ) {
        if ( allFiles.at(i) == allFiles.at( i - 1 ) ) {
            allFiles.removeAt(i);
            --i;
        }
    }

    return allFiles;
}
105

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
QStringList MarbleDirs::pluginEntryList( const QString& relativePath, QDir::Filters filters )
{
    QStringList filesLocal = QDir( MarbleDirs::pluginLocalPath() + '/' + relativePath ).entryList(filters);
    QStringList filesSystem = QDir( MarbleDirs::pluginSystemPath() + '/' + relativePath ).entryList(filters);
    QStringList allFiles( filesLocal );
    allFiles << filesSystem;

    // remove duplicate entries
    allFiles.sort();
    for ( int i = 1; i < allFiles.size(); ++i ) {
        if ( allFiles.at(i) == allFiles.at( i - 1 ) ) {
            allFiles.removeAt(i);
            --i;
        }
    }

    return allFiles;
}

125
QString MarbleDirs::systemPath()
126
127
{
    QString systempath;
Torsten Rahn's avatar
   
Torsten Rahn committed
128

129
130
131
132
133
134
135
136
137
138
#ifdef Q_OS_MACX
    //
    // On OSX lets try to find any file first in the bundle
    // before branching out to home and sys dirs
    //
    CFURLRef myBundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
    CFStringRef myMacPath = CFURLCopyFileSystemPath(myBundleRef, kCFURLPOSIXPathStyle);
    const char *mypPathPtr = CFStringGetCStringPtr(myMacPath,CFStringGetSystemEncoding());
    CFRelease(myBundleRef);
    QString myPath(mypPathPtr);
139
    CFRelease(myMacPath);
140
141
142
143
    //do some magick so that we can still find data dir if
    //marble was not built as a bundle
    if (myPath.contains(".app"))  //its a bundle!
    {
144
      systempath = myPath + "/Contents/Resources/data";
145
    }
146

147
148
    if ( QFile::exists( systempath ) ){ 
      return systempath;
149
    }
150
#endif   // mac bundle
151

152
#ifdef Q_OS_ANDROID
Gábor Péterffy's avatar
Gábor Péterffy committed
153
154
155
156
    systempath = "assets:/data";
    return systempath;
#endif

Torsten Rahn's avatar
   
Torsten Rahn committed
157
158
159
// Should this happen before the Mac bundle already?
if ( !runTimeMarbleDataPath.isEmpty() )
    return runTimeMarbleDataPath;
160

161
#ifdef MARBLE_DATA_PATH
Torsten Rahn's avatar
   
Torsten Rahn committed
162
163
    //MARBLE_DATA_PATH is a compiler define set by cmake
    QString compileTimeMarbleDataPath(MARBLE_DATA_PATH);
164

165
166
167
    if(QDir(compileTimeMarbleDataPath).exists())
        return compileTimeMarbleDataPath;
#endif  // MARBLE_DATA_PATH
168

169
    return QDir( QCoreApplication::applicationDirPath() 
Torsten Rahn's avatar
   
Torsten Rahn committed
170
171

#if defined(QTONLY)
172
                     + QLatin1String( "/data" )
Torsten Rahn's avatar
   
Torsten Rahn committed
173
#else
174
175
176
177
178
                     + QLatin1String( "/../share/apps/marble/data" )
#endif
                     ).canonicalPath();
}

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
QString MarbleDirs::pluginSystemPath()
{
    QString systempath;

#ifdef Q_OS_MACX
    //
    // On OSX lets try to find any file first in the bundle
    // before branching out to home and sys dirs
    //
    CFURLRef myBundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
    CFStringRef myMacPath = CFURLCopyFileSystemPath(myBundleRef, kCFURLPOSIXPathStyle);
    const char *mypPathPtr = CFStringGetCStringPtr(myMacPath,CFStringGetSystemEncoding());
    CFRelease(myBundleRef);
    CFRelease(myMacPath);
    QString myPath(mypPathPtr);
    //do some magick so that we can still find data dir if
    //marble was not built as a bundle
    if (myPath.contains(".app"))  //its a bundle!
    {
      systempath = myPath + "/Contents/Resources/plugins";
    }

    if ( QFile::exists( systempath ) ){ 
      return systempath;
    }
#endif   // mac bundle

// Should this happen before the Mac bundle already?
if ( !runTimeMarblePluginPath.isEmpty() )
    return runTimeMarblePluginPath;

210
#ifdef Q_OS_ANDROID
211
212
213
    return "assets:/plugins";
#endif

214
215
216
217
218
219
220
221
222
223
224
225
226
#ifdef MARBLE_PLUGIN_PATH
    //MARBLE_PLUGIN_PATH is a compiler define set by cmake
    QString compileTimeMarblePluginPath(MARBLE_PLUGIN_PATH);

    if(QDir(compileTimeMarblePluginPath).exists())
        return compileTimeMarblePluginPath;
#endif  // MARBLE_PLUGIN_PATH

    return QDir( QCoreApplication::applicationDirPath() 

#if defined(QTONLY)
                     + QLatin1String( "/plugins" )
#else
227
                     + QLatin1String( "/../lib/kde4/plugins/marble" )
228
229
230
231
#endif
                     ).canonicalPath();
}

232
QString MarbleDirs::localPath() 
233
234
{
#ifndef Q_OS_WIN
235
236
237
238
239
    QString dataHome = getenv( "XDG_DATA_HOME" );
    if( dataHome.isEmpty() )
        dataHome = QDir::homePath() + "/.local/share";

    return dataHome + "/marble"; // local path
240
#else
241
242
243
244
245
#if QT_VERSION >= 0x050000
	return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/.marble/data";
#else
	return QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/.marble/data";
#endif
246
#endif
247
}
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
QStringList MarbleDirs::oldLocalPaths()
{
    QStringList possibleOldPaths;

#ifndef Q_OS_WIN
    QString oldDefault = QDir::homePath() + "/.marble/data";
    possibleOldPaths.append( oldDefault );

    QString xdgDefault = QDir::homePath() + "/.local/share/marble";
    possibleOldPaths.append( xdgDefault );

    QString xdg = getenv( "XDG_DATA_HOME" );
    xdg += "/marble/";
    possibleOldPaths.append( xdg );
#endif
264
265
266
267
268
269
270
271
272
273
274

#ifdef Q_OS_WIN
	HWND hwnd = 0;
	WCHAR *appdata_path = new WCHAR[MAX_PATH + 1];

	SHGetSpecialFolderPathW(hwnd, appdata_path, CSIDL_APPDATA, 0);
	QString appdata = QString::fromUtf16(reinterpret_cast<ushort*>(appdata_path));
	delete[] appdata_path;
	possibleOldPaths << QString(QDir::fromNativeSeparators(appdata) + "/.marble/data"); // local path
#endif

275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    QString currentLocalPath = QDir( MarbleDirs::localPath() ).canonicalPath();
    QStringList oldPaths;
    foreach( const QString& possibleOldPath, possibleOldPaths ) {
        if( !QDir().exists( possibleOldPath ) ) {
            continue;
        }

        QString canonicalPossibleOldPath = QDir( possibleOldPath ).canonicalPath();
        if( canonicalPossibleOldPath == currentLocalPath ) {
            continue;
        }

        oldPaths.append( canonicalPossibleOldPath );
    }

    return oldPaths;
}

293
QString MarbleDirs::pluginLocalPath() 
294
295
{
#ifndef Q_OS_WIN
296
    return QString( QDir::homePath() + "/.marble/plugins" ); // local path
297
#else
298
299
300
301
302
#if QT_VERSION >= 0x050000
	return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/.marble/plugins";
#else
	return QDesktopServices::storageLocation(QDesktopServices::DataLocation) + "/.marble/plugins";
#endif
303
#endif
304
305
}

306
307
QString MarbleDirs::marbleDataPath()
{
Torsten Rahn's avatar
   
Torsten Rahn committed
308
    return runTimeMarbleDataPath;
309
310
}

311
312
QString MarbleDirs::marblePluginPath()
{
313
    return runTimeMarblePluginPath;
314
315
}

316
317
void MarbleDirs::setMarbleDataPath( const QString& adaptedPath )
{
318
319
    if ( !QDir::root().exists( adaptedPath ) )
    {
320
        qWarning() << QString( "Invalid MarbleDataPath \"%1\". Using \"%2\" instead." ).arg( adaptedPath ).arg( systemPath() );
Torsten Rahn's avatar
   
Torsten Rahn committed
321
        return;
322
323
    }

Torsten Rahn's avatar
   
Torsten Rahn committed
324
    runTimeMarbleDataPath = adaptedPath;
325
}
326

327
328
329
330
void MarbleDirs::setMarblePluginPath( const QString& adaptedPath )
{
    if ( !QDir::root().exists( adaptedPath ) )
    {
331
        qWarning() << QString( "Invalid MarblePluginPath \"%1\". Using \"%2\" instead." ).arg( adaptedPath ).arg( pluginSystemPath() );
332
333
334
335
336
337
338
        return;
    }

    runTimeMarblePluginPath = adaptedPath;
}


339
340
void MarbleDirs::debug()
{
Patrick Spendrin's avatar
Patrick Spendrin committed
341
342
343
344
345
346
347
348
349
350
351
352
353
    mDebug() << "=== MarbleDirs: ===";
    mDebug() << "Local Path:" << localPath();
    mDebug() << "Plugin Local Path:" << pluginLocalPath();
    mDebug() << "";
    mDebug() << "Marble Data Path (Run Time) :" << runTimeMarbleDataPath; 
    mDebug() << "Marble Data Path (Compile Time):" << QString(MARBLE_DATA_PATH); 
    mDebug() << "";
    mDebug() << "Marble Plugin Path (Run Time) :" << runTimeMarblePluginPath; 
    mDebug() << "Marble Plugin Path (Compile Time):" << QString(MARBLE_PLUGIN_PATH); 
    mDebug() << "";
    mDebug() << "System Path:" << systemPath();
    mDebug() << "Plugin System Path:" << pluginSystemPath();
    mDebug() << "===================";
354
}