File indexing completed on 2023-09-24 03:58:57
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 }