File indexing completed on 2024-04-14 03:46:52

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2006-2010 Torsten Rahn <tackat@kde.org>
0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
0005 // SPDX-FileCopyrightText: 2011-2013 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
0006 // SPDX-FileCopyrightText: 2012 Illya Kovalevskyy <illya.kovalevskyy@gmail.com>
0007 // SPDX-FileCopyrightText: 2012 Mohammed Nafees <nafees.technocool@gmail.com>
0008 //
0009 
0010 #include "QtMainWindow.h"
0011 
0012 #include "MarbleDebug.h"
0013 #include <QList>
0014 #include <QSettings>
0015 #include <QUrl>
0016 #include <QCloseEvent>
0017 #include <QVariant>
0018 #include <QVector>
0019 #include <QAction>
0020 #include <QLabel>
0021 #include <QWhatsThis>
0022 #include <QApplication>
0023 #include <QIcon>
0024 #include <QMenuBar>
0025 #include <QStatusBar>
0026 #include <QProgressBar>
0027 #include <QToolBar>
0028 #include <QDesktopServices>
0029 #include <QFileDialog>
0030 #include <QMessageBox>
0031 #include <QPrintDialog>
0032 #include <QPrinter>
0033 #include <QDialogButtonBox>
0034 #include <QClipboard>
0035 #include <QNetworkProxy>
0036 
0037 #include "EditBookmarkDialog.h"
0038 #include "BookmarkManagerDialog.h"
0039 #include "CurrentLocationWidget.h"
0040 #include "MapViewWidget.h"
0041 #include "MarbleDirs.h"
0042 #include "MarbleAboutDialog.h"
0043 #include "QtMarbleConfigDialog.h"
0044 #include "SunControlWidget.h"
0045 #include "TimeControlWidget.h"
0046 #include "MarbleLocale.h"
0047 #include "DownloadRegionDialog.h"
0048 #include "ViewportParams.h"
0049 #include "AbstractFloatItem.h"
0050 #include "MarbleModel.h"
0051 #include "MarbleClock.h"
0052 #include "FileManager.h"
0053 #include "HttpDownloadManager.h"
0054 #include "BookmarkManager.h"
0055 #include "NewBookmarkFolderDialog.h"
0056 #include "GeoSceneDocument.h"
0057 #include "GeoSceneHead.h"
0058 #include "GeoSceneMap.h"
0059 #include "GeoDataLookAt.h"
0060 #include "GeoDataCoordinates.h"
0061 #include "GeoDataLatLonAltBox.h"
0062 #include "GeoDataDocument.h"
0063 #include "GeoDataFolder.h"
0064 #include "GeoDataPlacemark.h"
0065 #include "GeoUriParser.h"
0066 #include "routing/RoutingManager.h"
0067 #include "routing/RoutingProfilesModel.h"
0068 #include "routing/RoutingWidget.h"
0069 #include "routing/RouteRequest.h"
0070 #include "ParseRunnerPlugin.h"
0071 #include "PositionTracking.h"
0072 #include "PositionProviderPlugin.h"
0073 #include "PluginManager.h"
0074 #include "MarbleColors.h"
0075 #include "MapThemeDownloadDialog.h"
0076 #include "MapWizard.h"
0077 #include "MarbleWidgetInputHandler.h"
0078 #include "Planet.h"
0079 #include "cloudsync/CloudSyncManager.h"
0080 #include "cloudsync/BookmarkSyncManager.h"
0081 #include "cloudsync/RouteSyncManager.h"
0082 #include "MovieCaptureDialog.h"
0083 #include "DataMigration.h"
0084 #include "TileCoordsPyramid.h"
0085 
0086 using namespace Marble;
0087 /* TRANSLATOR Marble::MainWindow */
0088 
0089 MainWindow::MainWindow(const QString& marbleDataPath, const QVariantMap& cmdLineSettings, QWidget *parent) :
0090         QMainWindow(parent),
0091         m_controlView( nullptr ),
0092         m_savedSize( QSize(-1, -1) ),
0093         m_sunControlDialog( nullptr ),
0094         m_timeControlDialog( nullptr ),
0095         m_configDialog( nullptr ),
0096         m_downloadRegionDialog( nullptr ),
0097         m_movieCaptureDialog( nullptr ),
0098 
0099         // File Menu
0100         m_fileMenu( nullptr ),
0101         m_viewMenu( nullptr ),
0102         m_helpMenu( nullptr ),
0103         m_settingsMenu( nullptr ),
0104         m_panelMenu( nullptr ),
0105         m_viewSizeMenu( nullptr ),
0106         m_infoBoxesMenu( nullptr ),
0107         m_onlineServicesMenu( nullptr ),
0108         m_bookmarkMenu( nullptr ),
0109         m_openAction( nullptr ),
0110         m_exportMapAction( nullptr ),
0111         m_downloadAction( nullptr ),
0112         m_downloadRegionAction( nullptr ),
0113         m_printPreviewAction( nullptr ),
0114         m_printAction( nullptr ),
0115         m_workOfflineAction( nullptr ),
0116         m_quitAction( nullptr ),
0117         m_mapWizardAction( nullptr ),
0118 
0119         // Edit Menu
0120         m_copyMapAction( nullptr ),
0121         m_copyCoordinatesAction( nullptr ),
0122         m_osmEditAction( nullptr ),
0123         m_recordMovieAction( nullptr ),
0124         m_stopRecordingAction( nullptr ),
0125 
0126         // View Menu
0127         m_showCloudsAction( nullptr ),\
0128         m_controlSunAction( nullptr ),
0129         m_controlTimeAction( nullptr ),
0130         m_reloadAction( nullptr ),
0131 
0132         // Settings Menu
0133         m_fullScreenAction( nullptr ),
0134         m_statusBarAction( nullptr ),
0135         m_configDialogAction( nullptr ),
0136         m_viewSizeActsGroup( nullptr ),
0137 
0138         // Help Menu
0139         m_whatsThisAction( nullptr ),
0140         m_aboutMarbleAction( nullptr ),
0141         m_aboutQtAction( nullptr ),
0142         m_lockFloatItemsAction( nullptr ),
0143         m_handbookAction( nullptr ),
0144         m_forumAction( nullptr ),
0145 
0146         // Status Bar
0147         m_positionLabel( nullptr ),
0148         m_distanceLabel( nullptr ),
0149         m_zoomLabel( nullptr ),
0150         m_clockLabel( nullptr ),
0151         m_downloadProgressBar( nullptr ),
0152         m_toggleTileLevelAction( nullptr ),
0153         m_angleDisplayUnitActionGroup( nullptr ),
0154         m_dmsDegreeAction( nullptr ),
0155         m_decimalDegreeAction( nullptr ),
0156         m_utmAction( nullptr ),
0157 
0158         //Bookmark Menu
0159         m_addBookmarkAction( nullptr ),
0160         m_setHomeAction( nullptr ),
0161         m_toggleBookmarkDisplayAction( nullptr ),
0162         m_manageBookmarksAction( nullptr )
0163 {
0164     setUpdatesEnabled( false );
0165 
0166     QString selectedPath = marbleDataPath.isEmpty() ? readMarbleDataPath() : marbleDataPath;
0167     if ( !selectedPath.isEmpty() )
0168         MarbleDirs::setMarbleDataPath( selectedPath );
0169 
0170 #ifdef Q_OS_WIN
0171     QPointer<DataMigration> migration = new DataMigration(this);
0172     migration->exec();
0173 #endif
0174 
0175     m_controlView = new ControlView( this );
0176 
0177     setWindowIcon(QIcon(QStringLiteral(":/icons/marble.png")));
0178     setCentralWidget( m_controlView );
0179 
0180     // Initializing config dialog
0181     m_configDialog = new QtMarbleConfigDialog( m_controlView->marbleWidget(),
0182                                                m_controlView->cloudSyncManager(),
0183                                                this );
0184     connect( m_configDialog, SIGNAL(settingsChanged()),
0185              this, SLOT(updateSettings()) );
0186     connect( m_configDialog, SIGNAL(clearVolatileCacheClicked()),
0187              m_controlView->marbleWidget(), SLOT(clearVolatileTileCache()) );
0188     connect( m_configDialog, SIGNAL(clearPersistentCacheClicked()),
0189              m_controlView->marbleModel(), SLOT(clearPersistentTileCache()) );
0190     connect( m_configDialog, SIGNAL(syncNowClicked()),
0191              m_controlView->cloudSyncManager()->bookmarkSyncManager(), SLOT(startBookmarkSync()) );
0192     connect(m_configDialog, SIGNAL(syncNowClicked()),
0193             m_configDialog, SLOT(disableSyncNow()));
0194 
0195     connect(m_controlView->marbleModel()->fileManager(), &FileManager::fileError, this,
0196         [this](const QString& path, const QString& error) {
0197             QMessageBox::warning(this, tr("Marble"), // krazy:exclude=qclasses
0198                    tr("Sorry, unable to open '%1':\n'%2'").arg(path).arg(error),
0199                    QMessageBox::Ok);
0200         });
0201 
0202     // Load bookmark file. If it does not exist, a default one will be used.
0203     m_controlView->marbleModel()->bookmarkManager()->loadFile( "bookmarks/bookmarks.kml" );
0204 
0205     createActions();
0206     QList<QAction*> const panelActions = m_controlView->setupDockWidgets( this );
0207     createMenus( panelActions );
0208     createStatusBar();
0209 
0210     connect( m_controlView->marbleWidget(), SIGNAL(themeChanged(QString)),
0211              this, SLOT(updateMapEditButtonVisibility(QString)) );
0212     connect(m_controlView->marbleModel(), SIGNAL(themeChanged(QString)),
0213             this, SLOT(updateWindowTitle()));
0214     connect(m_controlView->marbleModel(), SIGNAL(themeChanged(QString)),
0215             this, SLOT(updateCenterFromTheme()));
0216 
0217     connect( m_controlView, SIGNAL(showMapWizard()), this, SLOT(showMapWizard()) );
0218     connect( m_controlView, SIGNAL(mapThemeDeleted()), this, SLOT(fallBackToDefaultTheme()) );
0219 
0220     updateWindowTitle();
0221     setUpdatesEnabled( true );
0222 
0223     m_position =  QCoreApplication::translate( "Marble", NOT_AVAILABLE );
0224     m_distance = marbleWidget()->distanceString();
0225     m_zoom = QString::number( marbleWidget()->tileZoomLevel() );
0226 
0227     m_clock = QLocale().toString( m_controlView->marbleModel()->clockDateTime().addSecs( m_controlView->marbleModel()->clockTimezone() ), QLocale::ShortFormat );
0228     QMetaObject::invokeMethod(this,
0229                               "initObject", Qt::QueuedConnection,
0230                               Q_ARG(QVariantMap, cmdLineSettings));
0231 }
0232 
0233 MainWindow::~MainWindow()
0234 {
0235     delete m_movieCaptureDialog;
0236 }
0237 
0238 void MainWindow::addGeoDataFile( const QString &fileName )
0239 {
0240     QFileInfo file( fileName );
0241 
0242     if ( !file.exists() )
0243         return;
0244 
0245     // delay file loading to initObject(), such that restoring view from previous session in readSettings()
0246     // doesn't interfere with focusing on these files
0247     m_commandlineFilePaths << file.absoluteFilePath();
0248 }
0249 
0250 void MainWindow::initObject(const QVariantMap& cmdLineSettings)
0251 {
0252     QCoreApplication::processEvents ();
0253     setupStatusBar();
0254     readSettings(cmdLineSettings);
0255 
0256     for ( const QString &path: m_commandlineFilePaths ) {
0257         m_controlView->marbleModel()->addGeoDataFile( path );
0258     }
0259 
0260     if ( cmdLineSettings.contains( "tour" ) ) {
0261         QString const tour = cmdLineSettings.value( "tour" ).toString();
0262         m_controlView->openTour( tour );
0263     }
0264     m_commandlineFilePaths.clear();
0265 }
0266 
0267 void MainWindow::createActions()
0268  {
0269      m_openAction = new QAction(QIcon(QStringLiteral(":/icons/document-open.png")), tr("&Open..."), this);
0270      m_openAction->setShortcut( QKeySequence( "Ctrl+O" ) );
0271      m_openAction->setStatusTip( tr( "Open a file for viewing on Marble"));
0272      connect( m_openAction, SIGNAL(triggered()),
0273               this, SLOT(openFile()) );
0274 
0275      m_downloadAction = new QAction(QIcon(QStringLiteral(":/icons/get-hot-new-stuff.png")), tr("&Download Maps..."), this);
0276      connect(m_downloadAction, SIGNAL(triggered()), this, SLOT(openMapDialog()));
0277 
0278      m_exportMapAction = new QAction(QIcon(QStringLiteral(":/icons/document-save-as.png")), tr("&Export Map..."), this);
0279      m_exportMapAction->setShortcut(QKeySequence("Ctrl+S"));
0280      m_exportMapAction->setStatusTip(tr("Save a screenshot of the map"));
0281      connect(m_exportMapAction, SIGNAL(triggered()), this, SLOT(exportMapScreenShot()));
0282 
0283      // Action: Download Region
0284      m_downloadRegionAction = new QAction( tr( "Download &Region..." ), this );
0285      m_downloadRegionAction->setStatusTip( tr( "Download a map region in different zoom levels for offline usage" ) );
0286      connect( m_downloadRegionAction, SIGNAL(triggered()), SLOT(showDownloadRegionDialog()) );
0287 
0288      m_printAction = new QAction(QIcon(QStringLiteral(":/icons/document-print.png")), tr("&Print..."), this);
0289      m_printAction->setShortcut(tr("Ctrl+P"));
0290      m_printAction->setStatusTip(tr("Print a screenshot of the map"));
0291      connect(m_printAction, SIGNAL(triggered()), this, SLOT(printMapScreenShot()));
0292 
0293      m_printPreviewAction = new QAction(QIcon(QStringLiteral(":/icons/document-print-preview.png")), tr("Print Previe&w ..."), this);
0294      m_printPreviewAction->setStatusTip(tr("Print a screenshot of the map"));
0295      connect(m_printPreviewAction, SIGNAL(triggered()), m_controlView, SLOT(printPreview()));
0296 
0297      m_quitAction = new QAction(QIcon(QStringLiteral(":/icons/application-exit.png")), tr("&Quit"), this);
0298      m_quitAction->setShortcut(tr("Ctrl+Q"));
0299      m_quitAction->setStatusTip(tr("Quit the Application"));
0300      connect(m_quitAction, SIGNAL(triggered()), this, SLOT(close()));
0301 
0302      m_copyMapAction = new QAction(QIcon(QStringLiteral(":/icons/edit-copy.png")), tr("&Copy Map"), this);
0303      m_copyMapAction->setShortcut(QKeySequence("Ctrl+C"));
0304      m_copyMapAction->setStatusTip(tr("Copy a screenshot of the map"));
0305      connect(m_copyMapAction, SIGNAL(triggered()), this, SLOT(copyMap()));
0306 
0307      m_osmEditAction = new QAction(QIcon(QStringLiteral(":/icons/edit-map.png")), tr("&Edit Map..."), this );
0308      m_osmEditAction->setShortcut(QKeySequence( "Ctrl+E" ) );
0309      m_osmEditAction->setStatusTip(tr( "Edit the current map region in an external editor" ) );
0310      updateMapEditButtonVisibility( m_controlView->marbleWidget()->mapThemeId() );
0311      connect( m_osmEditAction, SIGNAL(triggered()), m_controlView, SLOT(launchExternalMapEditor()) );
0312 
0313      m_recordMovieAction = new QAction(tr("&Record Movie"), this);
0314      m_recordMovieAction->setStatusTip(tr("Records a movie of the globe"));
0315      m_recordMovieAction->setShortcut(QKeySequence("Ctrl+Shift+R"));
0316      m_recordMovieAction->setIcon(QIcon(QStringLiteral(":/icons/animator.png")));
0317      connect(m_recordMovieAction, SIGNAL(triggered()),
0318              this, SLOT(showMovieCaptureDialog()));
0319 
0320      m_stopRecordingAction = new QAction( tr("&Stop Recording"), this );
0321      m_stopRecordingAction->setStatusTip( tr("Stop recording a movie of the globe") );
0322      m_stopRecordingAction->setShortcut(QKeySequence( "Ctrl+Shift+S" ));
0323      m_stopRecordingAction->setEnabled( false );
0324      connect( m_stopRecordingAction, SIGNAL(triggered()),
0325              this, SLOT(stopRecording()) );
0326 
0327      m_configDialogAction = new QAction(QIcon(QStringLiteral(":/icons/settings-configure.png")), tr("&Configure Marble"), this);
0328      m_configDialogAction->setStatusTip(tr("Show the configuration dialog"));
0329      connect(m_configDialogAction, SIGNAL(triggered()), this, SLOT(editSettings()));
0330 
0331      m_copyCoordinatesAction = new QAction(QIcon(QStringLiteral(":/icons/copy-coordinates.png")), tr("C&opy Coordinates"), this);
0332      m_copyCoordinatesAction->setStatusTip(tr("Copy the center coordinates as text"));
0333      connect(m_copyCoordinatesAction, SIGNAL(triggered()), this, SLOT(copyCoordinates()));
0334 
0335      m_fullScreenAction = new QAction(QIcon(QStringLiteral(":/icons/view-fullscreen.png")), tr("&Full Screen Mode"), this);
0336      m_fullScreenAction->setShortcut(QKeySequence("Ctrl+Shift+F"));
0337      m_fullScreenAction->setCheckable( true );
0338      m_fullScreenAction->setStatusTip(tr("Full Screen Mode"));
0339      connect(m_fullScreenAction, SIGNAL(triggered(bool)), this, SLOT(showFullScreen(bool)));
0340 
0341      m_statusBarAction = new QAction( tr("&Show Status Bar"), this);
0342      m_statusBarAction->setCheckable( true );
0343      m_statusBarAction->setStatusTip(tr("Show Status Bar"));
0344      connect(m_statusBarAction, SIGNAL(triggered(bool)), this, SLOT(showStatusBar(bool)));
0345 
0346 
0347      m_lockFloatItemsAction = new QAction(QIcon(QStringLiteral(":/icons/unlock.png")), tr("Lock Position"), this);
0348      m_lockFloatItemsAction->setCheckable( true );
0349      m_lockFloatItemsAction->setStatusTip(tr("Lock Position of Floating Items"));
0350      connect(m_lockFloatItemsAction, SIGNAL(triggered(bool)), this, SLOT(lockPosition(bool)));
0351 
0352      m_showCloudsAction = new QAction(QIcon(QStringLiteral(":/icons/clouds.png")), tr("&Clouds"), this);
0353      m_showCloudsAction->setCheckable( true );
0354      m_showCloudsAction->setStatusTip(tr("Show Real Time Cloud Cover"));
0355      connect(m_showCloudsAction, SIGNAL(triggered(bool)), this, SLOT(showClouds(bool)));
0356 
0357      m_workOfflineAction = new QAction(QIcon(QStringLiteral(":/icons/user-offline.png")), tr("Work Off&line"), this);
0358      m_workOfflineAction->setCheckable( true );
0359      connect(m_workOfflineAction, SIGNAL(triggered(bool)), this, SLOT(workOffline(bool)));
0360 
0361      m_controlTimeAction = new QAction(QIcon(QStringLiteral(":/icons/clock.png")), tr("&Time Control..."), this );
0362      m_controlTimeAction->setStatusTip( tr( "Configure Time Control " ) );
0363      connect( m_controlTimeAction, SIGNAL(triggered()), this, SLOT(controlTime()) );
0364 
0365      m_controlSunAction = new QAction( tr( "S&un Control..." ), this );
0366      m_controlSunAction->setStatusTip( tr( "Configure Sun Control" ) );
0367      connect( m_controlSunAction, SIGNAL(triggered()), this, SLOT(controlSun()) );
0368 
0369      m_reloadAction = new QAction(QIcon(QStringLiteral(":/icons/view-refresh.png")), tr("&Redisplay"), this);
0370      m_reloadAction->setShortcut(QKeySequence("F5"));
0371      m_reloadAction->setStatusTip(tr("Reload Current Map"));
0372      connect(m_reloadAction, SIGNAL(triggered()), this, SLOT(reload()));
0373 
0374      m_handbookAction = new QAction(QIcon(QStringLiteral(":/icons/help-contents.png")), tr("Marble Virtual Globe &Handbook"), this);
0375      m_handbookAction->setShortcut(QKeySequence("F1"));
0376      m_handbookAction->setStatusTip(tr("Show the Handbook for Marble Virtual Globe"));
0377      connect(m_handbookAction, SIGNAL(triggered()), this, SLOT(handbook()));
0378 
0379      m_whatsThisAction = new QAction(QIcon(QStringLiteral(":/icons/help-whatsthis.png")), tr("What's &This"), this);
0380      m_whatsThisAction->setShortcut(QKeySequence("Shift+F1"));
0381      m_whatsThisAction->setStatusTip(tr("Show a detailed explanation of the action."));
0382      connect(m_whatsThisAction, SIGNAL(triggered()), this, SLOT(enterWhatsThis()));
0383 
0384      m_forumAction = new QAction( tr("&Community Forum"), this);
0385      m_forumAction->setStatusTip(tr("Visit Marble's Community Forum"));
0386      connect(m_forumAction, SIGNAL(triggered()), this, SLOT(openForum()));
0387 
0388      m_aboutMarbleAction = new QAction(QIcon(QStringLiteral(":/icons/marble.png")), tr("&About Marble Virtual Globe"), this);
0389      m_aboutMarbleAction->setStatusTip(tr("Show the application's About Box"));
0390      connect(m_aboutMarbleAction, SIGNAL(triggered()), this, SLOT(aboutMarble()));
0391 
0392      m_aboutQtAction = new QAction(tr("About &Qt"), this);
0393      m_aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));
0394      connect(m_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
0395 
0396      //Bookmark Actions
0397      m_addBookmarkAction = new QAction(QIcon(QStringLiteral(":/icons/bookmark-new.png")), tr("Add &Bookmark..."), this);
0398      m_addBookmarkAction->setShortcut(QKeySequence("Ctrl+B"));
0399      m_addBookmarkAction->setStatusTip(tr("Add Bookmark"));
0400      connect( m_addBookmarkAction, SIGNAL(triggered()), this, SLOT(openEditBookmarkDialog()) );
0401 
0402      m_setHomeAction = new QAction(QIcon(QStringLiteral(":/icons/go-home.png")), tr("&Set Home Location"), this);
0403      m_setHomeAction->setStatusTip( tr( "&Set Home Location" ) );
0404      connect( m_setHomeAction, SIGNAL(triggered()), this, SLOT(setHome()) );
0405 
0406      m_toggleBookmarkDisplayAction = new QAction(tr( "Show &Bookmarks" ), this);
0407      m_toggleBookmarkDisplayAction->setStatusTip( tr( "Toggle display of Bookmarks" ) );
0408      m_toggleBookmarkDisplayAction->setCheckable( true );
0409      connect( m_toggleBookmarkDisplayAction, SIGNAL(triggered(bool)), this, SLOT(showBookmarks(bool)) );
0410 
0411      m_manageBookmarksAction = new QAction(QIcon(QStringLiteral(":/icons/bookmarks-organize.png")), tr("&Manage Bookmarks..."), this);
0412      m_manageBookmarksAction->setStatusTip( tr( "Manage Bookmarks" ) );
0413      connect( m_manageBookmarksAction, SIGNAL(triggered()), this, SLOT(manageBookmarks()) );
0414      
0415      // Map Wizard action
0416      m_mapWizardAction = new QAction(QIcon(QStringLiteral(":/icons/create-new-map.png")), tr("&Create a New Map..."), this);
0417      m_mapWizardAction->setStatusTip( tr( "A wizard guides you through the creation of your own map theme." ) );
0418      connect( m_mapWizardAction, SIGNAL(triggered()), SLOT(showMapWizard()) );
0419 
0420      // Statusbar Actions
0421      m_toggleTileLevelAction = new QAction( tr( "Show Tile Zoom Level" ), statusBar() );
0422      m_toggleTileLevelAction->setCheckable( true );
0423      m_toggleTileLevelAction->setChecked( false );
0424      connect( m_toggleTileLevelAction, SIGNAL(triggered(bool)),
0425               this, SLOT(showZoomLevel(bool)) );
0426 
0427      m_angleDisplayUnitActionGroup = new QActionGroup( statusBar() );
0428 
0429      m_dmsDegreeAction = new QAction( tr( "Degree (DMS)" ), statusBar() );
0430      m_dmsDegreeAction->setCheckable( true );
0431      m_dmsDegreeAction->setData( (int)DMSDegree );
0432      m_angleDisplayUnitActionGroup->addAction(m_dmsDegreeAction);
0433 
0434      m_decimalDegreeAction = new QAction( tr( "Degree (Decimal)" ), statusBar() );
0435      m_decimalDegreeAction->setCheckable( true );
0436      m_decimalDegreeAction->setData( (int)DecimalDegree );
0437      m_angleDisplayUnitActionGroup->addAction(m_decimalDegreeAction);
0438 
0439      m_utmAction = new QAction( tr( "Universal Transverse Mercator (UTM)" ), statusBar() );
0440      m_utmAction->setCheckable( true );
0441      m_utmAction->setData( (int)UTM );
0442      m_angleDisplayUnitActionGroup->addAction(m_utmAction);
0443 
0444      connect( m_angleDisplayUnitActionGroup, SIGNAL(triggered(QAction*)),
0445               this, SLOT(changeAngleDisplayUnit(QAction*)) );
0446 
0447      // View size actions
0448      m_viewSizeActsGroup = ControlView::createViewSizeActionGroup( this );
0449      connect( m_viewSizeActsGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeViewSize(QAction*)) );
0450 }
0451 
0452 void MainWindow::createMenus( const QList<QAction*> &panelActions )
0453 {
0454         m_fileMenu = menuBar()->addMenu(tr("&File"));
0455         m_fileMenu->addAction(m_openAction);
0456         m_fileMenu->addAction(m_downloadAction);
0457         m_fileMenu->addAction( m_downloadRegionAction );
0458         m_fileMenu->addAction( m_mapWizardAction );
0459         m_fileMenu->addAction(m_exportMapAction);
0460         m_fileMenu->addSeparator();
0461         m_fileMenu->addAction(m_printAction);
0462         m_fileMenu->addAction(m_printPreviewAction);
0463         m_fileMenu->addSeparator();
0464         m_fileMenu->addAction(m_workOfflineAction);
0465         m_fileMenu->addAction(m_quitAction);
0466 
0467         m_fileMenu = menuBar()->addMenu(tr("&Edit"));
0468         m_fileMenu->addAction(m_copyMapAction);
0469         m_fileMenu->addAction(m_copyCoordinatesAction);
0470         m_fileMenu->addAction( m_osmEditAction );
0471         m_fileMenu->addSeparator();
0472         m_fileMenu->addAction(m_recordMovieAction);
0473         m_fileMenu->addAction(m_stopRecordingAction);
0474 
0475         m_viewMenu = menuBar()->addMenu(tr("&View"));
0476         m_infoBoxesMenu = new QMenu(tr("&Info Boxes"), this);
0477         m_onlineServicesMenu = new QMenu(tr("&Online Services"), this);
0478         createPluginsMenus();
0479 
0480         m_bookmarkMenu = menuBar()->addMenu(tr("&Bookmarks"));
0481         createBookmarkMenu();
0482         connect( m_bookmarkMenu, SIGNAL(aboutToShow()), this, SLOT(createBookmarkMenu()) );
0483 
0484         m_panelMenu = new QMenu(tr("&Panels"), this);
0485         for( QAction* action: panelActions ) {
0486             m_panelMenu->addAction( action );
0487         }
0488 
0489         m_viewSizeMenu = new QMenu(tr("&View Size"), this);
0490         m_viewSizeMenu->addActions( m_viewSizeActsGroup->actions() );
0491 
0492         m_settingsMenu = menuBar()->addMenu(tr("&Settings"));
0493         m_settingsMenu->addMenu( m_panelMenu );
0494         m_settingsMenu->addAction(m_statusBarAction);
0495         m_settingsMenu->addSeparator();
0496         m_settingsMenu->addMenu( m_viewSizeMenu );
0497         m_settingsMenu->addAction(m_fullScreenAction);
0498         m_settingsMenu->addSeparator();
0499         m_settingsMenu->addAction(m_configDialogAction);
0500 
0501         m_helpMenu = menuBar()->addMenu(tr("&Help"));
0502         m_helpMenu->addAction(m_handbookAction);
0503         m_helpMenu->addAction(m_forumAction);
0504         m_helpMenu->addSeparator();
0505         m_helpMenu->addAction(m_whatsThisAction);
0506         m_helpMenu->addSeparator();
0507         m_helpMenu->addAction(m_aboutMarbleAction);
0508         m_helpMenu->addAction(m_aboutQtAction);
0509 
0510         // FIXME: Discuss if this is the best place to put this
0511         QList<RenderPlugin *> pluginList = m_controlView->marbleWidget()->renderPlugins();
0512         QList<RenderPlugin *>::const_iterator it = pluginList.constBegin();
0513         QList<RenderPlugin *>::const_iterator const listEnd = pluginList.constEnd();
0514         for (; it != listEnd; ++it ) {
0515             connect( (*it), SIGNAL(actionGroupsChanged()),
0516                      this, SLOT(createPluginMenus()) );
0517         }
0518 }
0519 
0520 void MainWindow::createPluginsMenus()
0521 {
0522     m_onlineServicesMenu->clear();
0523     m_infoBoxesMenu->clear();
0524     m_viewMenu->clear();
0525 
0526     m_viewMenu->addAction(m_reloadAction);
0527     m_viewMenu->addSeparator();
0528 
0529     // Do not create too many menu entries on a MID
0530     // FIXME: Set up another way of switching the plugins on and off.
0531     if( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
0532         return;
0533     }
0534 
0535     m_infoBoxesMenu->addAction(m_lockFloatItemsAction);
0536     m_infoBoxesMenu->addSeparator();
0537     QList<QAction*> themeActions;
0538 
0539     QList<RenderPlugin *> renderPluginList = m_controlView->marbleWidget()->renderPlugins();
0540     QList<RenderPlugin *>::const_iterator i = renderPluginList.constBegin();
0541     QList<RenderPlugin *>::const_iterator const end = renderPluginList.constEnd();
0542     for (; i != end; ++i ) {
0543         switch( (*i)->renderType() ) {
0544         case RenderPlugin::TopLevelRenderType:
0545             m_viewMenu->addAction( (*i)->action() );
0546             break;
0547         case RenderPlugin::PanelRenderType:
0548             m_infoBoxesMenu->addAction( (*i)->action() );
0549             break;
0550         case RenderPlugin::OnlineRenderType:
0551             m_onlineServicesMenu->addAction( (*i)->action() );
0552             break;
0553         case RenderPlugin::ThemeRenderType:
0554             themeActions.append( (*i)->action() );
0555             break;
0556         default:
0557             mDebug() << "No menu entry created for plugin with unknown render type:" << (*i)->nameId();
0558             break;
0559         }
0560     }
0561     m_viewMenu->addMenu( m_infoBoxesMenu );
0562     m_viewMenu->addMenu( m_onlineServicesMenu );
0563     m_viewMenu->addActions( themeActions );
0564     m_viewMenu->addAction( m_showCloudsAction );
0565     m_viewMenu->addSeparator();
0566     m_viewMenu->addAction(m_controlSunAction);
0567     m_viewMenu->addAction(m_controlTimeAction);
0568 }
0569 
0570 void MainWindow::createBookmarksListMenu( QMenu *bookmarksListMenu, const GeoDataContainer *container )
0571 {
0572     //m_bookmarksListMenu->clear();
0573 
0574     QVector<GeoDataPlacemark*> bookmarks = container->placemarkList();
0575 
0576     for ( const GeoDataPlacemark *placemark: bookmarks ) {
0577         QAction *bookmarkAction = new QAction( placemark->name(), this );
0578         QVariant var;
0579 
0580         const GeoDataLookAt* lookAt = placemark->lookAt();
0581         if ( !lookAt ) {
0582             GeoDataCoordinates coordinates = placemark->coordinate();
0583             GeoDataLookAt coordinateToLookAt;
0584             coordinateToLookAt.setCoordinates( coordinates );
0585             coordinateToLookAt.setRange( marbleWidget()->lookAt().range() );
0586             var.setValue( coordinateToLookAt );
0587         } else {
0588             var.setValue( *lookAt );
0589         }
0590         bookmarkAction->setData( var );
0591         bookmarksListMenu->addAction( bookmarkAction );
0592     }
0593 
0594 }
0595 void MainWindow::createBookmarkMenu()
0596 {
0597     m_bookmarkMenu->clear();
0598     m_bookmarkMenu->addAction( m_addBookmarkAction );
0599     m_bookmarkMenu->addAction( m_toggleBookmarkDisplayAction );
0600     m_toggleBookmarkDisplayAction->setChecked( m_controlView->marbleModel()->bookmarkManager()->document()->isVisible() );
0601     m_bookmarkMenu->addAction( m_setHomeAction );
0602     m_bookmarkMenu->addAction( m_manageBookmarksAction );
0603 
0604     m_bookmarkMenu->addSeparator();
0605 
0606     m_bookmarkMenu->addAction( QIcon(QStringLiteral(":/icons/go-home.png")), tr("&Home"),
0607                                m_controlView->marbleWidget(), SLOT(goHome()) );
0608     createFolderList( m_bookmarkMenu, m_controlView->marbleModel()->bookmarkManager()->document() );
0609 }
0610 
0611 void MainWindow::createFolderList( QMenu *bookmarksListMenu, const GeoDataContainer *container )
0612 {
0613     QVector<GeoDataFolder*> folders = container->folderList();
0614 
0615     if ( folders.size() == 1 && folders.first()->name() == tr("Default")) {
0616         createBookmarksListMenu( bookmarksListMenu, folders.first() );
0617     }
0618     else {
0619         for ( const GeoDataFolder *folder: folders ) {
0620             QMenu *subMenu = bookmarksListMenu->addMenu(QIcon(QStringLiteral(":/icons/folder-bookmark.png")), folder->name());
0621             createFolderList( subMenu, folder );
0622             connect( subMenu, SIGNAL(triggered(QAction*)),
0623                                       this, SLOT(lookAtBookmark(QAction*)) );
0624         }
0625     }
0626 
0627     createBookmarksListMenu( bookmarksListMenu, container );
0628     connect( bookmarksListMenu, SIGNAL(triggered(QAction*)),
0629                               this, SLOT(lookAtBookmark(QAction*)) );
0630 }
0631 
0632 
0633 void MainWindow::lookAtBookmark( QAction *action)
0634 {
0635     if ( action->data().isNull() ) {
0636         return;
0637     }
0638 
0639     GeoDataLookAt temp = qvariant_cast<GeoDataLookAt>( action->data() ) ;
0640     m_controlView->marbleWidget()->flyTo( temp ) ;
0641     mDebug() << " looking at bookmark having longitude : "<< temp.longitude(GeoDataCoordinates::Degree)
0642              << " latitude :  "<< temp.latitude(GeoDataCoordinates::Degree)
0643              << " distance : " << temp.range();
0644 
0645 
0646 }
0647 
0648 void MainWindow::manageBookmarks()
0649 {
0650     MarbleModel * const model = m_controlView->marbleModel();
0651     QPointer<BookmarkManagerDialog> dialog = new BookmarkManagerDialog( model, this );
0652     dialog->exec();
0653     delete dialog;
0654 }
0655 
0656 void MainWindow::setHome()
0657 {
0658     MarbleWidget *widget = m_controlView->marbleWidget();
0659     widget->model()->setHome( widget->centerLongitude(), widget->centerLatitude(), widget->zoom() );
0660 }
0661 
0662 void MainWindow::openEditBookmarkDialog()
0663 {
0664     MarbleWidget *widget = m_controlView->marbleWidget();
0665     QPointer<EditBookmarkDialog> dialog = new EditBookmarkDialog( widget->model()->bookmarkManager(), widget );
0666     dialog->setMarbleWidget( widget );
0667     dialog->setCoordinates( widget->lookAt().coordinates() );
0668     dialog->setRange( widget->lookAt().range() );
0669     dialog->setReverseGeocodeName();
0670     if ( dialog->exec() == QDialog::Accepted ) {
0671         widget->model()->bookmarkManager()->addBookmark( dialog->folder(), dialog->bookmark() );
0672     }
0673     delete dialog;
0674 }
0675 
0676 void MainWindow::createPluginMenus()
0677 {
0678     // Remove and delete toolbars if they exist
0679     while( !m_pluginToolbars.isEmpty() ) {
0680         QToolBar* tb = m_pluginToolbars.takeFirst();
0681         this->removeToolBar(tb);
0682         tb->deleteLater();
0683     }
0684 
0685     // Do not create too many menu entries on a MID
0686     // FIXME: Set up another way of switching the plugins on and off.
0687     if( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) {
0688         return;
0689     }
0690 
0691     //remove and delete old menus if they exist
0692     while(  !m_pluginMenus.isEmpty() ) {
0693         m_viewMenu->removeAction( m_pluginMenus.takeFirst() );
0694     }
0695 
0696     QList<RenderPlugin *> renderPluginList = m_controlView->marbleWidget()->renderPlugins();
0697     QList<RenderPlugin *>::const_iterator i = renderPluginList.constBegin();
0698     QList<RenderPlugin *>::const_iterator const end = renderPluginList.constEnd();
0699 
0700     for (; i != end; ++i ) {
0701 
0702         // menus
0703         const QList<QActionGroup*> *tmp_actionGroups = (*i)->actionGroups();
0704         if ((*i)->enabled() && tmp_actionGroups && (*i)->nameId() != QLatin1String("annotation")) {
0705            for( QActionGroup *ag: *tmp_actionGroups ) {
0706                if( !ag->actions().isEmpty() ) {
0707                    m_pluginMenus.append( m_viewMenu->addSeparator() );
0708                }
0709                for( QAction *action: ag->actions() ) {
0710                    m_viewMenu->addAction( action );
0711                    m_pluginMenus.append( action );
0712                }
0713            }
0714         }
0715 
0716         // toolbars
0717         const QList<QActionGroup*> *tmp_toolbarActionGroups = (*i)->toolbarActionGroups();
0718         if ( (*i)->enabled() && tmp_toolbarActionGroups ) {
0719             QToolBar* toolbar = new QToolBar(this);
0720             toolbar->setObjectName(QLatin1String("plugin-toolbar-") + (*i)->nameId());
0721 
0722             for( QActionGroup* ag: *tmp_toolbarActionGroups ) {
0723                 toolbar->addActions( ag->actions() );
0724                 if ( tmp_toolbarActionGroups->last() != ag ) {
0725                     toolbar->addSeparator();
0726                 }
0727             }
0728 
0729             m_pluginToolbars.append( toolbar );
0730             this->addToolBar( toolbar );
0731         }
0732     }
0733 
0734 //    FIXME: load the menus once the method has been settled on
0735 }
0736 
0737 void MainWindow::createStatusBar()
0738 {
0739     statusBar()->showMessage(tr("Ready"));
0740     statusBar()->hide();
0741 }
0742 
0743 void MainWindow::openMapDialog()
0744 {
0745     QPointer<MapThemeDownloadDialog> dialog( new MapThemeDownloadDialog( m_controlView->marbleWidget() ) );
0746     dialog->exec();
0747     delete dialog;
0748 }
0749 
0750 void MainWindow::exportMapScreenShot()
0751 {
0752     QString fileName = QFileDialog::getSaveFileName(this, tr("Export Map"), // krazy:exclude=qclasses
0753                             QDir::homePath(),
0754                             tr("Images (*.jpg *.png)"));
0755 
0756     if ( !fileName.isEmpty() )
0757     {
0758         // Take the case into account where no file format is indicated
0759         const char * format = nullptr;
0760         if ( !fileName.endsWith(QLatin1String( "png" ), Qt::CaseInsensitive)
0761            && !fileName.endsWith(QLatin1String( "jpg" ), Qt::CaseInsensitive) )
0762         {
0763             format = "JPG";
0764         }
0765 
0766         QPixmap mapPixmap = m_controlView->mapScreenShot();
0767         bool success = mapPixmap.save( fileName, format );
0768         if ( !success )
0769         {
0770             QMessageBox::warning(this, tr("Marble"), // krazy:exclude=qclasses
0771                    tr( "An error occurred while trying to save the file.\n" ),
0772                    QMessageBox::Ok);
0773         }
0774     }
0775 }
0776 
0777 
0778 void MainWindow::showFullScreen( bool isChecked )
0779 {
0780     if ( isChecked ) {
0781         setWindowState( windowState() | Qt::WindowFullScreen ); // set
0782     }
0783     else {
0784         setWindowState( windowState() & ~Qt::WindowFullScreen ); // reset
0785     }
0786 
0787     m_fullScreenAction->setChecked( isChecked ); // Sync state with the GUI
0788 }
0789 
0790 void MainWindow::copyCoordinates()
0791 {
0792     qreal lon = m_controlView->marbleWidget()->centerLongitude();
0793     qreal lat = m_controlView->marbleWidget()->centerLatitude();
0794 
0795     QString  positionString = GeoDataCoordinates( lon, lat, 0.0, GeoDataCoordinates::Degree ).toString();
0796     QClipboard  *clipboard = QApplication::clipboard();
0797 
0798     clipboard->setText( positionString );
0799 }
0800 
0801 void MainWindow::copyMap()
0802 {
0803     QPixmap      mapPixmap = m_controlView->mapScreenShot();
0804     QClipboard  *clipboard = QApplication::clipboard();
0805 
0806     clipboard->setPixmap( mapPixmap );
0807 }
0808 
0809 void MainWindow::showStatusBar( bool isChecked )
0810 {
0811     if ( isChecked )
0812     {
0813         statusBar()->show();
0814     }
0815     else
0816     {
0817         statusBar()->hide();
0818     }
0819 
0820     m_statusBarAction->setChecked( isChecked ); // Sync state with the GUI
0821 }
0822 
0823 void MainWindow::showClouds( bool isChecked )
0824 {
0825     m_controlView->marbleWidget()->setShowClouds( isChecked );
0826 
0827     m_showCloudsAction->setChecked( isChecked ); // Sync state with the GUI
0828 }
0829 
0830 void MainWindow::showBookmarks( bool show )
0831 {
0832     m_controlView->marbleModel()->bookmarkManager()->setShowBookmarks( show );
0833 
0834     m_toggleBookmarkDisplayAction->setChecked( show ); // Sync state with the GUI
0835 }
0836 
0837 void MainWindow::workOffline( bool offline )
0838 {
0839     m_controlView->setWorkOffline( offline );
0840 
0841     m_workOfflineAction->setChecked( offline ); // Sync state with the GUI
0842 }
0843 
0844 void MainWindow::lockPosition( bool isChecked )
0845 {
0846     QList<AbstractFloatItem *> floatItemList = m_controlView->marbleWidget()->floatItems();
0847 
0848     QList<AbstractFloatItem *>::const_iterator i = floatItemList.constBegin();
0849     QList<AbstractFloatItem *>::const_iterator const end = floatItemList.constEnd();
0850     for (; i != end; ++i )
0851     {
0852         // Locking one would suffice as it affects all.
0853         // Nevertheless go through all.
0854         (*i)->setPositionLocked(isChecked);
0855     }
0856 }
0857 
0858 void MainWindow::controlSun()
0859 {
0860     if (!m_sunControlDialog) {
0861         m_sunControlDialog = new SunControlWidget( m_controlView->marbleWidget(), this );
0862         connect( m_sunControlDialog, SIGNAL(showSun(bool)),
0863                  this,               SLOT (showSun(bool)) );
0864     }
0865 
0866      m_sunControlDialog->show();
0867      m_sunControlDialog->raise();
0868      m_sunControlDialog->activateWindow();
0869 }
0870 
0871 void MainWindow::controlTime()
0872 {
0873     if ( !m_timeControlDialog )
0874     {
0875         m_timeControlDialog = new TimeControlWidget( m_controlView->marbleModel()->clock() );
0876     }
0877     /* m_timeControlDialog is a modeless dialog so that user may adjust time and interact with main application simultaneously.*/
0878     m_timeControlDialog->show();
0879     m_timeControlDialog->raise();
0880     m_timeControlDialog->activateWindow();
0881 }
0882 
0883 
0884 void MainWindow::showSun( bool active )
0885 {
0886     m_controlView->marbleWidget()->setShowSunShading( active );
0887 }
0888 
0889 void MainWindow::reload()
0890 {
0891     m_controlView->marbleWidget()->reloadMap();
0892 }
0893 
0894 void MainWindow::enterWhatsThis()
0895 {
0896     QWhatsThis::enterWhatsThisMode();
0897 }
0898 
0899 void MainWindow::aboutMarble()
0900 {
0901     MarbleAboutDialog dlg(this);
0902     dlg.setApplicationTitle( tr( "Marble Virtual Globe %1" ).arg( ControlView::applicationVersion() ) );
0903     dlg.exec();
0904 }
0905 
0906 void MainWindow::handbook()
0907 {
0908     const QString code = MarbleLocale::languageCode();
0909 
0910     // docs.kde.org falls back to the English manual if no translated
0911     // documentation is available for the requested language.
0912     QUrl handbookLocation(QLatin1String("https://docs.kde.org/?application=marble&branch=stable5&language=") + code);
0913 
0914     if( !QDesktopServices::openUrl( handbookLocation ) )
0915     qDebug() << "URL not opened";
0916 }
0917 
0918 void MainWindow::openForum()
0919 {
0920     QUrl forumLocation("https://forum.kde.org/viewforum.php?f=217");
0921     if( !QDesktopServices::openUrl( forumLocation ) ) {
0922         mDebug() << "Failed to open URL " << forumLocation.toString();
0923     }
0924 }
0925 
0926 void MainWindow::showPosition( const QString& position )
0927 {
0928     m_position = position;
0929     updateStatusBar();
0930 }
0931 
0932 void MainWindow::showDistance( const QString& distance )
0933 {
0934     m_distance = distance;
0935     updateStatusBar();
0936 }
0937 
0938 void MainWindow::showZoom( int zoom )
0939 {
0940     m_zoom = QString::number( zoom );
0941     updateStatusBar();
0942 }
0943 
0944 void MainWindow::showDateTime()
0945 {
0946     m_clock = QLocale().toString( m_controlView->marbleModel()->clockDateTime().addSecs( m_controlView->marbleModel()->clockTimezone() ), QLocale::ShortFormat );
0947     updateStatusBar();
0948 }
0949 
0950 void MainWindow::updateStatusBar()
0951 {
0952     if ( m_positionLabel )
0953         m_positionLabel->setText(tr("Position: %1").arg(m_position));
0954 
0955     if ( m_distanceLabel )
0956         m_distanceLabel->setText(tr("Altitude: %1").arg(m_distance));
0957 
0958     if ( m_zoomLabel )
0959         m_zoomLabel->setText(tr("Zoom: %1").arg(m_zoom));
0960 
0961     if ( m_clockLabel )
0962         m_clockLabel->setText(tr("Time: %1").arg(m_clock));
0963 
0964     switch ( m_configDialog->angleUnit() ) {
0965     case DMSDegree:
0966         m_dmsDegreeAction->setChecked( true );
0967         break;
0968     case DecimalDegree:
0969         m_decimalDegreeAction->setChecked( true );
0970         break;
0971     case UTM:
0972         m_utmAction->setChecked( true );
0973         break;
0974     }
0975 }
0976 
0977 void MainWindow::openFile()
0978 {
0979     const PluginManager *const pluginManager = m_controlView->marbleModel()->pluginManager();
0980 
0981     QStringList allFileExtensions;
0982     QStringList filters;
0983     for ( const ParseRunnerPlugin *plugin: pluginManager->parsingRunnerPlugins() ) {
0984         if (plugin->nameId() == QLatin1String("Cache"))
0985             continue;
0986 
0987         const QStringList fileExtensions = plugin->fileExtensions().replaceInStrings( QRegExp( "^" ), "*." );
0988         const QString filter = plugin->fileFormatDescription() + QLatin1String(" (") + fileExtensions.join(QLatin1Char(' ')) + QLatin1Char(')');
0989         filters << filter;
0990         allFileExtensions << fileExtensions;
0991     }
0992 
0993     allFileExtensions.sort();  // sort since file extensions are visible under Windows
0994     const QString allFileTypes = tr("All Supported Files") + QLatin1String(" (") + allFileExtensions.join(QLatin1Char(' ')) + QLatin1Char(')');
0995 
0996     filters.sort();
0997     filters.prepend( allFileTypes );
0998     const QString filter = filters.join( ";;" );
0999 
1000     QStringList fileNames = QFileDialog::getOpenFileNames( this, tr( "Open File" ), m_lastFileOpenPath, filter );
1001 
1002     if ( !fileNames.isEmpty() ) {
1003         const QString firstFile = fileNames.first();
1004         m_lastFileOpenPath = QFileInfo( firstFile ).absolutePath();
1005     }
1006 
1007     for( const QString &fileName: fileNames ) {
1008         m_controlView->marbleModel()->addGeoDataFile( fileName );
1009     }
1010 }
1011 
1012 void MainWindow::setupStatusBar()
1013 {
1014     statusBar()->setSizeGripEnabled( true );
1015     statusBar()->setContextMenuPolicy( Qt::ActionsContextMenu );
1016 
1017     statusBar()->addAction( m_toggleTileLevelAction );
1018 
1019     QMenu *angleDisplayUnitMenu = new QMenu(this);
1020     angleDisplayUnitMenu->addActions( m_angleDisplayUnitActionGroup->actions() );
1021     QAction *angleDisplayUnitMenuAction = new QAction( tr("&Angle Display Unit"), statusBar() );
1022     angleDisplayUnitMenuAction->setMenu( angleDisplayUnitMenu );
1023     statusBar()->addAction( angleDisplayUnitMenuAction );
1024 
1025     setupDownloadProgressBar();
1026 
1027     m_positionLabel = new QLabel( );
1028     m_positionLabel->setIndent( 5 );
1029     // UTM syntax is used in the template string, as it is longer than the lon/lat one
1030     QString templatePositionString = tr("Position: %1").arg(QLatin1String(" 00Z 000000.00 m E, 00000000.00 m N_"));
1031     int maxPositionWidth = fontMetrics().boundingRect(templatePositionString).width()
1032                             + 2 * m_positionLabel->margin() + 2 * m_positionLabel->indent();
1033     m_positionLabel->setFixedWidth( maxPositionWidth );
1034     statusBar()->addPermanentWidget ( m_positionLabel );
1035 
1036     m_distanceLabel = new QLabel( );
1037     m_distanceLabel->setIndent( 5 );
1038     QString templateDistanceString = tr("Altitude: %1").arg(QLatin1String(" 00.000,0 mu"));
1039     int maxDistanceWidth = fontMetrics().boundingRect(templateDistanceString).width()
1040                             + 2 * m_distanceLabel->margin() + 2 * m_distanceLabel->indent();
1041     m_distanceLabel->setFixedWidth( maxDistanceWidth );
1042     statusBar()->addPermanentWidget ( m_distanceLabel );
1043 
1044     m_zoomLabel = new QLabel( );
1045     m_zoomLabel->setIndent( 5 );
1046     QString templateZoomString = tr("Zoom: %1").arg(QLatin1String(" 00"));
1047     int maxZoomWidth = fontMetrics().boundingRect(templateZoomString).width()
1048                             + 2 * m_zoomLabel->margin() + 2 * m_zoomLabel->indent();
1049     m_zoomLabel->setFixedWidth( maxZoomWidth );
1050     // Not added here, but activated by the user with the context menu
1051 
1052     m_clockLabel = new QLabel( );
1053     m_clockLabel->setIndent( 5 );
1054     QString templateDateTimeString = tr("Time: %1").arg(QLocale().toString(QDateTime::fromString( "01:01:1000", "dd:mm:yyyy"), QLocale::ShortFormat));
1055     int maxDateTimeWidth = fontMetrics().boundingRect( templateDateTimeString ).width()
1056                             + 2 * m_clockLabel->margin() + 2 * m_clockLabel->indent();
1057     m_clockLabel->setFixedWidth( maxDateTimeWidth );
1058     statusBar()->addPermanentWidget ( m_clockLabel );
1059 
1060     connect( marbleWidget(), SIGNAL(mouseMoveGeoPosition(QString)),
1061               this, SLOT(showPosition(QString)) );
1062     connect( marbleWidget(), SIGNAL(distanceChanged(QString)),
1063               this, SLOT(showDistance(QString)) );
1064     connect( marbleWidget(), SIGNAL(tileLevelChanged(int)),
1065             this, SLOT(showZoom(int)) );
1066     connect( m_controlView->marbleModel()->clock(), SIGNAL(timeChanged()),
1067               this, SLOT(showDateTime()) );
1068 
1069     updateStatusBar();
1070 }
1071 
1072 void MainWindow::setupDownloadProgressBar()
1073 {
1074     m_downloadProgressBar = new QProgressBar;
1075     m_downloadProgressBar->setVisible( true );
1076     statusBar()->addPermanentWidget( m_downloadProgressBar );
1077 
1078     HttpDownloadManager * const downloadManager =
1079         m_controlView->marbleModel()->downloadManager();
1080     Q_ASSERT( downloadManager );
1081     connect( downloadManager, SIGNAL(progressChanged(int,int)), SLOT(handleProgress(int,int)) );
1082     connect( downloadManager, SIGNAL(jobRemoved()), SLOT(removeProgressItem()) );
1083 }
1084 
1085 void MainWindow::handleProgress( int active, int queued ){
1086     m_downloadProgressBar->setUpdatesEnabled( false );
1087     if ( m_downloadProgressBar->value() < 0 ) {
1088         m_downloadProgressBar->setMaximum( 1 );
1089         m_downloadProgressBar->setValue( 0 );
1090         m_downloadProgressBar->setVisible( true );
1091     } else {
1092         m_downloadProgressBar->setMaximum( qMax<int>( m_downloadProgressBar->maximum(), active + queued ) );
1093     }
1094 
1095     m_downloadProgressBar->setUpdatesEnabled( true );
1096 }
1097 
1098 void MainWindow::removeProgressItem(){
1099     m_downloadProgressBar->setUpdatesEnabled( false );
1100     m_downloadProgressBar->setValue( m_downloadProgressBar->value() + 1 );
1101     if ( m_downloadProgressBar->value() == m_downloadProgressBar->maximum() ) {
1102         m_downloadProgressBar->reset();
1103         m_downloadProgressBar->setVisible( false );
1104     }
1105 
1106     m_downloadProgressBar->setUpdatesEnabled( true );
1107 }
1108 
1109 void MainWindow::closeEvent( QCloseEvent *event )
1110 {
1111     writeSettings();
1112 
1113     QCloseEvent newEvent;
1114     QCoreApplication::sendEvent( m_controlView, &newEvent );
1115 
1116     if ( newEvent.isAccepted() ) {
1117         event->accept();
1118     } else {
1119         event->ignore();
1120     }
1121 }
1122 
1123 QString MainWindow::readMarbleDataPath()
1124 {
1125      QSettings settings;
1126 
1127      settings.beginGroup("MarbleWidget");
1128      const auto marbleDataPath = settings.value("marbleDataPath", "").toString();
1129      settings.endGroup();
1130 
1131      return marbleDataPath;
1132 }
1133 
1134 void MainWindow::readSettings(const QVariantMap& overrideSettings)
1135 {
1136      QSettings settings;
1137 
1138      settings.beginGroup("MainWindow");
1139          resize(settings.value("size", QSize(640, 480)).toSize());
1140          move(settings.value("pos", QPoint(200, 200)).toPoint());
1141          showFullScreen(settings.value("fullScreen", false ).toBool());
1142          showStatusBar(settings.value("statusBar", false ).toBool());
1143          showZoomLevel(settings.value("showZoomLevel",false).toBool());
1144          show();
1145          showClouds(settings.value("showClouds", true ).toBool());
1146          workOffline(settings.value("workOffline", false ).toBool());
1147          m_controlView->marbleWidget()->setShowAtmosphere(settings.value("showAtmosphere", true ).toBool());
1148          m_lastFileOpenPath = settings.value("lastFileOpenDir", QDir::homePath()).toString();
1149          showBookmarks( settings.value( "showBookmarks", true ).toBool() );
1150          restoreState( settings.value("windowState").toByteArray() );
1151      settings.endGroup();
1152 
1153      setUpdatesEnabled(false);
1154 
1155      settings.beginGroup("MarbleWidget");
1156          QString mapThemeId;
1157          const QVariantMap::ConstIterator mapThemeIdIt = overrideSettings.find(QLatin1String("mapTheme"));
1158          if ( mapThemeIdIt != overrideSettings.constEnd() ) {
1159             mapThemeId = mapThemeIdIt.value().toString();
1160          } else {
1161             mapThemeId = settings.value("mapTheme", m_controlView->defaultMapThemeId() ).toString();
1162          }
1163          mDebug() << "mapThemeId:" << mapThemeId;
1164          m_controlView->marbleWidget()->setMapThemeId( mapThemeId );
1165          m_controlView->marbleWidget()->setProjection(
1166             (Projection)(settings.value("projection", Spherical ).toInt())
1167          );
1168 
1169          // Set home position
1170          m_controlView->marbleModel()->setHome(
1171             settings.value("homeLongitude", 9.4).toDouble(),
1172             settings.value("homeLatitude", 54.8).toDouble(),
1173             settings.value("homeZoom", 1050 ).toInt()
1174          );
1175 
1176          // Center on/Distance
1177          const QVariantMap::ConstIterator distanceIt = overrideSettings.find(QLatin1String("distance"));
1178          const bool isDistanceOverwritten = (distanceIt != overrideSettings.constEnd());
1179 
1180          const QVariantMap::ConstIterator lonLatIt = overrideSettings.find(QLatin1String("lonlat"));
1181          if ( lonLatIt != overrideSettings.constEnd() ) {
1182             const QVariantList lonLat = lonLatIt.value().toList();
1183             m_controlView->marbleWidget()->centerOn( lonLat.at(0).toDouble(), lonLat.at(1).toDouble() );
1184          } else {
1185             switch ( m_configDialog->onStartup() ) {
1186             case Marble::LastLocationVisited:
1187                 m_controlView->marbleWidget()->centerOn(
1188                     settings.value("quitLongitude", 0.0).toDouble(),
1189                     settings.value("quitLatitude", 0.0).toDouble() );
1190                 if (! isDistanceOverwritten) {
1191                     // set default radius to 1350 (Atlas theme's "sharp" radius)
1192                     m_controlView->marbleWidget()->setRadius( settings.value("quitRadius", 1350).toInt() );
1193                 }
1194                 break;
1195             case Marble::ShowHomeLocation:
1196                 m_controlView->marbleWidget()->goHome();
1197                 break;
1198             default:
1199                 break;
1200             }
1201          }
1202          if (isDistanceOverwritten) {
1203              m_controlView->marbleWidget()->setDistance(distanceIt.value().toDouble());
1204          }
1205 
1206          // Geo URI parsing
1207          QString geoUriString = qvariant_cast<QString>( overrideSettings.value("geo-uri", ""));
1208          if ( !geoUriString.isEmpty() ) {
1209              m_controlView->openGeoUri( geoUriString );
1210          }
1211 
1212          bool isLocked = settings.value( "lockFloatItemPositions", false ).toBool();
1213          m_lockFloatItemsAction->setChecked( isLocked );
1214          lockPosition(isLocked);
1215      settings.endGroup();
1216 
1217      settings.beginGroup( "Sun" );
1218          m_controlView->marbleWidget()->setShowSunShading( settings.value( "showSun", false ).toBool() );
1219          m_controlView->marbleWidget()->setShowCityLights( settings.value( "showCitylights", false ).toBool() );
1220          m_controlView->marbleWidget()->setLockToSubSolarPoint( settings.value( "lockToSubSolarPoint", false ).toBool() );
1221          m_controlView->marbleWidget()->setSubSolarPointIconVisible( settings.value( "subSolarPointIconVisible", false ).toBool() );
1222      settings.endGroup();
1223 
1224      settings.beginGroup( "Time" );
1225         if( settings.value( "systemTime", "true" ).toBool() == true  )
1226         {
1227             /* nothing to do */
1228         }
1229         else if( settings.value( "lastSessionTime", "true" ).toBool() == true )
1230         {
1231             m_controlView->marbleModel()->setClockDateTime( settings.value( "dateTime" ).toDateTime() );
1232             m_controlView->marbleModel()->setClockSpeed( settings.value( "speedSlider", 1 ).toInt() );
1233         }
1234      settings.endGroup();
1235 
1236      setUpdatesEnabled(true);
1237 
1238      // Load previous route settings
1239      settings.beginGroup( "Routing" );
1240      {
1241          RoutingManager *const routingManager = m_controlView->marbleModel()->routingManager();
1242          routingManager->readSettings();
1243          bool const startupWarning = settings.value( "showGuidanceModeStartupWarning", QVariant( true ) ).toBool();
1244          routingManager->setShowGuidanceModeStartupWarning( startupWarning );
1245          routingManager->setLastOpenPath( settings.value( "lastRouteOpenPath", QDir::homePath() ).toString() );
1246          routingManager->setLastSavePath( settings.value( "lastRouteSavePath", QDir::homePath() ).toString() );
1247 
1248          QColor tempColor;
1249          tempColor = QColor( settings.value( "routeColorStandard", Oxygen::skyBlue4.name() ).toString() );
1250          tempColor.setAlpha( settings.value( "routeAlphaStandard", 200 ).toInt() );
1251          routingManager->setRouteColorStandard( tempColor );
1252 
1253          tempColor = QColor( settings.value( "routeColorHighlighted", Oxygen::skyBlue1.name() ).toString() );
1254          tempColor.setAlpha( settings.value( "routeAlphaHighlighted", 200 ).toInt() );
1255          routingManager->setRouteColorHighlighted( tempColor );
1256 
1257          tempColor = QColor( settings.value( "routeColorAlternative", Oxygen::aluminumGray4.name() ).toString() );
1258          tempColor.setAlpha( settings.value( "routeAlphaAlternative", 200 ).toInt() );
1259          routingManager->setRouteColorAlternative( tempColor );
1260      }
1261      settings.endGroup();
1262 
1263 
1264     settings.beginGroup( "Routing Profile" );
1265     if ( settings.contains( "Num" ) ) {
1266         QList<RoutingProfile> profiles;
1267         int numProfiles = settings.value( "Num", 0 ).toInt();
1268         for ( int i = 0; i < numProfiles; ++i ) {
1269             settings.beginGroup( QString( "Profile %0" ).arg(i) );
1270             QString name = settings.value( "Name", tr( "Unnamed" ) ).toString();
1271             RoutingProfile profile( name );
1272             for ( const QString& pluginName: settings.childGroups() ) {
1273                 settings.beginGroup( pluginName );
1274                 profile.pluginSettings().insert( pluginName, QHash<QString, QVariant>() );
1275                 for ( const QString& key: settings.childKeys() ) {
1276                     if (key != QLatin1String("Enabled")) {
1277                         profile.pluginSettings()[ pluginName ].insert( key, settings.value( key ) );
1278                     }
1279                 }
1280                 settings.endGroup();
1281             }
1282             profiles << profile;
1283             settings.endGroup();
1284         }
1285         m_controlView->marbleModel()->routingManager()->profilesModel()->setProfiles( profiles );
1286     } else {
1287         m_controlView->marbleModel()->routingManager()->profilesModel()->loadDefaultProfiles();
1288     }
1289     int const profileIndex = settings.value( "currentIndex", 0 ).toInt();
1290     if ( profileIndex >= 0 && profileIndex < m_controlView->marbleModel()->routingManager()->profilesModel()->rowCount() ) {
1291         RoutingProfile profile = m_controlView->marbleModel()->routingManager()->profilesModel()->profiles().at( profileIndex );
1292         m_controlView->marbleModel()->routingManager()->routeRequest()->setRoutingProfile( profile );
1293     }
1294 
1295     settings.endGroup();
1296 
1297     settings.beginGroup( "Plugins");
1298     PositionTracking* tracking = m_controlView->marbleModel()->positionTracking();
1299     tracking->readSettings();
1300     QString positionProvider = settings.value( "activePositionTrackingPlugin", QString() ).toString();
1301     if ( !positionProvider.isEmpty() ) {
1302         const PluginManager* pluginManager = m_controlView->marbleModel()->pluginManager();
1303         for( const PositionProviderPlugin* plugin: pluginManager->positionProviderPlugins() ) {
1304             if ( plugin->nameId() == positionProvider ) {
1305                 PositionProviderPlugin* instance = plugin->newInstance();
1306                 tracking->setPositionProviderPlugin( instance );
1307                 break;
1308             }
1309         }
1310     }
1311     settings.endGroup();
1312 
1313     settings.beginGroup( "Tracking" );
1314     if ( settings.contains( "autoCenter" ) || settings.contains( "recenterMode" ) ) {
1315         CurrentLocationWidget* trackingWidget = m_controlView->currentLocationWidget();
1316         Q_ASSERT( trackingWidget );
1317         trackingWidget->setRecenterMode( settings.value( "recenterMode", 0 ).toInt() );
1318         trackingWidget->setAutoZoom( settings.value( "autoZoom", false ).toBool() );
1319         trackingWidget->setTrackVisible( settings.value( "trackVisible", true ).toBool() );
1320         trackingWidget->setLastOpenPath( settings.value( "lastTrackOpenPath", QDir::homePath() ).toString() );
1321         trackingWidget->setLastSavePath( settings.value( "lastTrackSavePath", QDir::homePath() ).toString() );
1322     }
1323     settings.endGroup();
1324 
1325      // The config dialog has to read settings.
1326      m_configDialog->readSettings();
1327 
1328      settings.beginGroup( "Navigation" );
1329      m_controlView->setExternalMapEditor( settings.value( "externalMapEditor", "" ).toString() );
1330      settings.endGroup();
1331 
1332      settings.beginGroup( "CloudSync" );
1333      CloudSyncManager* cloudSyncManager = m_controlView->cloudSyncManager();
1334      cloudSyncManager->setOwncloudCredentials( settings.value( "owncloudServer", "" ).toString(),
1335                                                settings.value( "owncloudUsername", "" ).toString(),
1336                                                settings.value( "owncloudPassword", "" ).toString() );
1337      cloudSyncManager->setSyncEnabled( settings.value( "enableSync", false ).toBool() );
1338      cloudSyncManager->routeSyncManager()->setRouteSyncEnabled( settings.value( "syncRoutes", true ).toBool() );
1339      cloudSyncManager->bookmarkSyncManager()->setBookmarkSyncEnabled( settings.value( "syncBookmarks", true ).toBool() );
1340      settings.endGroup();
1341 }
1342 
1343 void MainWindow::writeSettings()
1344 {
1345      QSettings settings;
1346 
1347      settings.beginGroup( "MainWindow" );
1348          settings.setValue( "size", size() );
1349          settings.setValue( "pos", pos() );
1350          settings.setValue( "fullScreen", m_fullScreenAction->isChecked() );
1351          settings.setValue( "statusBar", m_statusBarAction->isChecked() );
1352          settings.setValue( "showZoomLevel", m_toggleTileLevelAction->isChecked() );
1353          settings.setValue( "showClouds", m_showCloudsAction->isChecked() );
1354          settings.setValue( "workOffline", m_workOfflineAction->isChecked() );
1355          settings.setValue( "showAtmosphere", m_controlView->marbleWidget()->showAtmosphere() );
1356          settings.setValue( "lastFileOpenDir", m_lastFileOpenPath );
1357          settings.setValue( "showBookmarks", m_toggleBookmarkDisplayAction->isChecked() );
1358          settings.setValue( "windowState", saveState() );
1359      settings.endGroup();
1360 
1361      settings.beginGroup( "MarbleWidget" );
1362          // Get the 'home' values from the widget and store them in the settings.
1363          qreal homeLon = 0;
1364          qreal homeLat = 0;
1365          int homeZoom = 0;
1366          m_controlView->marbleModel()->home( homeLon, homeLat, homeZoom );
1367          QString  mapTheme = m_controlView->marbleWidget()->mapThemeId();
1368          int      projection = (int)( m_controlView->marbleWidget()->projection() );
1369 
1370          settings.setValue( "homeLongitude", homeLon );
1371          settings.setValue( "homeLatitude",  homeLat );
1372          settings.setValue( "homeZoom",      homeZoom );
1373 
1374          settings.setValue( "mapTheme",   mapTheme );
1375          settings.setValue( "projection", projection );
1376 
1377          // Get the 'quit' values from the widget and store them in the settings.
1378          qreal  quitLon = m_controlView->marbleWidget()->centerLongitude();
1379          qreal  quitLat = m_controlView->marbleWidget()->centerLatitude();
1380          const int quitRadius = m_controlView->marbleWidget()->radius();
1381 
1382          settings.setValue( "quitLongitude", quitLon );
1383          settings.setValue( "quitLatitude", quitLat );
1384          settings.setValue( "quitRadius", quitRadius );
1385 
1386          settings.setValue( "lockFloatItemPositions", m_lockFloatItemsAction->isChecked() );
1387      settings.endGroup();
1388 
1389      settings.beginGroup( "Sun" );
1390          settings.setValue( "showSun", m_controlView->marbleWidget()->showSunShading() );
1391          settings.setValue( "showCitylights", m_controlView->marbleWidget()->showCityLights() );
1392          settings.setValue( "lockToSubSolarPoint", m_controlView->marbleWidget()->isLockedToSubSolarPoint() );
1393          settings.setValue( "subSolarPointIconVisible", m_controlView->marbleWidget()->isSubSolarPointIconVisible() );
1394      settings.endGroup();
1395 
1396       settings.beginGroup( "Time" );
1397          settings.setValue( "dateTime", m_controlView->marbleModel()->clockDateTime() );
1398          settings.setValue( "speedSlider", m_controlView->marbleModel()->clockSpeed() );
1399      settings.endGroup();
1400 
1401      settings.beginGroup( "Routing Profile" );
1402      QList<RoutingProfile>  profiles = m_controlView->marbleWidget()
1403                          ->model()->routingManager()->profilesModel()->profiles();
1404      settings.setValue( "Num", profiles.count() );
1405      for ( int i = 0; i < profiles.count(); ++i ) {
1406          settings.beginGroup( QString( "Profile %0" ).arg(i) );
1407          const RoutingProfile& profile = profiles.at( i );
1408          settings.setValue( "Name", profile.name() );
1409          for ( const QString& pluginName: settings.childGroups() ) {
1410              settings.beginGroup( pluginName );
1411              settings.remove(QString()); //remove all keys
1412              settings.endGroup();
1413          }
1414          for ( const QString &key: profile.pluginSettings().keys() ) {
1415              settings.beginGroup( key );
1416              settings.setValue( "Enabled", true );
1417              for ( const QString& settingKey: profile.pluginSettings()[ key ].keys() ) {
1418                  Q_ASSERT(settingKey != QLatin1String("Enabled"));
1419                  settings.setValue( settingKey, profile.pluginSettings()[ key ][ settingKey ] );
1420              }
1421              settings.endGroup();
1422          }
1423          settings.endGroup();
1424      }
1425      RoutingProfile const profile = m_controlView->marbleWidget()->model()->routingManager()->routeRequest()->routingProfile();
1426      settings.setValue( "currentIndex", profiles.indexOf( profile ) );
1427      settings.endGroup();
1428 
1429      settings.beginGroup( "Plugins");
1430      QString positionProvider;
1431      PositionTracking* tracking = m_controlView->marbleModel()->positionTracking();
1432      tracking->writeSettings();
1433      if ( tracking->positionProviderPlugin() ) {
1434          positionProvider = tracking->positionProviderPlugin()->nameId();
1435      }
1436      settings.setValue( "activePositionTrackingPlugin", positionProvider );
1437      settings.endGroup();
1438 
1439      settings.beginGroup( "Tracking" );
1440      CurrentLocationWidget* trackingWidget = m_controlView->currentLocationWidget();
1441      if ( trackingWidget ) {
1442          // Can be null due to lazy initialization
1443          settings.setValue( "recenterMode", trackingWidget->recenterMode() );
1444          settings.setValue( "autoZoom", trackingWidget->autoZoom() );
1445          settings.setValue( "trackVisible", trackingWidget->trackVisible() );
1446          settings.setValue( "lastTrackOpenPath", trackingWidget->lastOpenPath() );
1447          settings.setValue( "lastTrackSavePath", trackingWidget->lastSavePath() );
1448      }
1449      settings.endGroup();
1450 
1451      // The config dialog has to write settings.
1452      m_configDialog->writeSettings();
1453 
1454      // Store current route settings
1455      settings.beginGroup( "Routing" );
1456      {
1457          RoutingManager *const routingManager = m_controlView->marbleModel()->routingManager();
1458          routingManager->writeSettings();
1459          settings.setValue( "showGuidanceModeStartupWarning", routingManager->showGuidanceModeStartupWarning() );
1460          settings.setValue( "lastRouteOpenPath", routingManager->lastOpenPath() );
1461          settings.setValue( "lastRouteSavePath", routingManager->lastSavePath() );
1462          settings.setValue( "routeColorStandard", routingManager->routeColorStandard().name() );
1463          settings.setValue( "routeAlphaStandard", routingManager->routeColorStandard().alpha() );
1464          settings.setValue( "routeColorHighlighted", routingManager->routeColorHighlighted().name() );
1465          settings.setValue( "routeAlphaHighlighted", routingManager->routeColorHighlighted().alpha() );
1466          settings.setValue( "routeColorAlternative", routingManager->routeColorAlternative().name() );
1467          settings.setValue( "routeAlphaAlternative", routingManager->routeColorAlternative().alpha() );
1468      }
1469      settings.endGroup();
1470 
1471      settings.beginGroup( "Navigation");
1472      settings.setValue( "externalMapEditor", m_controlView->externalMapEditor() );
1473      settings.endGroup();
1474 }
1475 
1476 void MainWindow::editSettings()
1477 {
1478     // Show the settings dialog.
1479     m_configDialog->show();
1480     m_configDialog->raise();
1481     m_configDialog->activateWindow();
1482 }
1483 
1484 void MainWindow::updateSettings()
1485 {
1486     mDebug() << "Updating Settings ...";
1487 
1488     // FIXME: Font doesn't get updated instantly.
1489     m_controlView->marbleWidget()->setDefaultFont( m_configDialog->mapFont() );
1490 
1491     m_controlView->marbleWidget()->setMapQualityForViewContext( m_configDialog->stillQuality(), Marble::Still );
1492     m_controlView->marbleWidget()->setMapQualityForViewContext( m_configDialog->animationQuality(), Marble::Animation );
1493 
1494     m_controlView->marbleWidget()->setDefaultAngleUnit( m_configDialog->angleUnit() );
1495     MarbleGlobal::getInstance()->locale()->setMeasurementSystem( m_configDialog->measurementSystem() );
1496 
1497     m_distance = m_controlView->marbleWidget()->distanceString();
1498     updateStatusBar();
1499 
1500     m_controlView->marbleWidget()->setAnimationsEnabled( m_configDialog->animateTargetVoyage() );
1501     m_controlView->marbleWidget()->inputHandler()->setInertialEarthRotationEnabled( m_configDialog->inertialEarthRotation() );
1502     m_controlView->marbleWidget()->inputHandler()->setMouseViewRotationEnabled( m_configDialog->mouseViewRotation() );
1503     if ( !m_configDialog->externalMapEditor().isEmpty() ) {
1504         m_controlView->setExternalMapEditor( m_configDialog->externalMapEditor() );
1505     }
1506 
1507     // Cache
1508     m_controlView->marbleModel()->setPersistentTileCacheLimit( m_configDialog->persistentTileCacheLimit() * 1024 );
1509     m_controlView->marbleWidget()->setVolatileTileCacheLimit( m_configDialog->volatileTileCacheLimit() * 1024 );
1510 
1511     /*
1512     m_controlView->marbleWidget()->setProxy( m_configDialog->proxyUrl(), m_configDialog->proxyPort(), m_configDialog->user(), m_configDialog->password() );
1513     */
1514 
1515     CloudSyncManager* cloudSyncManager = m_controlView->cloudSyncManager();
1516     cloudSyncManager->setOwncloudCredentials( m_configDialog->owncloudServer(),
1517                                               m_configDialog->owncloudUsername(),
1518                                               m_configDialog->owncloudPassword() );
1519     cloudSyncManager->setSyncEnabled( m_configDialog->syncEnabled() );
1520     cloudSyncManager->routeSyncManager()->setRouteSyncEnabled( m_configDialog->syncRoutes() );
1521     cloudSyncManager->bookmarkSyncManager()->setBookmarkSyncEnabled( m_configDialog->syncBookmarks() );
1522 
1523     m_controlView->marbleWidget()->update();
1524 }
1525 
1526 void MainWindow::showDownloadRegionDialog()
1527 {
1528     if ( !m_downloadRegionDialog ) {
1529         m_downloadRegionDialog = new DownloadRegionDialog( m_controlView->marbleWidget(), m_controlView );
1530         // it might be tempting to move the connects to DownloadRegionDialog's "accepted" and
1531         // "applied" signals, be aware that the "hidden" signal might be come before the "accepted"
1532         // signal, leading to a too early disconnect.
1533         connect( m_downloadRegionDialog, SIGNAL(accepted()), SLOT(downloadRegion()));
1534         connect( m_downloadRegionDialog, SIGNAL(applied()), SLOT(downloadRegion()));
1535     }
1536     // FIXME: get allowed range from current map theme
1537     m_downloadRegionDialog->setAllowedTileLevelRange( 0, 16 );
1538     m_downloadRegionDialog->setSelectionMethod( DownloadRegionDialog::VisibleRegionMethod );
1539     ViewportParams const * const viewport =
1540         m_controlView->marbleWidget()->viewport();
1541     m_downloadRegionDialog->setSpecifiedLatLonAltBox( viewport->viewLatLonAltBox() );
1542     m_downloadRegionDialog->setVisibleLatLonAltBox( viewport->viewLatLonAltBox() );
1543 
1544     m_downloadRegionDialog->show();
1545     m_downloadRegionDialog->raise();
1546     m_downloadRegionDialog->activateWindow();
1547 }
1548 
1549 void MainWindow::downloadRegion()
1550 {
1551     Q_ASSERT( m_downloadRegionDialog );
1552     QVector<TileCoordsPyramid> const pyramid = m_downloadRegionDialog->region();
1553     if ( !pyramid.isEmpty() ) {
1554         m_controlView->marbleWidget()->downloadRegion( pyramid );
1555     }
1556 }
1557 
1558 void MainWindow::printMapScreenShot()
1559 {
1560 #ifndef QT_NO_PRINTER
1561     QPrinter printer( QPrinter::HighResolution );
1562     QPointer<QPrintDialog> printDialog = new QPrintDialog( &printer, this );
1563     m_controlView->printMapScreenShot( printDialog );
1564     delete printDialog;
1565 #endif
1566 }
1567 
1568 void MainWindow::updateMapEditButtonVisibility( const QString &mapTheme )
1569 {
1570     Q_ASSERT( m_osmEditAction );
1571     QStringList osmThemes = QStringList()
1572             << "earth/openstreetmap/openstreetmap.dgml"
1573             << "earth/hikebikemap/hikebikemap.dgml"
1574             << "earth/opencyclemap/opencyclemap.dgml"
1575             << "earth/public-transport/public-transport.dgml"
1576             << "earth/openseamap/openseamap.dgml"
1577             << "earth/vectorosm/vectorosm.dgml";
1578     m_osmEditAction->setVisible(osmThemes.contains(mapTheme));
1579 }
1580 
1581 void MainWindow::showMovieCaptureDialog()
1582 {
1583     if (m_movieCaptureDialog == nullptr) {
1584         m_movieCaptureDialog = new MovieCaptureDialog(m_controlView->marbleWidget(),
1585                                                       m_controlView->marbleWidget());
1586         connect( m_movieCaptureDialog, SIGNAL(started()), this, SLOT(changeRecordingState()));
1587     }
1588     m_movieCaptureDialog->show();
1589 }
1590 
1591 void MainWindow::stopRecording()
1592 {
1593     if ( m_movieCaptureDialog ) {
1594         m_movieCaptureDialog->stopRecording();
1595         changeRecordingState();
1596     }
1597 }
1598 
1599 void MainWindow::changeRecordingState()
1600 {
1601     m_recordMovieAction->setEnabled( !m_recordMovieAction->isEnabled() );
1602     m_stopRecordingAction->setEnabled( !m_stopRecordingAction->isEnabled() );
1603 }
1604 
1605 void MainWindow::updateWindowTitle()
1606 {
1607     GeoSceneDocument *theme = m_controlView->marbleModel()->mapTheme();
1608     setWindowTitle(theme ? theme->head()->name() : QString());
1609 }
1610 
1611 void MainWindow::updateCenterFromTheme()
1612 {
1613    //A scene provider may provide only a subset of the globe, use scene properties read from a dgml as a starting point
1614    GeoSceneDocument * theme = m_controlView->marbleModel()->mapTheme();
1615    if (theme) {
1616        const GeoSceneMap* map = theme->map();
1617        if (map) {
1618            const QVariantList coords = map->center();
1619            if (! coords.empty()) {
1620                if (coords.count() == 2) {
1621                    m_controlView->marbleWidget()->centerOn( coords.at(0).toDouble(), coords.at(1).toDouble() );
1622                }
1623                else if (coords.count() == 4) {
1624                    // If the  the map theme provides a bounding box that does not contain
1625                    // the current view then we center on the bounding box of the map theme.
1626                    GeoDataLatLonBox latLonBox(coords.at(0).toDouble(), coords.at(1).toDouble(),
1627                                               coords.at(2).toDouble(), coords.at(3).toDouble(), GeoDataCoordinates::Degree);
1628                    GeoDataLatLonAltBox viewBox = m_controlView->marbleWidget()->viewport()->viewLatLonAltBox();
1629                    if (!latLonBox.contains(viewBox)) {
1630                        m_controlView->marbleWidget()->centerOn( latLonBox );
1631                    }
1632                }
1633                else {
1634                    mDebug() << QString("DGML theme %1 has invalid number of coordinates").arg(theme->head()->name());
1635                }
1636            }
1637       }
1638    }
1639 }
1640 
1641 void MainWindow::showMapWizard()
1642 {
1643     QPointer<MapWizard> mapWizard = new MapWizard();
1644     QSettings settings;
1645 
1646     settings.beginGroup( "MapWizard" );
1647         mapWizard->setWmsServers( settings.value( "wmsServers" ).toStringList() );
1648         mapWizard->setWmtsServers( settings.value( "wmtsServers" ).toStringList() );
1649         mapWizard->setStaticUrlServers( settings.value( "staticUrlServers" ).toStringList() );
1650     settings.endGroup();
1651 
1652     mapWizard->exec();
1653 
1654     settings.beginGroup( "MapWizard" );
1655         settings.setValue( "wmsServers", mapWizard->wmsServers() );
1656         settings.setValue( "wmtsServers", mapWizard->wmtsServers() );
1657         settings.setValue( "staticUrlServers", mapWizard->staticUrlServers() );
1658     settings.endGroup();
1659 
1660     mapWizard->deleteLater();
1661 }
1662 
1663 void MainWindow::showZoomLevel(bool show)
1664 {
1665     if ( show ) {
1666         m_zoomLabel->show();
1667         statusBar()->insertPermanentWidget( 2, m_zoomLabel );
1668     } else {
1669         statusBar()->removeWidget( m_zoomLabel );
1670     }
1671     // update from last modification
1672     m_toggleTileLevelAction->setChecked( show );
1673 }
1674 
1675 void MainWindow::changeAngleDisplayUnit( QAction *action )
1676 {
1677     m_configDialog->setAngleUnit((Marble::AngleUnit)action->data().toInt());
1678 }
1679 
1680 void MainWindow::fallBackToDefaultTheme()
1681 {
1682     m_controlView->marbleWidget()->setMapThemeId( m_controlView->defaultMapThemeId() );
1683 }
1684 
1685 void MainWindow::changeViewSize( QAction* action )
1686 {
1687     if ( action->data().type() == QVariant::Size ) {
1688         if ( m_savedSize.isEmpty() ) {
1689             m_savedSize = m_controlView->size();
1690         }
1691         m_controlView->setFixedSize( action->data().toSize() );
1692         adjustSize();
1693     } else {
1694         m_controlView->setMinimumSize( QSize( 0, 0 ) );
1695         m_controlView->setMaximumSize( QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ) );
1696         m_controlView->resize( m_savedSize );
1697         m_controlView->setMinimumSize( m_savedSize );
1698         adjustSize();
1699         m_controlView->setMinimumSize( QSize( 0, 0 ) );
1700         m_savedSize.setHeight( -1 );
1701     }
1702 }
1703 #include "moc_QtMainWindow.cpp"