File indexing completed on 2024-04-21 03:48:36

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
0005 //
0006 
0007 #include <QApplication>
0008 #include <QFile>
0009 #include <QDir>
0010 #include <QLocale>
0011 #include <QTranslator>
0012 #include <QStandardPaths>
0013 
0014 #include "QtMainWindow.h"
0015 
0016 #include "MapThemeManager.h"
0017 #include "MarbleWidgetInputHandler.h"
0018 #include "MarbleDirs.h"
0019 #include "MarbleDebug.h"
0020 #include "MarbleTest.h"
0021 #include "MarbleLocale.h"
0022 #include "GeoUriParser.h"
0023 
0024 #ifdef STATIC_BUILD
0025  #include <QtPlugin>
0026  Q_IMPORT_PLUGIN(qjpeg)
0027  Q_IMPORT_PLUGIN(qsvg)
0028 #endif
0029 
0030 #ifdef Q_OS_MACX
0031 //for getting app bundle path
0032 #include <ApplicationServices/ApplicationServices.h>
0033 #endif
0034 
0035 using namespace Marble;
0036  
0037 // load translation file from normal "KDE Applications" packaging installation
0038 static bool loadTranslation(const QString &localeDirName, QApplication &app)
0039 {
0040     const QString subPath = QLatin1String("locale/") + localeDirName + QLatin1String("/LC_MESSAGES/marble_qt.qm");
0041     const QString fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, subPath);
0042     if (fullPath.isEmpty()) {
0043         return false;
0044     }
0045 
0046     QTranslator* translator = new QTranslator(&app);
0047     if (!translator->load(fullPath)) {
0048         delete translator;
0049         return false;
0050     }
0051 
0052     app.installTranslator(translator);
0053 
0054     return true;
0055 }
0056 
0057 // load KDE translators system based translations
0058 // TODO: document other possible supported translation systems, if any, and where their catalog files are
0059 static void loadTranslations(QApplication &app)
0060 {
0061     // Quote from ecm_create_qm_loader created code:
0062     // The way Qt translation system handles plural forms makes it necessary to
0063     // have a translation file which contains only plural forms for `en`.
0064     // That's why we load the `en` translation unconditionally, then load the
0065     // translation for the current locale to overload it.
0066     const QString en(QStringLiteral("en"));
0067 
0068     loadTranslation(en, app);
0069 
0070     QLocale locale = QLocale::system();
0071     if (locale.name() != en) {
0072         if (!loadTranslation(locale.name(), app)) {
0073             loadTranslation(locale.bcp47Name(), app);
0074         }
0075     }
0076 }
0077 
0078 
0079 int main(int argc, char *argv[])
0080 {
0081     QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
0082 
0083     QApplication app(argc, argv);
0084     app.setApplicationName( "Marble Virtual Globe" );
0085     app.setOrganizationName( "KDE" );
0086     app.setOrganizationDomain( "kde.org" );
0087     app.setDesktopFileName(QStringLiteral("org.kde.marble-qt"));
0088 
0089     // Load Qt translation system catalog for libmarblewidget, the plugins and this app
0090     loadTranslations(app);
0091 
0092     app.setApplicationDisplayName(MainWindow::tr("Marble - Virtual Globe"));
0093 
0094     // For non static builds on mac and win
0095     // we need to be sure we can find the qt image
0096     // plugins. In mac be sure to look in the
0097     // application bundle...
0098 
0099 #ifdef Q_WS_WIN
0100     QApplication::addLibraryPath( QApplication::applicationDirPath() 
0101         + QDir::separator() + QLatin1String("plugins"));
0102 #endif
0103 #ifdef Q_OS_MACX
0104     QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus);
0105     qDebug("Adding qt image plugins to plugin search path...");
0106     CFURLRef myBundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
0107     CFStringRef myMacPath = CFURLCopyFileSystemPath(myBundleRef, kCFURLPOSIXPathStyle);
0108     const char *mypPathPtr = CFStringGetCStringPtr(myMacPath,CFStringGetSystemEncoding());
0109     CFRelease(myBundleRef);
0110     CFRelease(myMacPath);
0111     QString myPath(mypPathPtr);
0112     // if we are not in a bundle assume that the app is built
0113     // as a non bundle app and that image plugins will be
0114     // in system Qt frameworks. If the app is a bundle
0115     // lets try to set the qt plugin search path...
0116     if (myPath.contains(".app"))
0117     {
0118       myPath += QLatin1String("/Contents/plugins");
0119       QApplication::addLibraryPath( myPath );
0120       qDebug( "Added %s to plugin search path", qPrintable( myPath ) );
0121     }
0122 #endif
0123 
0124     QString marbleDataPath;
0125     int dataPathIndex=0;
0126     QString mapThemeId;
0127     QString tour;
0128     QString coordinatesString;
0129     QString distanceString;
0130     QString geoUriString;
0131     MarbleGlobal::Profiles profiles = MarbleGlobal::getInstance()->profiles();
0132 
0133     QStringList args = QApplication::arguments();
0134 
0135     if ( args.contains( "-h" ) || args.contains( "--help" ) ) {
0136         qWarning() << "Usage: marble [options] [files]";
0137         qWarning();
0138         qWarning() << "[files] can be zero, one or more .kml and/or .gpx files to load and show.";
0139         qWarning();
0140         qWarning() << "general options:";
0141         qWarning() << "  --marbledatapath=<path> .... Overwrite the compile-time path to map themes and other data";
0142         qWarning() << "  --geo-uri=<uri> ............ Show map at given geo uri";
0143         qWarning() << "  --latlon=<coordinates> ..... Show map at given lat lon coordinates";
0144         qWarning() << "  --distance=<value> ......... Set the distance of the observer to the globe (in km)";
0145         qWarning() << "  --map=<id> ................. Use map id (e.g. \"earth/openstreetmap/openstreetmap.dgml\")";
0146         qWarning() << "  --tour=<file> .............. Load a KML tour from the given file and play it";
0147         qWarning();
0148         qWarning() << "debug options:";
0149         qWarning() << "  --debug-info ............... write (more) debugging information to the console";
0150         qWarning() << "  --fps ...................... Show the paint performance (paint rate) in the top left corner";
0151         qWarning() << "  --runtimeTrace.............. Show the time spent and other debug info of each layer";
0152         qWarning() << "  --tile-id................... Write the identifier of texture tiles on top of them";
0153         qWarning() << "  --timedemo ................. Measure the paint performance while moving the map and quit";
0154         qWarning() << "  --debug-polygons ........... Display the polygon nodes and their index for debugging";
0155         qWarning() << "  --debug-levels ............. Display OSM placemarks according to the level selected";
0156         qWarning();
0157         qWarning() << "profile options (note that marble should automatically detect which profile to use. Override that with the options below):";
0158         qWarning() << "  --highresolution ........... Enforce the profile for devices with high resolution (e.g. desktop computers)";
0159         qWarning() << "  --nohighresolution ......... Deactivate the profile for devices with high resolution (e.g. desktop computers)";
0160 
0161         return 0;
0162     }
0163 
0164     for ( int i = 1; i < args.count(); ++i ) {
0165         const QString arg = args.at(i);
0166 
0167         if ( arg == QLatin1String( "--debug-info" ) )
0168         {
0169             MarbleDebug::setEnabled( true );
0170         }
0171         else if ( arg.startsWith( QLatin1String( "--marbledatapath=" ), Qt::CaseInsensitive ) )
0172         {
0173             marbleDataPath = args.at(i).mid(17);
0174         }
0175         else if ( arg.compare( QLatin1String( "--marbledatapath" ), Qt::CaseInsensitive ) == 0 && i+1 < args.size() ) {
0176             dataPathIndex = i + 1;
0177             marbleDataPath = args.value( dataPathIndex );
0178             ++i;
0179         }
0180         else if ( arg == QLatin1String( "--highresolution" ) ) {
0181             profiles |= MarbleGlobal::HighResolution;
0182         }
0183         else if ( arg == QLatin1String( "--nohighresolution" ) ) {
0184             profiles &= ~MarbleGlobal::HighResolution;
0185         }
0186         else if ( arg.startsWith( QLatin1String( "--latlon=" ), Qt::CaseInsensitive ) )
0187         {
0188             coordinatesString = arg.mid(9);
0189         }
0190         else if ( arg.compare( QLatin1String( "--latlon" ), Qt::CaseInsensitive ) == 0 && i+1 < args.size() ) {
0191             ++i;
0192             coordinatesString = args.value( i );
0193         }
0194         else if ( arg.compare( QLatin1String( "--geo-uri=" ), Qt::CaseInsensitive ) == 0 ) {
0195             geoUriString = arg.mid(10);
0196         }
0197         else if ( arg.compare( QLatin1String( "--geo-uri" ), Qt::CaseInsensitive ) == 0 && i+1 < args.size() )
0198         {
0199             ++i;
0200             geoUriString = args.value(i);
0201         }
0202         else if ( arg.startsWith( QLatin1String( "--distance=" ), Qt::CaseInsensitive ) )
0203         {
0204             distanceString = arg.mid(11);
0205         }
0206         else if ( arg.compare( QLatin1String( "--distance" ), Qt::CaseInsensitive ) == 0 && i+1 < args.size() ) {
0207             ++i;
0208             distanceString = args.value( i );
0209         }
0210         else if ( arg.startsWith( QLatin1String( "--map=" ), Qt::CaseInsensitive ) )
0211         {
0212             mapThemeId = arg.mid(6);
0213         }
0214         else if ( arg.compare( QLatin1String( "--map" ), Qt::CaseInsensitive ) == 0 && i+1 < args.size() ) {
0215             ++i;
0216             mapThemeId = args.value( i );
0217         }
0218         else if ( arg.startsWith( QLatin1String( "--tour=" ), Qt::CaseInsensitive ) )
0219         {
0220             tour = arg.mid(7);
0221         }
0222         else if ( arg.compare( QLatin1String( "--tour" ), Qt::CaseInsensitive ) == 0 && i+1 < args.size() ) {
0223             ++i;
0224             tour = args.value( i );
0225         }
0226     }
0227     MarbleGlobal::getInstance()->setProfiles( profiles );
0228 
0229     MarbleLocale::MeasurementSystem const measurement =
0230             (MarbleLocale::MeasurementSystem)QLocale::system().measurementSystem();
0231     MarbleGlobal::getInstance()->locale()->setMeasurementSystem( measurement );
0232 
0233     QVariantMap cmdLineSettings;
0234     if ( !mapThemeId.isEmpty() ) {
0235         cmdLineSettings.insert( QLatin1String("mapTheme"), QVariant(mapThemeId) );
0236     }
0237 
0238     if ( !coordinatesString.isEmpty() ) {
0239         bool success = false;
0240         const GeoDataCoordinates coordinates = GeoDataCoordinates::fromString(coordinatesString, success);
0241         if ( success ) {
0242             QVariantList lonLat;
0243             lonLat << QVariant( coordinates.longitude(GeoDataCoordinates::Degree) )
0244                    << QVariant( coordinates.latitude(GeoDataCoordinates::Degree) );
0245             cmdLineSettings.insert( QLatin1String("lonlat"), QVariant(lonLat) );
0246         }
0247     }
0248     if ( !distanceString.isEmpty() ) {
0249         bool success = false;
0250         const qreal distance = distanceString.toDouble(&success);
0251         if ( success ) {
0252             cmdLineSettings.insert( QLatin1String("distance"), QVariant(distance) );
0253         }
0254     }
0255     if ( !tour.isEmpty() ) {
0256         cmdLineSettings.insert( QLatin1String("tour"), QVariant(tour) );
0257     }
0258 
0259     cmdLineSettings.insert( QLatin1String("geo-uri"), QVariant(geoUriString) );
0260 
0261     MainWindow window( marbleDataPath, cmdLineSettings );
0262 
0263 //    window.marbleWidget()->rotateTo( 0, 0, -90 );
0264 //    window.show();
0265 
0266     for ( int i = 1; i < args.count(); ++i ) {
0267         const QString arg = args.at(i);
0268         if (arg == QLatin1String("--timedemo")) {
0269             window.resize(900, 640);
0270             MarbleTest marbleTest( window.marbleWidget() );
0271             marbleTest.timeDemo();
0272             return 0;
0273         }
0274 
0275         if (arg == QLatin1String("--fps")) {
0276             window.marbleControl()->marbleWidget()->setShowFrameRate( true );
0277         }
0278         else if (arg == QLatin1String("--tile-id")) {
0279             window.marbleControl()->marbleWidget()->setShowTileId(true);
0280         }
0281         else if (arg == QLatin1String("--runtimeTrace")) {
0282             window.marbleControl()->marbleWidget()->setShowRuntimeTrace( true );
0283         }
0284         else if (arg == QLatin1String("--debug-polygons")) {
0285             window.marbleControl()->marbleWidget()->setShowDebugPolygons( true );
0286         }
0287         else if ( i != dataPathIndex && QFile::exists( arg ) ) {
0288             window.addGeoDataFile(arg);
0289         }
0290         else if (arg == QLatin1String("--debug-levels")) {
0291             window.marbleWidget()->setDebugLevelTags(true);
0292         }
0293     }
0294 
0295     auto const marbleWidget = window.marbleControl()->marbleWidget();
0296     bool const debugModeEnabled = marbleWidget->showRuntimeTrace() || marbleWidget->showDebugPolygons() ||
0297             marbleWidget->debugLevelTags() || MarbleDebug::isEnabled();
0298     marbleWidget->inputHandler()->setDebugModeEnabled(debugModeEnabled);
0299 
0300     return app.exec();
0301 }