diff --git a/src/apps/marble-kde/marble.kcfg b/src/apps/marble-kde/marble.kcfg index 9da3f60aa..f503480e5 100644 --- a/src/apps/marble-kde/marble.kcfg +++ b/src/apps/marble-kde/marble.kcfg @@ -1,334 +1,337 @@ "../../lib/marble/MarbleGlobal.h" "../../lib/marble/MarbleColors.h" QtCore/QDir QtCore/QLocale QFontDatabase 9.4 54.8 1050 0.0 0.0 11564500 true false false false 0 true 1 -100 100 true false true false false 0 false true QDir::homePath() QDir::homePath() false 0 QLocale::MetricSystem Marble::DMSDegree Marble::HighQuality Marble::LowQuality Marble::Native QFontDatabase::systemFont(QFontDatabase::GeneralFont) QDir::homePath() false false false false Marble::KeepAxisVertically Marble::ShowHomeLocation true + + true + false 0 100 0 999999 0 0 999999 8080 0 65535 true Marble::HttpProxy false false true true false true true true 0 Marble::Oxygen::skyBlue4 200 Marble::Oxygen::seaBlue2 200 Marble::Oxygen::aluminumGray4 200 false owncloud true true diff --git a/src/apps/marble-kde/marble_part.cpp b/src/apps/marble-kde/marble_part.cpp index 596f64ce5..20031927a 100644 --- a/src/apps/marble-kde/marble_part.cpp +++ b/src/apps/marble-kde/marble_part.cpp @@ -1,1832 +1,1833 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2007 Tobias Koenig // Copyright 2008 Inge Wallin // Copyright 2009 Jens-Michael Hoffmann // Copyright 2010 Harshit Jain // // Own #include "marble_part.h" // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // KF #include #include #include #include #include #include #include #include #include #include #include #include // Marble library classes #include "AbstractFloatItem.h" #include "EditBookmarkDialog.h" #include "BookmarkManager.h" #include "BookmarkManagerDialog.h" #include "CurrentLocationWidget.h" #include "DownloadRegionDialog.h" #include "GeoDataCoordinates.h" #include "GeoDataFolder.h" #include "GeoDataLatLonAltBox.h" #include "GeoDataLookAt.h" #include "GeoDataPlacemark.h" #include "HttpDownloadManager.h" #include "MarbleDirs.h" #include "MarbleDebug.h" #include "MarbleLocale.h" #include "MarbleModel.h" #include "MarblePluginSettingsWidget.h" #include "MapWizard.h" #include "NewBookmarkFolderDialog.h" #include "RenderPluginModel.h" #include "routing/RoutingManager.h" #include "routing/RoutingProfilesModel.h" #include "routing/RoutingProfilesWidget.h" #include "routing/RouteRequest.h" #include "SunControlWidget.h" #include "TimeControlWidget.h" #include "TileCoordsPyramid.h" #include "ViewportParams.h" #include "MarbleClock.h" #include "ParseRunnerPlugin.h" #include "PositionTracking.h" #include "PositionProviderPlugin.h" #include "PluginManager.h" #include "SearchInputWidget.h" #include "MarbleWidgetInputHandler.h" #include "Planet.h" #include "MapThemeDownloadDialog.h" #include "cloudsync/BookmarkSyncManager.h" #include "MovieCaptureDialog.h" #include "cloudsync/RouteSyncManager.h" #include "cloudsync/CloudSyncManager.h" // Marble non-library classes #include "ControlView.h" #include "settings.h" using namespace Marble; #include "ui_MarbleCacheSettingsWidget.h" #include "ui_MarbleViewSettingsWidget.h" #include "ui_MarbleNavigationSettingsWidget.h" #include "ui_MarbleTimeSettingsWidget.h" namespace Marble { namespace { const char POSITION_STRING[] = I18N_NOOP( "Position: %1" ); const char DISTANCE_STRING[] = I18N_NOOP( "Altitude: %1" ); const char TILEZOOMLEVEL_STRING[] = I18N_NOOP( "Tile Zoom Level: %1" ); const char DATETIME_STRING[] = I18N_NOOP( "Time: %1" ); } K_PLUGIN_FACTORY(MarblePartFactory, registerPlugin();) K_EXPORT_PLUGIN(MarblePartFactory("marble")) MarblePart::MarblePart( QWidget *parentWidget, QObject *parent, const QVariantList &arguments ) : KParts::ReadOnlyPart( parent ), m_sunControlDialog( nullptr ), m_timeControlDialog( nullptr ), m_downloadRegionDialog( nullptr ), m_movieCaptureDialog( nullptr ), m_externalMapEditorAction( nullptr ), m_recordMovieAction( nullptr ), m_stopRecordingAction( nullptr ), m_recentFilesAction( nullptr ), m_configDialog( nullptr ), m_position( QCoreApplication::translate( "Marble", NOT_AVAILABLE ) ), m_tileZoomLevel( QCoreApplication::translate( "Marble", NOT_AVAILABLE ) ), m_positionLabel( nullptr ), m_distanceLabel( nullptr ) { // only set marble data path when a path was given if ( arguments.count() != 0 && !arguments.first().toString().isEmpty() ) MarbleDirs::setMarbleDataPath( arguments.first().toString() ); // Setting measure system to provide nice standards for all unit questions. // This has to happen before any initialization so plugins (for example) can // use it during initialization. MarbleLocale *marbleLocale = MarbleGlobal::getInstance()->locale(); // KF5 TODO: Read Connecting Calls to Catalogs" in ki18n programmer's guide // and enable translations // KLocale *kLocale = KGlobal::locale(); // if ( kLocale->measureSystem() == KLocale::Metric ) { // marbleLocale->setMeasurementSystem( QLocale::MetricSystem ); // } // else { // marbleLocale->setMeasurementSystem( QLocale::ImperialSystem ); // } marbleLocale->setMeasurementSystem( MarbleLocale::ImperialSystem ); migrateNewstuffConfigFiles(); m_externalEditorMapping[0] = ""; m_externalEditorMapping[1] = "potlatch"; m_externalEditorMapping[2] = "josm"; m_externalEditorMapping[3] = "merkaartor"; m_controlView = new ControlView( parentWidget ); setWidget( m_controlView ); setupActions(); setXMLFile( "marble_part.rc" ); m_statusBarExtension = new KParts::StatusBarExtension( this ); m_statusBarExtension->statusBar()->setUpdatesEnabled( false ); // Load bookmark file. If it does not exist, a default one will be used. m_controlView->marbleModel()->bookmarkManager()->loadFile( "bookmarks/bookmarks.kml" ); initializeCustomTimezone(); setupStatusBar(); readSettings(); m_statusBarExtension->statusBar()->setUpdatesEnabled( true ); // Show startup location switch ( MarbleSettings::onStartup() ) { case LastLocationVisited: { GeoDataLookAt target; target.setLongitude( MarbleSettings::quitLongitude() ); target.setLatitude( MarbleSettings::quitLatitude() ); target.setRange( MarbleSettings::quitRange() ); m_controlView->marbleWidget()->flyTo( target, Instant ); } break; case ShowHomeLocation: m_controlView->marbleWidget()->goHome( Instant ); break; } connect( m_controlView, SIGNAL(showUploadDialog()), this, SLOT(showUploadNewStuffDialog()) ); connect( m_controlView, SIGNAL(showMapWizard()), this, SLOT(showMapWizard()) ); connect( m_controlView, SIGNAL(mapThemeDeleted()), this, SLOT(fallBackToDefaultTheme()) ); } MarblePart::~MarblePart() { writeSettings(); // Check whether this delete is really needed. delete m_configDialog; } ControlView* MarblePart::controlView() const { return m_controlView; } KAboutData *MarblePart::createAboutData() { return new KAboutData( QString( I18N_NOOP( "marble_part" ) ), QString( "Marble" ), ControlView::applicationVersion(), i18n( "A Virtual Globe" ), KAboutLicense::LGPL_V2 ); } bool MarblePart::openUrl( const QUrl &url ) { QFileInfo fileInfo( url.toLocalFile() ); if ( fileInfo.isReadable() ) { m_controlView->marbleModel()->addGeoDataFile( url.toLocalFile() ); m_recentFilesAction->addUrl( url ); return true; } KMessageBox::error( widget(), i18n( "Sorry, unable to open '%1'. The file is not accessible.", fileInfo.fileName() ), i18n( "File not accessible" ) ); return false; } bool MarblePart::openFile() { const PluginManager *const pluginManager = m_controlView->marbleModel()->pluginManager(); QStringList allFileExtensions; QStringList filters; for ( const ParseRunnerPlugin *plugin: pluginManager->parsingRunnerPlugins() ) { if (plugin->nameId() == QLatin1String("Cache")) continue; const QStringList fileExtensions = plugin->fileExtensions().replaceInStrings( QRegExp( "^" ), "*." ); const QString filter = plugin->fileFormatDescription() + QLatin1String(" (") + fileExtensions.join(QLatin1Char(' ')) + QLatin1Char(')'); filters << filter; allFileExtensions << fileExtensions; } allFileExtensions.sort(); // sort since file extensions are visible under Windows const QString allFileTypes = i18n("All Supported Files") + QLatin1String(" (") + allFileExtensions.join(QLatin1Char(' ')) + QLatin1Char(')'); filters.sort(); filters.prepend( allFileTypes ); const QString filter = filters.join( ";;" ); QStringList fileNames = QFileDialog::getOpenFileNames( widget(), i18n("Open File"), m_lastFileOpenPath, filter ); if ( !fileNames.isEmpty() ) { const QString firstFile = fileNames.first(); m_lastFileOpenPath = QFileInfo( firstFile ).absolutePath(); } for( const QString &fileName: fileNames ) { openUrl( QUrl::fromLocalFile(fileName) ); } return true; } void MarblePart::exportMapScreenShot() { QString fileName = QFileDialog::getSaveFileName( widget(), i18n("Export Map"), QDir::homePath(), i18n( "Images *.jpg *.png" ) ); if ( !fileName.isEmpty() ) { // Take the case into account where no file format is indicated const char * format = nullptr; if ( !fileName.endsWith(QLatin1String( "png" ), Qt::CaseInsensitive) && !fileName.endsWith(QLatin1String( "jpg" ), Qt::CaseInsensitive) ) { format = "JPG"; } QPixmap mapPixmap = m_controlView->mapScreenShot(); bool success = mapPixmap.save( fileName, format ); if ( !success ) { KMessageBox::error( widget(), i18nc( "Application name", "Marble" ), i18n( "An error occurred while trying to save the file.\n" ), KMessageBox::Notify ); } } } void MarblePart::setShowBookmarks( bool show ) { m_controlView->marbleModel()->bookmarkManager()->setShowBookmarks( show ); m_toggleBookmarkDisplayAction->setChecked( show ); // Sync state with the GUI } void MarblePart::setShowClouds( bool isChecked ) { m_controlView->marbleWidget()->setShowClouds( isChecked ); m_showCloudsAction->setChecked( isChecked ); // Sync state with the GUI } void MarblePart::showPositionLabel( bool isChecked ) { m_positionLabel->setVisible( isChecked ); } void MarblePart::showAltitudeLabel( bool isChecked ) { m_distanceLabel->setVisible( isChecked ); } void MarblePart::showTileZoomLevelLabel( bool isChecked ) { m_tileZoomLevelLabel->setVisible( isChecked ); } void MarblePart::showDateTimeLabel( bool isChecked ) { m_clockLabel->setVisible( isChecked ); } void MarblePart::showDownloadProgressBar( bool isChecked ) { MarbleSettings::setShowDownloadProgressBar( isChecked ); // Change visibility only if there is a download happening m_downloadProgressBar->setVisible( isChecked && m_downloadProgressBar->value() >= 0 ); } void MarblePart::showFullScreen( bool isChecked ) { if ( QApplication::activeWindow() ) KToggleFullScreenAction::setFullScreen( QApplication::activeWindow(), isChecked ); m_fullScreenAct->setChecked( isChecked ); // Sync state with the GUI } void MarblePart::showStatusBar( bool isChecked ) { if ( !m_statusBarExtension->statusBar() ) return; m_statusBarExtension->statusBar()->setVisible( isChecked ); } void MarblePart::controlSun() { if ( !m_sunControlDialog ) { m_sunControlDialog = new SunControlWidget( m_controlView->marbleWidget(), m_controlView ); connect( m_sunControlDialog, SIGNAL(showSun(bool)), this, SLOT (showSun(bool)) ); connect( m_sunControlDialog, SIGNAL(showSun(bool)), m_showShadow, SLOT (setChecked(bool)) ); connect( m_sunControlDialog, SIGNAL(isLockedToSubSolarPoint(bool)), m_lockToSubSolarPoint, SLOT (setChecked(bool)) ); connect( m_sunControlDialog, SIGNAL(isSubSolarPointIconVisible(bool)), m_setSubSolarPointIconVisible, SLOT (setChecked(bool)) ); } m_sunControlDialog->show(); m_sunControlDialog->raise(); m_sunControlDialog->activateWindow(); } void MarblePart::controlTime() { if ( !m_timeControlDialog ) { m_timeControlDialog = new TimeControlWidget( m_controlView->marbleModel()->clock() ); } m_timeControlDialog->show(); m_timeControlDialog->raise(); m_timeControlDialog->activateWindow(); } void MarblePart::showSun( bool active ) { m_controlView->marbleWidget()->setShowSunShading( active ); m_sunControlDialog->setSunShading( active ); } void MarblePart::lockToSubSolarPoint( bool lock ) { m_controlView->marbleWidget()->setLockToSubSolarPoint( lock ); } void MarblePart::setSubSolarPointIconVisible( bool show ) { m_controlView->marbleWidget()->setSubSolarPointIconVisible( show ); } void MarblePart::workOffline( bool offline ) { m_controlView->setWorkOffline( offline ); m_newStuffAction->setEnabled( !offline ); m_downloadRegionAction->setEnabled( !offline ); } void MarblePart::copyMap() { QPixmap mapPixmap = m_controlView->mapScreenShot(); QClipboard *clipboard = QApplication::clipboard(); clipboard->setPixmap( mapPixmap ); } void MarblePart::copyCoordinates() { qreal lon = m_controlView->marbleWidget()->centerLongitude(); qreal lat = m_controlView->marbleWidget()->centerLatitude(); QString positionString = GeoDataCoordinates( lon, lat, 0.0, GeoDataCoordinates::Degree ).toString(); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText( positionString ); } void MarblePart::readSettings() { qDebug() << "Start: MarblePart::readSettings()"; // Set home position m_controlView->marbleModel()->setHome( MarbleSettings::homeLongitude(), MarbleSettings::homeLatitude(), MarbleSettings::homeZoom() ); // Map theme and projection QString mapTheme = MarbleSettings::mapTheme(); if ( mapTheme.isEmpty() ) { mapTheme = m_controlView->defaultMapThemeId(); } m_controlView->marbleWidget()->setMapThemeId( mapTheme ); m_controlView->marbleWidget()->setProjection( (Projection) MarbleSettings::projection() ); m_controlView->marbleWidget()->setShowClouds( MarbleSettings::showClouds() ); m_showCloudsAction->setChecked( MarbleSettings::showClouds() ); workOffline( MarbleSettings::workOffline() ); m_workOfflineAction->setChecked( MarbleSettings::workOffline() ); m_lockFloatItemsAct->setChecked(MarbleSettings::lockFloatItemPositions()); lockFloatItemPosition(MarbleSettings::lockFloatItemPositions()); setShowBookmarks( MarbleSettings::showBookmarks() ); // Sun m_controlView->marbleWidget()->setShowSunShading( MarbleSettings::showSun() ); m_showShadow->setChecked( MarbleSettings::showSun() ); m_controlView->marbleWidget()->setShowCityLights( MarbleSettings::showCitylights() ); m_controlView->marbleWidget()->setSubSolarPointIconVisible( MarbleSettings::subSolarPointIconVisible() ); m_controlView->marbleWidget()->setLockToSubSolarPoint( MarbleSettings::lockToSubSolarPoint() ); m_setSubSolarPointIconVisible->setChecked( MarbleSettings::subSolarPointIconVisible() ); m_lockToSubSolarPoint->setChecked( MarbleSettings::lockToSubSolarPoint() ); // View m_lastFileOpenPath = MarbleSettings::lastFileOpenDir(); // Tracking settings readTrackingSettings(); // Load previous route settings m_controlView->marbleModel()->routingManager()->readSettings(); bool const startupWarning = MarbleSettings::showGuidanceModeStartupWarning(); m_controlView->marbleModel()->routingManager()->setShowGuidanceModeStartupWarning( startupWarning ); KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); if ( sharedConfig->hasGroup( "Routing Profiles" ) ) { QList profiles; KConfigGroup profilesGroup = sharedConfig->group( "Routing Profiles" ); int numProfiles = profilesGroup.readEntry( "Num", 0 ); for ( int i = 0; i < numProfiles; ++i ) { KConfigGroup profileGroup = profilesGroup.group( QString( "Profile %0" ).arg(i) ); QString name = profileGroup.readEntry( "Name", i18n( "Unnamed" ) ); RoutingProfile profile( name ); for ( const QString& pluginName: profileGroup.groupList() ) { KConfigGroup pluginGroup = profileGroup.group( pluginName ); profile.pluginSettings().insert( pluginName, QHash() ); for ( const QString& key: pluginGroup.keyList() ) { if (key != QLatin1String("Enabled")) { profile.pluginSettings()[ pluginName ].insert( key, pluginGroup.readEntry( key ) ); } } } profiles << profile; } m_controlView->marbleModel()->routingManager()->profilesModel()->setProfiles( profiles ); } else { m_controlView->marbleModel()->routingManager()->profilesModel()->loadDefaultProfiles(); } int const profileIndex = MarbleSettings::currentRoutingProfile(); if ( profileIndex >= 0 && profileIndex < m_controlView->marbleModel()->routingManager()->profilesModel()->rowCount() ) { RoutingProfile profile = m_controlView->marbleModel()->routingManager()->profilesModel()->profiles().at( profileIndex ); m_controlView->marbleModel()->routingManager()->routeRequest()->setRoutingProfile( profile ); } PositionTracking *const tracking = m_controlView->marbleModel()->positionTracking(); tracking->readSettings(); QString positionProvider = MarbleSettings::activePositionTrackingPlugin(); if ( !positionProvider.isEmpty() ) { const PluginManager* pluginManager = m_controlView->marbleModel()->pluginManager(); for( const PositionProviderPlugin* plugin: pluginManager->positionProviderPlugins() ) { if ( plugin->nameId() == positionProvider ) { PositionProviderPlugin* instance = plugin->newInstance(); tracking->setPositionProviderPlugin( instance ); break; } } } readStatusBarSettings(); updateSettings(); // Time if( MarbleSettings::systemTime() == true ) { /* nothing to do */ } else if( MarbleSettings::lastSessionTime() == true ) { m_controlView->marbleModel()->setClockDateTime( MarbleSettings::dateTime() ); m_controlView->marbleModel()->setClockSpeed( MarbleSettings::speedSlider() ); } readPluginSettings(); m_controlView->setExternalMapEditor( m_externalEditorMapping[MarbleSettings::externalMapEditor()] ); CloudSyncManager* cloudSyncManager = m_controlView->cloudSyncManager(); cloudSyncManager->setOwncloudCredentials( MarbleSettings::owncloudServer(), MarbleSettings::owncloudUsername(), MarbleSettings::owncloudPassword()); cloudSyncManager->setSyncEnabled( MarbleSettings::enableSync() ); cloudSyncManager->routeSyncManager()->setRouteSyncEnabled( MarbleSettings::syncRoutes() ); cloudSyncManager->bookmarkSyncManager()->setBookmarkSyncEnabled( MarbleSettings::syncBookmarks() ); } void MarblePart::readTrackingSettings() { if( MarbleSettings::autoCenter() || MarbleSettings::recenterMode() ) { CurrentLocationWidget *trackingWidget = m_controlView->currentLocationWidget(); if( trackingWidget ) { trackingWidget->setRecenterMode( MarbleSettings::recenterMode() ); trackingWidget->setAutoZoom( MarbleSettings::autoZoom() ); trackingWidget->setTrackVisible( MarbleSettings::trackVisible() ); trackingWidget->setLastOpenPath( MarbleSettings::lastTrackOpenPath() ); trackingWidget->setLastSavePath( MarbleSettings::lastTrackSavePath() ); } } } void MarblePart::readStatusBarSettings() { const bool showPos = MarbleSettings::showPositionLabel(); m_showPositionAction->setChecked( showPos ); showPositionLabel( showPos ); const bool showAlt = MarbleSettings::showAltitudeLabel(); m_showAltitudeAction->setChecked( showAlt ); showAltitudeLabel( showAlt ); const bool showTileZoom = MarbleSettings::showTileZoomLevelLabel(); m_showTileZoomLevelAction->setChecked( showTileZoom ); showTileZoomLevelLabel( showTileZoom ); const bool showDateTime = MarbleSettings::showDateTimeLabel(); m_showDateTimeAction->setChecked( showDateTime ); showDateTimeLabel( showDateTime ); const bool showProgress = MarbleSettings::showDownloadProgressBar(); m_showDownloadProgressAction->setChecked( showProgress ); showDownloadProgressBar( showProgress ); } void MarblePart::writeSettings() { // Get the 'quit' values from the widget and store them in the settings. qreal quitLon = m_controlView->marbleWidget()->lookAt().longitude(); qreal quitLat = m_controlView->marbleWidget()->lookAt().latitude(); qreal quitRange = m_controlView->marbleWidget()->lookAt().range(); MarbleSettings::setQuitLongitude( quitLon ); MarbleSettings::setQuitLatitude( quitLat ); MarbleSettings::setQuitRange( quitRange ); // Get the 'home' values from the widget and store them in the settings. qreal homeLon = 0; qreal homeLat = 0; int homeZoom = 0; m_controlView->marbleModel()->home( homeLon, homeLat, homeZoom ); MarbleSettings::setHomeLongitude( homeLon ); MarbleSettings::setHomeLatitude( homeLat ); MarbleSettings::setHomeZoom( homeZoom ); // Set default font MarbleSettings::setMapFont( m_controlView->marbleWidget()->defaultFont() ); // Get whether animations to the target are enabled MarbleSettings::setAnimateTargetVoyage( m_controlView->marbleWidget()->animationsEnabled() ); // Map theme and projection MarbleSettings::setMapTheme( m_controlView->marbleWidget()->mapThemeId() ); MarbleSettings::setProjection( m_controlView->marbleWidget()->projection() ); MarbleSettings::setShowClouds( m_controlView->marbleWidget()->showClouds() ); MarbleSettings::setWorkOffline( m_workOfflineAction->isChecked() ); MarbleSettings::setStillQuality( m_controlView->marbleWidget()->mapQuality( Still ) ); MarbleSettings::setAnimationQuality( m_controlView->marbleWidget()-> mapQuality( Animation ) ); MarbleSettings::setShowBookmarks( m_controlView->marbleModel()->bookmarkManager()->showBookmarks() ); MarbleSettings::setLastFileOpenDir( m_lastFileOpenPath ); MarbleSettings::setDistanceUnit( MarbleGlobal::getInstance()->locale()->measurementSystem() ); MarbleSettings::setAngleUnit( m_controlView->marbleWidget()->defaultAngleUnit() ); // Sun MarbleSettings::setShowSun( m_controlView->marbleWidget()->showSunShading() ); MarbleSettings::setShowCitylights( m_controlView->marbleWidget()->showCityLights() ); MarbleSettings::setLockToSubSolarPoint( m_controlView->marbleWidget()->isLockedToSubSolarPoint() ); MarbleSettings::setSubSolarPointIconVisible( m_controlView->marbleWidget()->isSubSolarPointIconVisible() ); // Tracking CurrentLocationWidget *trackingWidget = m_controlView->currentLocationWidget(); if( trackingWidget ) { MarbleSettings::setRecenterMode( trackingWidget->recenterMode() ); MarbleSettings::setAutoZoom( trackingWidget->autoZoom() ); MarbleSettings::setTrackVisible( trackingWidget->trackVisible() ); MarbleSettings::setLastTrackOpenPath( trackingWidget->lastOpenPath() ); MarbleSettings::setLastTrackSavePath( trackingWidget->lastSavePath() ); } // Caches MarbleSettings::setVolatileTileCacheLimit( m_controlView->marbleWidget()-> volatileTileCacheLimit() / 1024 ); MarbleSettings::setPersistentTileCacheLimit( m_controlView->marbleModel()-> persistentTileCacheLimit() / 1024 ); // Time MarbleSettings::setDateTime( m_controlView->marbleModel()->clockDateTime() ); MarbleSettings::setSpeedSlider( m_controlView->marbleModel()->clockSpeed() ); // Plugins writePluginSettings(); QString positionProvider; PositionTracking* tracking = m_controlView->marbleModel()->positionTracking(); tracking->writeSettings(); if ( tracking->positionProviderPlugin() ) { positionProvider = tracking->positionProviderPlugin()->nameId(); } MarbleSettings::setActivePositionTrackingPlugin( positionProvider ); MarbleSettings::setLockFloatItemPositions( m_lockFloatItemsAct->isChecked() ); writeStatusBarSettings(); // Store recent files KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); m_recentFilesAction->saveEntries( sharedConfig->group( "RecentFiles" ) ); // Store current route settings RoutingManager *routingManager = m_controlView->marbleWidget()->model()->routingManager(); routingManager->writeSettings(); bool const startupWarning = routingManager->showGuidanceModeStartupWarning(); MarbleSettings::setShowGuidanceModeStartupWarning( startupWarning ); QList profiles = routingManager->profilesModel()->profiles(); RoutingProfile const profile = routingManager->routeRequest()->routingProfile(); MarbleSettings::setCurrentRoutingProfile( profiles.indexOf( profile ) ); QList const editors = m_externalEditorMapping.values(); MarbleSettings::setExternalMapEditor( editors.indexOf( m_controlView->externalMapEditor() ) ); applyPluginState(); MarbleSettings::self()->save(); } void MarblePart::writeStatusBarSettings() { MarbleSettings::setShowPositionLabel( m_showPositionAction->isChecked() ); MarbleSettings::setShowAltitudeLabel( m_showAltitudeAction->isChecked() ); MarbleSettings::setShowTileZoomLevelLabel( m_showTileZoomLevelAction->isChecked() ); MarbleSettings::setShowDateTimeLabel( m_showDateTimeAction->isChecked() ); MarbleSettings::setShowDownloadProgressBar( m_showDownloadProgressAction->isChecked() ); } void MarblePart::setupActions() { // Action: Recent Files m_recentFilesAction = KStandardAction::openRecent( this, SLOT(openUrl(QUrl)), actionCollection() ); KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); m_recentFilesAction->loadEntries( sharedConfig->group( "RecentFiles" ) ); // Action: Download Region m_downloadRegionAction = new QAction( this ); m_downloadRegionAction->setText( i18nc( "Action for downloading an entire region of a map", "Download Region..." )); actionCollection()->addAction( "file_download_region", m_downloadRegionAction ); connect( m_downloadRegionAction, SIGNAL(triggered()), SLOT(showDownloadRegionDialog())); // Action: Print Map m_printMapAction = KStandardAction::print( this, SLOT(printMapScreenShot()), actionCollection() ); m_printPreviewAction = KStandardAction::printPreview( m_controlView, SLOT(printPreview()), actionCollection() ); // Action: Export Map m_exportMapAction = new QAction( this ); actionCollection()->addAction( "exportMap", m_exportMapAction ); m_exportMapAction->setText( i18nc( "Action for saving the map to a file", "&Export Map..." ) ); m_exportMapAction->setIcon( QIcon::fromTheme( "document-save-as" ) ); actionCollection()->setDefaultShortcut( m_exportMapAction, Qt::CTRL + Qt::Key_S ); connect( m_exportMapAction, SIGNAL(triggered(bool)), this, SLOT(exportMapScreenShot()) ); // Action: Work Offline m_workOfflineAction = new QAction( this ); actionCollection()->addAction( "workOffline", m_workOfflineAction ); m_workOfflineAction->setText( i18nc( "Action for toggling offline mode", "&Work Offline" ) ); m_workOfflineAction->setIcon( QIcon::fromTheme( "user-offline" ) ); m_workOfflineAction->setCheckable( true ); m_workOfflineAction->setChecked( false ); connect( m_workOfflineAction, SIGNAL(triggered(bool)), this, SLOT(workOffline(bool)) ); // Action: Copy Map to the Clipboard m_copyMapAction = KStandardAction::copy( this, SLOT(copyMap()), actionCollection() ); m_copyMapAction->setText( i18nc( "Action for copying the map to the clipboard", "&Copy Map" ) ); // Action: Copy Coordinates string m_copyCoordinatesAction = new QAction( this ); actionCollection()->addAction( "edit_copy_coordinates", m_copyCoordinatesAction ); m_copyCoordinatesAction->setText( i18nc( "Action for copying the coordinates to the clipboard", "C&opy Coordinates" ) ); m_copyCoordinatesAction->setIcon(QIcon(QStringLiteral(":/icons/copy-coordinates.png"))); connect( m_copyCoordinatesAction, SIGNAL(triggered(bool)), this, SLOT(copyCoordinates()) ); // Action: Open a Gpx or a Kml File m_openAct = KStandardAction::open( this, SLOT(openFile()), actionCollection() ); m_openAct->setText( i18nc( "Action for opening a file", "&Open..." ) ); // Standard actions. So far only Quit. KStandardAction::quit( qApp, SLOT(closeAllWindows()), actionCollection() ); // Action: Get hot new stuff m_newStuffAction = KNS3::standardAction( i18nc( "Action for downloading maps (GHNS)", "Download Maps..."), this, SLOT(showNewStuffDialog()), actionCollection(), "new_stuff" ); m_newStuffAction->setStatusTip( i18nc( "Status tip", "Download new maps")); actionCollection()->setDefaultShortcut( m_newStuffAction, Qt::CTRL + Qt::Key_N ); // Action: Create a New Map m_mapWizardAct = new QAction( i18nc( "Action for creating new maps", "&Create a New Map..." ), this ); m_mapWizardAct->setIcon(QIcon(QStringLiteral(":/icons/create-new-map.png"))); actionCollection()->addAction( "createMap", m_mapWizardAct ); m_mapWizardAct->setStatusTip( i18nc( "Status tip", "A wizard guides you through the creation of your own map theme." ) ); connect( m_mapWizardAct, SIGNAL(triggered()), SLOT(showMapWizard()) ); KStandardAction::showStatusbar( this, SLOT(showStatusBar(bool)), actionCollection() ); m_fullScreenAct = KStandardAction::fullScreen( nullptr, nullptr, widget(), actionCollection() ); connect( m_fullScreenAct, SIGNAL(triggered(bool)), this, SLOT(showFullScreen(bool)) ); // Action: Show Crosshairs option QList pluginList = m_controlView->marbleWidget()->renderPlugins(); QList::const_iterator i = pluginList.constBegin(); QList::const_iterator const end = pluginList.constEnd(); for (; i != end; ++i ) { if ((*i)->nameId() == QLatin1String("crosshairs")) { actionCollection()->addAction( "show_crosshairs", (*i)->action() ); } } // Action: Show Clouds option m_showCloudsAction = new QAction( this ); actionCollection()->addAction( "show_clouds", m_showCloudsAction ); m_showCloudsAction->setCheckable( true ); m_showCloudsAction->setChecked( true ); m_showCloudsAction->setIcon(QIcon(QStringLiteral(":/icons/clouds.png"))); m_showCloudsAction->setText( i18nc( "Action for toggling clouds", "&Clouds" ) ); connect( m_showCloudsAction, SIGNAL(triggered(bool)), this, SLOT(setShowClouds(bool)) ); // Action: Show Sunshade options m_controlSunAction = new QAction( this ); actionCollection()->addAction( "control_sun", m_controlSunAction ); m_controlSunAction->setText( i18nc( "Action for sun control dialog", "S&un Control..." ) ); connect( m_controlSunAction, SIGNAL(triggered(bool)), this, SLOT(controlSun()) ); KStandardAction::redisplay( m_controlView->marbleWidget(), SLOT(reloadMap()), actionCollection() ); // Action: Show Time options m_controlTimeAction = new QAction( this ); actionCollection()->addAction( "control_time", m_controlTimeAction ); m_controlTimeAction->setIcon(QIcon(QStringLiteral(":/icons/clock.png"))); m_controlTimeAction->setText( i18nc( "Action for time control dialog", "&Time Control..." ) ); connect( m_controlTimeAction, SIGNAL(triggered(bool)), this, SLOT(controlTime()) ); // Action: Lock float items m_lockFloatItemsAct = new QAction ( this ); actionCollection()->addAction( "options_lock_floatitems", m_lockFloatItemsAct ); m_lockFloatItemsAct->setText( i18nc( "Action for locking float items on the map", "Lock Position" ) ); m_lockFloatItemsAct->setIcon(QIcon(QStringLiteral(":/icons/unlock.png"))); m_lockFloatItemsAct->setCheckable( true ); m_lockFloatItemsAct->setChecked( false ); connect( m_lockFloatItemsAct, SIGNAL(triggered(bool)), this, SLOT(lockFloatItemPosition(bool)) ); KStandardAction::preferences( this, SLOT(editSettings()), actionCollection() ); //Toggle Action: Show sun shadow m_showShadow = new KToggleAction( i18n( "Show Shadow" ), this ); // m_showShadow->setIcon(QIcon(QStringLiteral(""))); // Fixme: Add Icon actionCollection()->addAction( "sun_shadow", m_showShadow ); m_showShadow->setCheckedState( KGuiItem( i18n( "Hide Shadow" ) ) ); m_showShadow->setToolTip(i18n("Shows and hides the shadow of the sun")); connect( m_showShadow, SIGNAL(triggered(bool)), this, SLOT(showSun(bool))); //Toggle Action: Show Sun icon on the Sub-Solar Point m_setSubSolarPointIconVisible = new KToggleAction( i18n( "Show sun icon on the Sub-Solar Point" ), this ); actionCollection()->addAction( "show_icon_on_subsolarpoint", m_setSubSolarPointIconVisible ); m_setSubSolarPointIconVisible->setCheckedState( KGuiItem( i18n( "Hide sun icon on the Sub-Solar Point" ) ) ); m_setSubSolarPointIconVisible->setToolTip( i18n( "Show sun icon on the sub-solar point" ) ); connect( m_setSubSolarPointIconVisible, SIGNAL(triggered(bool)), this, SLOT(setSubSolarPointIconVisible(bool))); //Toggle Action: Lock globe to the Sub-Solar Point m_lockToSubSolarPoint = new KToggleAction( i18n( "Lock Globe to the Sub-Solar Point" ), this ); actionCollection()->addAction( "lock_to_subsolarpoint", m_lockToSubSolarPoint ); m_lockToSubSolarPoint->setCheckedState( KGuiItem( i18n( "Unlock Globe to the Sub-Solar Point" ) ) ); m_lockToSubSolarPoint->setToolTip( i18n( "Lock globe to the sub-solar point" ) ); connect( m_lockToSubSolarPoint, SIGNAL(triggered(bool)), this, SLOT(lockToSubSolarPoint(bool))); // FIXME: Discuss if this is the best place to put this QList::const_iterator it = pluginList.constBegin(); QList::const_iterator const itEnd = pluginList.constEnd(); for (; it != itEnd; ++it ) { if ((*it)->nameId() != QLatin1String("annotation")) { connect( (*it), SIGNAL(actionGroupsChanged()), this, SLOT(createPluginMenus()) ); } } m_addBookmarkAction = new QAction( this ); actionCollection()->addAction( "add_bookmark", m_addBookmarkAction ); m_addBookmarkAction->setText( i18nc( "Add Bookmark", "&Add Bookmark" ) ); m_addBookmarkAction->setIcon(QIcon(QStringLiteral(":/icons/bookmark-new.png"))); actionCollection()->setDefaultShortcut( m_addBookmarkAction, Qt::CTRL + Qt::Key_B ); connect( m_addBookmarkAction, SIGNAL(triggered()), this, SLOT(openEditBookmarkDialog()) ); m_toggleBookmarkDisplayAction = new QAction( this ); actionCollection()->addAction( "show_bookmarks", m_toggleBookmarkDisplayAction ); m_toggleBookmarkDisplayAction->setText( i18nc( "Show Bookmarks", "Show &Bookmarks" ) ); m_toggleBookmarkDisplayAction->setStatusTip( i18n( "Show or hide bookmarks in the map" ) ); m_toggleBookmarkDisplayAction->setCheckable( true ); m_toggleBookmarkDisplayAction->setChecked( m_controlView->marbleModel()->bookmarkManager()->showBookmarks() ); connect( m_toggleBookmarkDisplayAction, SIGNAL(toggled(bool)), m_controlView->marbleModel()->bookmarkManager(), SLOT(setShowBookmarks(bool)) ); m_setHomeAction = new QAction( this ); actionCollection()->addAction( "set_home", m_setHomeAction ); m_setHomeAction->setText( i18n( "&Set Home Location" ) ); m_setHomeAction->setIcon( QIcon::fromTheme( "go-home" ) ); connect( m_setHomeAction, SIGNAL(triggered()), this, SLOT(setHome()) ); m_manageBookmarksAction = new QAction( this ); actionCollection()->addAction( "manage_bookmarks", m_manageBookmarksAction ); m_manageBookmarksAction->setText( i18nc( "Manage Bookmarks", "&Manage Bookmarks" ) ); m_manageBookmarksAction->setIcon(QIcon(QStringLiteral(":/icons/bookmarks-organize.png"))); connect( m_manageBookmarksAction, SIGNAL(triggered()), this, SLOT(openManageBookmarksDialog()) ); createFolderList(); connect( m_controlView->marbleModel()->bookmarkManager(), SIGNAL(bookmarksChanged()), this, SLOT(createFolderList()) ); m_externalMapEditorAction = new QAction( this ); actionCollection()->addAction( "external_editor", m_externalMapEditorAction ); m_externalMapEditorAction->setText( i18nc( "Edit the map in an external application", "&Edit Map" ) ); m_externalMapEditorAction->setIcon(QIcon(QStringLiteral(":/icons/edit-map.png"))); actionCollection()->setDefaultShortcut( m_externalMapEditorAction, Qt::CTRL + Qt::Key_E ); connect( m_externalMapEditorAction, SIGNAL(triggered()), m_controlView, SLOT(launchExternalMapEditor()) ); connect( m_controlView->marbleWidget(), SIGNAL(themeChanged(QString)), this, SLOT(updateMapEditButtonVisibility(QString)) ); m_recordMovieAction = new QAction( i18n( "&Record Movie" ), this ); actionCollection()->addAction( "record_movie" , m_recordMovieAction ); m_recordMovieAction->setStatusTip( i18n( "Records a movie of the globe" ) ); actionCollection()->setDefaultShortcut( m_recordMovieAction, Qt::CTRL + Qt::SHIFT + Qt::Key_R ); m_recordMovieAction->setIcon(QIcon(QStringLiteral(":/icons/animator.png"))); connect( m_recordMovieAction, SIGNAL(triggered()), this, SLOT(showMovieCaptureDialog()) ); m_stopRecordingAction = new QAction( i18n( "&Stop recording" ), this ); actionCollection()->addAction( "stop_recording" , m_stopRecordingAction ); m_stopRecordingAction->setStatusTip( i18n( "Stop recording a movie of the globe" ) ); actionCollection()->setDefaultShortcut( m_recordMovieAction, Qt::CTRL + Qt::SHIFT + Qt::Key_S ); m_stopRecordingAction->setEnabled( false ); connect( m_stopRecordingAction, SIGNAL(triggered()), this, SLOT(stopRecording()) ); } void MarblePart::createFolderList() { QList actionList; QVector folders = m_controlView->marbleModel()->bookmarkManager()->folders(); QVector::const_iterator i = folders.constBegin(); QVector::const_iterator end = folders.constEnd(); for (; i != end; ++i ) { QMenu *m_bookmarksListMenu = new QMenu( (*i)->name() ); createBookmarksListMenu( m_bookmarksListMenu, *(*i) ); connect( m_bookmarksListMenu, SIGNAL(triggered(QAction*)), this, SLOT(lookAtBookmark(QAction*)) ); actionList.append( m_bookmarksListMenu->menuAction() ); } unplugActionList("folders"); plugActionList( "folders", actionList ); } void MarblePart::createBookmarksListMenu( QMenu *m_bookmarksListMenu, const GeoDataFolder &folder ) { m_bookmarksListMenu->clear(); QVector bookmarks = folder.placemarkList(); QVector::const_iterator i = bookmarks.constBegin(); QVector::const_iterator end = bookmarks.constEnd(); for (; i != end; ++i ) { QAction *bookmarkAct = new QAction( (*i)->name(), this ); QVariant var; GeoDataLookAt* lookAt = (*i)->lookAt(); if ( !lookAt ) { GeoDataLookAt coordinateToLookAt; coordinateToLookAt.setCoordinates( (*i)->coordinate() ); coordinateToLookAt.setRange( (*i)->coordinate().altitude() ); } else { var.setValue( *lookAt ); } bookmarkAct->setData( var ); m_bookmarksListMenu->addAction( bookmarkAct ); } } void MarblePart::createInfoBoxesMenu() { QList floatItemList = m_controlView->marbleWidget()->floatItems(); QList actionList; QList::const_iterator i = floatItemList.constBegin(); QList::const_iterator const end = floatItemList.constEnd(); for (; i != end; ++i ) { actionList.append( (*i)->action() ); } unplugActionList( "infobox_actionlist" ); plugActionList( "infobox_actionlist", actionList ); } void MarblePart::createOnlineServicesMenu() { QList renderPluginList = m_controlView->marbleWidget()->renderPlugins(); QList actionList; QList::const_iterator i = renderPluginList.constBegin(); QList::const_iterator const end = renderPluginList.constEnd(); for (; i != end; ++i ) { // FIXME: This will go into the layer manager when AbstractDataPlugin is an interface if( (*i)->renderType() == RenderPlugin::OnlineRenderType ) { actionList.append( (*i)->action() ); } } unplugActionList( "onlineservices_actionlist" ); plugActionList( "onlineservices_actionlist", actionList ); } void MarblePart::createRenderPluginActions() { QList renderPluginList = m_controlView->marbleWidget()->renderPlugins(); QList actionList; QList::const_iterator i = renderPluginList.constBegin(); QList::const_iterator const end = renderPluginList.constEnd(); for (; i != end; ++i ) { if( (*i)->renderType() == RenderPlugin::ThemeRenderType ) { actionList.append( (*i)->action() ); } } unplugActionList( "themerender_actionlist" ); plugActionList( "themerender_actionlist", actionList ); } void MarblePart::showDateTime() { m_clock = QLocale().toString( m_controlView->marbleModel()->clockDateTime().addSecs( m_controlView->marbleModel()->clockTimezone() ), QLocale::ShortFormat ); updateStatusBar(); } void MarblePart::showPosition( const QString& position ) { m_position = position; updateStatusBar(); } void MarblePart::showZoomLevel( const int tileLevel ) { if ( tileLevel == -1 ) m_tileZoomLevel = QCoreApplication::translate( "Marble", NOT_AVAILABLE ); else { m_tileZoomLevel.setNum( tileLevel ); } updateStatusBar(); } void MarblePart::mapThemeChanged( const QString& newMapTheme ) { Q_UNUSED( newMapTheme ); updateTileZoomLevel(); updateStatusBar(); } void MarblePart::createPluginMenus() { unplugActionList("plugins_actionlist"); unplugActionList("plugins_menuactionlist"); QList renderPluginList = m_controlView->marbleWidget()->renderPlugins(); QList::const_iterator i = renderPluginList.constBegin(); QList::const_iterator const end = renderPluginList.constEnd(); for (; i != end; ++i ) { // menus const QList *tmp_actionGroups = (*i)->actionGroups(); if( (*i)->enabled() && tmp_actionGroups ) { for( QActionGroup *ag: *tmp_actionGroups ) { plugActionList( "plugins_menuactionlist", ag->actions() ); } } // toolbars const QList *tmp_toolbarActionGroups = (*i)->toolbarActionGroups(); if ( (*i)->enabled() && tmp_toolbarActionGroups ) { for( QActionGroup* ag: *tmp_toolbarActionGroups ) { plugActionList( "plugins_actionlist", ag->actions() ); } } } } void MarblePart::updateTileZoomLevel() { const int tileZoomLevel = m_controlView->marbleWidget()->tileZoomLevel(); if ( tileZoomLevel == -1 ) m_tileZoomLevel = QCoreApplication::translate( "Marble", NOT_AVAILABLE ); else { m_tileZoomLevel.setNum( tileZoomLevel ); } } void MarblePart::migrateNewstuffConfigFiles() { // Newstuff config files used to be in the KDE data directory of the user, but are now // shared between Marble KDE and Marble Qt in Marble's data path of the user. // This method moves an old KDE newstuff config file to the new location if the former // exists and the latter not. QFileInfo const target(MarbleDirs::localPath() + QLatin1String("/newstuff/marble-map-themes.knsregistry")); if ( !target.exists() ) { QString const source = QStandardPaths::locate( QStandardPaths::GenericDataLocation, "knewstuff3/marble.knsregistry" ); if ( !source.isEmpty() ) { if ( !target.absoluteDir().exists() ) { if ( !QDir::root().mkpath( target.absolutePath() ) ) { mDebug() << "Failed to create target directory " << target.absolutePath() << " needed for newstuff migration"; return; } } QFile registryFile( source ); if ( !registryFile.open( QFile::ReadOnly ) ) { mDebug() << "Cannot parse newstuff xml file"; return; } QDomDocument xml; if ( !xml.setContent( registryFile.readAll() ) ) { mDebug() << "Cannot parse newstuff xml data"; return; } QDomNodeList items = xml.elementsByTagName( "stuff" ); for ( int i = 0; i < items.length(); ++i ) { repairNode( items.item(i), QString("summary") ); repairNode( items.item(i), QString("author") ); } QFile output( target.absoluteFilePath() ); if ( !output.open( QFile::WriteOnly ) ) { mDebug() << "Cannot open " << target.absoluteFilePath() << " for writing"; } else { QTextStream outStream( &output ); outStream << xml.toString( 2 ); outStream.flush(); output.close(); } } } } void MarblePart::repairNode( QDomNode node, const QString &child ) { int const size = node.namedItem( child ).toElement().text().size(); if ( size > 1024 ) { QString const theme = node.namedItem(QStringLiteral("name")).toElement().text(); mDebug() << "Removing GHNS field " << child << " of map theme " << theme << ": Size " << size << " exceeds maximum size (see bug 319542)."; node.removeChild( node.namedItem( child ) ); } } void MarblePart::updateCloudSyncStatus(const QString& status ) { m_ui_cloudSyncSettings.cloudSyncStatus->setText(status); switch (m_controlView->cloudSyncManager()->status()){ case CloudSyncManager::Success: m_ui_cloudSyncSettings.cloudSyncStatus->setStyleSheet("QLabel { color : green; }"); break; case CloudSyncManager::Error: m_ui_cloudSyncSettings.cloudSyncStatus->setStyleSheet("QLabel { color : red; }"); break; case CloudSyncManager::Unknown: m_ui_cloudSyncSettings.cloudSyncStatus->setStyleSheet("QLabel { color : grey; }"); break; } } void MarblePart::updateCloudSyncCredentials() { m_controlView->cloudSyncManager()->setOwncloudCredentials( m_ui_cloudSyncSettings.kcfg_owncloudServer->text(), m_ui_cloudSyncSettings.kcfg_owncloudUsername->text(), m_ui_cloudSyncSettings.kcfg_owncloudPassword->text() ); } void MarblePart::updateStatusBar() { if ( m_positionLabel ) m_positionLabel->setText( i18n( POSITION_STRING, m_position ) ); if ( m_distanceLabel ) m_distanceLabel->setText( i18n( DISTANCE_STRING, m_controlView->marbleWidget()->distanceString() ) ); if ( m_tileZoomLevelLabel ) m_tileZoomLevelLabel->setText( i18n( TILEZOOMLEVEL_STRING, m_tileZoomLevel ) ); if ( m_clockLabel ) m_clockLabel->setText( i18n( DATETIME_STRING, m_clock ) ); } void MarblePart::setupStatusBar() { QFontMetrics statusBarFontMetrics( m_statusBarExtension->statusBar()->fontMetrics() ); // UTM syntax is used in the template string, as it is longer than the lon/lat one QString templatePositionString = QString( "%1 00Z 000000.00 m E, 00000000.00 m N_" ).arg(POSITION_STRING); m_positionLabel = setupStatusBarLabel( templatePositionString ); QString templateDistanceString = QString( "%1 00.000,0 mu" ).arg(DISTANCE_STRING); m_distanceLabel = setupStatusBarLabel( templateDistanceString ); QString templateDateTimeString = QString( "%1 %2" ).arg( DATETIME_STRING , QLocale().toString( QDateTime::fromString ( "01:01:1000", "dd:mm:yyyy"), QLocale::ShortFormat ) ); m_clockLabel = setupStatusBarLabel( templateDateTimeString ); const QString templateTileZoomLevelString = i18n( TILEZOOMLEVEL_STRING, m_tileZoomLevel ); m_tileZoomLevelLabel = setupStatusBarLabel( templateTileZoomLevelString ); connect( m_controlView->marbleWidget(), SIGNAL(mouseMoveGeoPosition(QString)), this, SLOT(showPosition(QString)) ); connect( m_controlView->marbleWidget(), SIGNAL(distanceChanged(QString)), this, SLOT(updateStatusBar()) ); connect( m_controlView->marbleWidget(), SIGNAL(tileLevelChanged(int)), SLOT(showZoomLevel(int))); connect( m_controlView->marbleWidget(), SIGNAL(themeChanged(QString)), this, SLOT(mapThemeChanged(QString)), Qt::QueuedConnection ); connect( m_controlView->marbleModel()->clock(), SIGNAL(timeChanged()), this, SLOT(showDateTime()) ); setupDownloadProgressBar(); setupStatusBarActions(); updateStatusBar(); } QLabel * MarblePart::setupStatusBarLabel( const QString& templateString ) { QFontMetrics statusBarFontMetrics( m_statusBarExtension->statusBar()->fontMetrics() ); QLabel * const label = new QLabel( m_statusBarExtension->statusBar() ); label->setIndent( 5 ); int maxWidth = statusBarFontMetrics.boundingRect( templateString ).width() + 2 * label->margin() + 2 * label->indent(); label->setFixedWidth( maxWidth ); m_statusBarExtension->addStatusBarItem( label, -1, false ); return label; } void MarblePart::setupDownloadProgressBar() { // get status bar and add progress widget QStatusBar * const statusBar = m_statusBarExtension->statusBar(); Q_ASSERT( statusBar ); m_downloadProgressBar = new QProgressBar; m_downloadProgressBar->setVisible( MarbleSettings::showDownloadProgressBar() ); statusBar->addPermanentWidget( m_downloadProgressBar ); HttpDownloadManager * const downloadManager = m_controlView->marbleModel()->downloadManager(); Q_ASSERT( downloadManager ); connect( downloadManager, SIGNAL(progressChanged(int,int)), SLOT(handleProgress(int,int)) ); connect( downloadManager, SIGNAL(jobRemoved()), SLOT(removeProgressItem()) ); } void MarblePart::setupStatusBarActions() { QStatusBar * const statusBar = m_statusBarExtension->statusBar(); Q_ASSERT( statusBar ); statusBar->setContextMenuPolicy( Qt::CustomContextMenu ); connect( statusBar, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showStatusBarContextMenu(QPoint))); m_showPositionAction = new KToggleAction( i18nc( "Action for toggling", "Show Position" ), this ); m_showDateTimeAction = new KToggleAction( i18nc( "Action for toggling", "Show Date and Time" ), this ); m_showAltitudeAction = new KToggleAction( i18nc( "Action for toggling", "Show Altitude" ), this ); m_showTileZoomLevelAction = new KToggleAction( i18nc( "Action for toggling", "Show Tile Zoom Level" ), this ); m_showDownloadProgressAction = new KToggleAction( i18nc( "Action for toggling", "Show Download Progress Bar" ), this ); connect( m_showPositionAction, SIGNAL(triggered(bool)), this, SLOT(showPositionLabel(bool)) ); connect( m_showAltitudeAction, SIGNAL(triggered(bool)), this, SLOT(showAltitudeLabel(bool)) ); connect( m_showTileZoomLevelAction, SIGNAL(triggered(bool)), this, SLOT(showTileZoomLevelLabel(bool)) ); connect( m_showDateTimeAction, SIGNAL(triggered(bool)), this, SLOT(showDateTimeLabel(bool)) ); connect( m_showDownloadProgressAction, SIGNAL(triggered(bool)), this, SLOT(showDownloadProgressBar(bool)) ); } void MarblePart::showNewStuffDialog() { QPointer dialog( new MapThemeDownloadDialog( m_controlView->marbleWidget() ) ); dialog->exec(); delete dialog; } void MarblePart::showUploadNewStuffDialog() { QString newStuffConfig = QStandardPaths::locate( QStandardPaths::GenericDataLocation, "marble/marble.knsrc" ); qDebug() << "KNS config file:" << newStuffConfig; QPointer dialog( new KNS3::UploadDialog( newStuffConfig, m_controlView ) ); qDebug() << "Creating the archive"; dialog->setUploadFile( QUrl( MapWizard::createArchive( m_controlView, m_controlView->marbleWidget()->mapThemeId() ) ) ); dialog->exec(); MapWizard::deleteArchive( m_controlView->marbleWidget()->mapThemeId() ); delete dialog; } void MarblePart::showDownloadRegionDialog() { MarbleWidget * const marbleWidget = m_controlView->marbleWidget(); if ( !m_downloadRegionDialog ) { m_downloadRegionDialog = new DownloadRegionDialog( marbleWidget, widget() ); // it might be tempting to move the connects to DownloadRegionDialog's "accepted" and // "applied" signals, be aware that the "hidden" signal might be come before the "accepted" // signal, leading to a too early disconnect. connect( m_downloadRegionDialog, SIGNAL(accepted()), SLOT(downloadRegion())); connect( m_downloadRegionDialog, SIGNAL(applied()), SLOT(downloadRegion())); } // FIXME: get allowed range from current map theme m_downloadRegionDialog->setAllowedTileLevelRange( 0, 16 ); m_downloadRegionDialog->setSelectionMethod( DownloadRegionDialog::VisibleRegionMethod ); ViewportParams const * const viewport = marbleWidget->viewport(); m_downloadRegionDialog->setSpecifiedLatLonAltBox( viewport->viewLatLonAltBox() ); m_downloadRegionDialog->setVisibleLatLonAltBox( viewport->viewLatLonAltBox() ); m_downloadRegionDialog->setVisibleTileLevel( marbleWidget->tileZoomLevel() ); m_downloadRegionDialog->show(); m_downloadRegionDialog->raise(); m_downloadRegionDialog->activateWindow(); } void MarblePart::downloadRegion() { Q_ASSERT( m_downloadRegionDialog ); QVector const pyramid = m_downloadRegionDialog->region(); if ( !pyramid.isEmpty() ) { m_controlView->marbleWidget()->downloadRegion( pyramid ); } } void MarblePart::showStatusBarContextMenu( const QPoint& pos ) { QStatusBar * const statusBar = m_statusBarExtension->statusBar(); Q_ASSERT( statusBar ); QMenu statusBarContextMenu( m_controlView->marbleWidget() ); statusBarContextMenu.addAction( m_showPositionAction ); statusBarContextMenu.addAction( m_showDateTimeAction ); statusBarContextMenu.addAction( m_showAltitudeAction ); statusBarContextMenu.addAction( m_showTileZoomLevelAction ); statusBarContextMenu.addAction( m_showDownloadProgressAction ); statusBarContextMenu.exec( statusBar->mapToGlobal( pos )); } void MarblePart::showMapWizard() { // Map Wizard QPointer mapWizard = new MapWizard( m_controlView ); mapWizard->setWmsServers( MarbleSettings::wmsServers() ); mapWizard->setStaticUrlServers( MarbleSettings::staticUrlServers() ); mapWizard->exec(); MarbleSettings::setWmsServers( mapWizard->wmsServers() ); MarbleSettings::setStaticUrlServers( mapWizard->staticUrlServers() ); mapWizard->deleteLater(); } void MarblePart::editSettings() { if ( KConfigDialog::showDialog( "settings" ) ) return; m_configDialog = new KConfigDialog( m_controlView, "settings", MarbleSettings::self() ); // view page Ui_MarbleViewSettingsWidget ui_viewSettings; QWidget *w_viewSettings = new QWidget( nullptr ); w_viewSettings->setObjectName( "view_page" ); ui_viewSettings.setupUi( w_viewSettings ); m_configDialog->addPage( w_viewSettings, i18n( "View" ), "configure" ); ui_viewSettings.label_labelLocalization->hide(); ui_viewSettings.kcfg_labelLocalization->hide(); // navigation page Ui_MarbleNavigationSettingsWidget ui_navigationSettings; QWidget *w_navigationSettings = new QWidget( nullptr ); w_navigationSettings->setObjectName( "navigation_page" ); ui_navigationSettings.setupUi( w_navigationSettings ); m_configDialog->addPage( w_navigationSettings, i18n( "Navigation" ), "transform-move" ); ui_navigationSettings.kcfg_dragLocation->hide(); ui_navigationSettings.label_dragLocation->hide(); // cache page Ui_MarbleCacheSettingsWidget ui_cacheSettings; QWidget *w_cacheSettings = new QWidget( nullptr ); w_cacheSettings->setObjectName( "cache_page" ); ui_cacheSettings.setupUi( w_cacheSettings ); m_configDialog->addPage( w_cacheSettings, i18n( "Cache & Proxy" ), "preferences-web-browser-cache" ); connect( ui_cacheSettings.button_clearVolatileCache, SIGNAL(clicked()), m_controlView->marbleWidget(), SLOT(clearVolatileTileCache()) ); connect( ui_cacheSettings.button_clearPersistentCache, SIGNAL(clicked()), m_controlView->marbleModel(), SLOT(clearPersistentTileCache()) ); // time page Ui_MarbleTimeSettingsWidget ui_timeSettings; QWidget *w_timeSettings = new QWidget( nullptr ); w_timeSettings->setObjectName( "time_page" ); ui_timeSettings.setupUi( w_timeSettings ); m_configDialog->addPage( w_timeSettings, i18n( "Date & Time" ), "clock" ); // Sync page QWidget *w_cloudSyncSettings = new QWidget( nullptr ); w_cloudSyncSettings->setObjectName( "sync_page" ); m_ui_cloudSyncSettings.setupUi( w_cloudSyncSettings ); m_ui_cloudSyncSettings.button_syncNow->setEnabled( MarbleSettings::syncBookmarks() ); m_configDialog->addPage( w_cloudSyncSettings, i18n( "Synchronization" ), "folder-sync" ); connect( m_ui_cloudSyncSettings.button_syncNow, SIGNAL(clicked()), m_controlView->cloudSyncManager()->bookmarkSyncManager(), SLOT(startBookmarkSync()) ); connect( m_ui_cloudSyncSettings.testLoginButton, SIGNAL(clicked()), this, SLOT(updateCloudSyncCredentials()) ); connect( m_controlView->cloudSyncManager(), SIGNAL(statusChanged(QString)), this, SLOT(updateCloudSyncStatus(QString))); // routing page RoutingProfilesWidget *w_routingSettings = new RoutingProfilesWidget( m_controlView->marbleModel() ); w_routingSettings->setObjectName( "routing_page" ); m_configDialog->addPage( w_routingSettings, i18n( "Routing" ), "flag"); // plugin page MarblePluginSettingsWidget *w_pluginSettings = new MarblePluginSettingsWidget(); RenderPluginModel *const pluginModel = new RenderPluginModel( w_pluginSettings ); pluginModel->setRenderPlugins( m_controlView->marbleWidget()->renderPlugins() ); w_pluginSettings->setModel( pluginModel ); w_pluginSettings->setObjectName( "plugin_page" ); m_configDialog->addPage( w_pluginSettings, i18n( "Plugins" ), "preferences-plugin" ); // Setting the icons of the pluginSettings page. w_pluginSettings->setConfigIcon( QIcon::fromTheme( "configure" ) ); w_pluginSettings->setAboutIcon( QIcon::fromTheme( "help-about" ) ); connect( w_pluginSettings, SIGNAL(pluginListViewClicked()), SLOT(enableApplyButton()) ); connect( m_configDialog, SIGNAL(settingsChanged(QString)), SLOT(updateSettings()) ); connect( m_configDialog, SIGNAL(accepted()), SLOT(applyPluginState()) ); connect( m_configDialog, SIGNAL(accepted()), pluginModel, SLOT(applyPluginState()) ); connect( m_configDialog, SIGNAL(rejected()), pluginModel, SLOT(retrievePluginState()) ); m_configDialog->show(); } void MarblePart::enableApplyButton() { //m_configDialog->enableButtonApply( true ); } void MarblePart::applyPluginState() { QList profiles = m_controlView->marbleWidget() ->model()->routingManager()->profilesModel()->profiles(); KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); KConfigGroup profilesGroup = sharedConfig->group( "Routing Profiles" ); profilesGroup.writeEntry( "Num", profiles.count() ); for ( int i = 0; i < profiles.count(); ++i ) { KConfigGroup profileGroup = profilesGroup.group( QString( "Profile %0" ).arg(i) ); RoutingProfile profile = profiles.at( i ); profileGroup.writeEntry( "Name", profile.name() ); for ( const QString &pluginName: profileGroup.groupList() ) { profileGroup.group( pluginName ).deleteGroup(); } for ( const QString &key: profile.pluginSettings().keys() ) { KConfigGroup pluginGroup = profileGroup.group( key ); pluginGroup.writeEntry( "Enabled", true ); for ( const QString& settingKey: profile.pluginSettings()[ key ].keys() ) { Q_ASSERT(settingKey != QLatin1String("Enabled")); pluginGroup.writeEntry( settingKey, profile.pluginSettings()[ key ][ settingKey ] ); } } } } void MarblePart::updateSettings() { qDebug() << "Updating Settings ..."; // FIXME: Font doesn't get updated instantly. m_controlView->marbleWidget()->setDefaultFont( MarbleSettings::mapFont() ); m_controlView->marbleWidget()-> setMapQualityForViewContext( (MapQuality) MarbleSettings::stillQuality(), Still ); m_controlView->marbleWidget()-> setMapQualityForViewContext( (MapQuality) MarbleSettings::animationQuality(), Animation ); m_controlView->marbleWidget()-> setDefaultAngleUnit( (AngleUnit) MarbleSettings::angleUnit() ); MarbleGlobal::getInstance()->locale()-> setMeasurementSystem( (MarbleLocale::MeasurementSystem) MarbleSettings::distanceUnit() ); updateStatusBar(); m_controlView->marbleWidget()->setAnimationsEnabled( MarbleSettings::animateTargetVoyage() ); // Cache m_controlView->marbleModel()-> setPersistentTileCacheLimit( MarbleSettings::persistentTileCacheLimit() * 1024 ); m_controlView->marbleWidget()-> setVolatileTileCacheLimit( MarbleSettings::volatileTileCacheLimit() * 1024 ); //Create and export the proxy QNetworkProxy proxy; // Make sure that no proxy is used for an empty string or the default value: if (MarbleSettings::proxyUrl().isEmpty() || MarbleSettings::proxyUrl() == QLatin1String("http://")) { proxy.setType( QNetworkProxy::NoProxy ); } else { if ( MarbleSettings::proxyType() == Marble::Socks5Proxy ) { proxy.setType( QNetworkProxy::Socks5Proxy ); } else if ( MarbleSettings::proxyType() == Marble::HttpProxy ) { proxy.setType( QNetworkProxy::HttpProxy ); } else { qDebug() << "Unknown proxy type! Using Http Proxy instead."; proxy.setType( QNetworkProxy::HttpProxy ); } } proxy.setHostName( MarbleSettings::proxyUrl() ); proxy.setPort( MarbleSettings::proxyPort() ); if ( MarbleSettings::proxyAuth() ) { proxy.setUser( MarbleSettings::proxyUser() ); proxy.setPassword( MarbleSettings::proxyPass() ); } QNetworkProxy::setApplicationProxy(proxy); m_controlView->marbleWidget()->update(); // Time if( MarbleSettings::systemTimezone() == true ) { QDateTime localTime = QDateTime::currentDateTime().toLocalTime(); localTime.setTimeSpec( Qt::UTC ); m_controlView->marbleModel()->setClockTimezone( QDateTime::currentDateTime().toUTC().secsTo( localTime ) ); } else if( MarbleSettings::utc() == true ) { m_controlView->marbleModel()->setClockTimezone( 0 ); } else if( MarbleSettings::customTimezone() == true ) { m_controlView->marbleModel()->setClockTimezone( m_timezone.value( MarbleSettings::chosenTimezone() ) ); } // Route rendering colors and alpha values QColor tempColor; tempColor = MarbleSettings::routeColorStandard(); tempColor.setAlpha( MarbleSettings::routeAlphaStandard() ); m_controlView->marbleModel()->routingManager()->setRouteColorStandard( tempColor ); tempColor = MarbleSettings::routeColorHighlighted(); tempColor.setAlpha( MarbleSettings::routeAlphaHighlighted() ); m_controlView->marbleModel()->routingManager()->setRouteColorHighlighted( tempColor ); tempColor = MarbleSettings::routeColorAlternative(); tempColor.setAlpha( MarbleSettings::routeAlphaAlternative() ); m_controlView->marbleModel()->routingManager()->setRouteColorAlternative( tempColor ); // External map editor m_controlView->setExternalMapEditor( m_externalEditorMapping[MarbleSettings::externalMapEditor()] ); m_controlView->marbleWidget()->inputHandler()->setInertialEarthRotationEnabled( MarbleSettings::inertialEarthRotation() ); + m_controlView->marbleWidget()->inputHandler()->setMouseViewRotationEnabled( MarbleSettings::mouseViewRotation() ); CloudSyncManager* cloudSyncManager = m_controlView->cloudSyncManager(); cloudSyncManager->setOwncloudCredentials( MarbleSettings::owncloudServer(), MarbleSettings::owncloudUsername(), MarbleSettings::owncloudPassword()); cloudSyncManager->setSyncEnabled( MarbleSettings::enableSync() ); cloudSyncManager->routeSyncManager()->setRouteSyncEnabled( MarbleSettings::syncRoutes() ); cloudSyncManager->bookmarkSyncManager()->setBookmarkSyncEnabled( MarbleSettings::syncBookmarks() ); } void MarblePart::writePluginSettings() { KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); for( RenderPlugin *plugin: m_controlView->marbleWidget()->renderPlugins() ) { KConfigGroup group = sharedConfig->group( QString( "plugin_" ) + plugin->nameId() ); const QHash hash = plugin->settings(); QHash::const_iterator it = hash.begin(); while( it != hash.end() ) { group.writeEntry( it.key(), it.value() ); ++it; } group.sync(); } } void MarblePart::readPluginSettings() { disconnect( m_controlView->marbleWidget(), SIGNAL(pluginSettingsChanged()), this, SLOT(writePluginSettings()) ); KSharedConfig::Ptr sharedConfig = KSharedConfig::openConfig(); for( RenderPlugin *plugin: m_controlView->marbleWidget()->renderPlugins() ) { KConfigGroup group = sharedConfig->group( QString( "plugin_" ) + plugin->nameId() ); QHash hash; for ( const QString& key: group.keyList() ) { hash.insert( key, group.readEntry( key ) ); } plugin->setSettings( hash ); } connect( m_controlView->marbleWidget(), SIGNAL(pluginSettingsChanged()), this, SLOT(writePluginSettings()) ); } void MarblePart::lockFloatItemPosition( bool enabled ) { QList floatItemList = m_controlView->marbleWidget()->floatItems(); QList::const_iterator i = floatItemList.constBegin(); QList::const_iterator const end = floatItemList.constEnd(); for (; i != end; ++i ) { // Locking one would suffice as it affects all. // Nevertheless go through all. (*i)->setPositionLocked(enabled); } } void MarblePart::handleProgress( int active, int queued ) { m_downloadProgressBar->setUpdatesEnabled( false ); if ( m_downloadProgressBar->value() < 0 ) { m_downloadProgressBar->setMaximum( 1 ); m_downloadProgressBar->setValue( 0 ); m_downloadProgressBar->setVisible( MarbleSettings::showDownloadProgressBar() ); } else { m_downloadProgressBar->setMaximum( qMax( m_downloadProgressBar->maximum(), active + queued ) ); } // qDebug() << "downloadProgressJobAdded: value/maximum: " // << m_downloadProgressBar->value() << '/' << m_downloadProgressBar->maximum(); m_downloadProgressBar->setUpdatesEnabled( true ); } void MarblePart::removeProgressItem() { m_downloadProgressBar->setUpdatesEnabled( false ); m_downloadProgressBar->setValue( m_downloadProgressBar->value() + 1 ); if ( m_downloadProgressBar->value() == m_downloadProgressBar->maximum() ) { m_downloadProgressBar->reset(); m_downloadProgressBar->setVisible( false ); } // qDebug() << "downloadProgressJobCompleted: value/maximum: " // << m_downloadProgressBar->value() << '/' << m_downloadProgressBar->maximum(); m_downloadProgressBar->setUpdatesEnabled( true ); } void MarblePart::openEditBookmarkDialog() { MarbleWidget *widget = m_controlView->marbleWidget(); QPointer dialog = new EditBookmarkDialog( widget->model()->bookmarkManager(), widget ); dialog->setCoordinates( widget->lookAt().coordinates() ); dialog->setRange( widget->lookAt().range() ); dialog->setMarbleWidget( widget ); dialog->setReverseGeocodeName(); if ( dialog->exec() == QDialog::Accepted ) { widget->model()->bookmarkManager()->addBookmark( dialog->folder(), dialog->bookmark() ); } delete dialog; } void MarblePart::setHome() { MarbleWidget *widget = m_controlView->marbleWidget(); widget->model()->setHome( widget->centerLongitude(), widget->centerLatitude(), widget->zoom() ); } void MarblePart::openManageBookmarksDialog() { MarbleModel * const model = m_controlView->marbleModel(); QPointer dialog = new BookmarkManagerDialog( model, m_controlView->marbleWidget() ); dialog->exec(); delete dialog; } void MarblePart::lookAtBookmark( QAction *action) { GeoDataLookAt temp = qvariant_cast( action->data() ) ; m_controlView->marbleWidget()->flyTo( temp ) ; mDebug() << " looking at bookmark having longitude : "<< temp.longitude(GeoDataCoordinates::Degree) << " latitude : "<< temp.latitude(GeoDataCoordinates::Degree) << " distance : " << temp.range(); } void MarblePart::initializeCustomTimezone() { if( m_timezone.count() == 0) { m_timezone.insert( 0, 0 ); m_timezone.insert( 1, 3600 ); m_timezone.insert( 2, 7200 ); m_timezone.insert( 3, 7200 ); m_timezone.insert( 4, 10800 ); m_timezone.insert( 5, 12600 ); m_timezone.insert( 6, 14400 ); m_timezone.insert( 7, 18000 ); m_timezone.insert( 8, 19800 ); m_timezone.insert( 9, 21600 ); m_timezone.insert( 10, 25200 ); m_timezone.insert( 11, 28800 ); m_timezone.insert( 12, 32400 ); m_timezone.insert( 13, 34200 ); m_timezone.insert( 14, 36000 ); m_timezone.insert( 15, 39600 ); m_timezone.insert( 16, 43200 ); m_timezone.insert( 17, -39600 ); m_timezone.insert( 18, -36000 ); m_timezone.insert( 19, -32400 ); m_timezone.insert( 20, -28800 ); m_timezone.insert( 21, -25200 ); m_timezone.insert( 22, -25200 ); m_timezone.insert( 23, -21600 ); m_timezone.insert( 24, -18000 ); m_timezone.insert( 25, -18000 ); m_timezone.insert( 26, -14400 ); m_timezone.insert( 27, -12600 ); m_timezone.insert( 28, -10800 ); m_timezone.insert( 29, -10800 ); m_timezone.insert( 30, -3600 ); } } void MarblePart::printMapScreenShot() { #ifndef QT_NO_PRINTER QPrinter printer( QPrinter::HighResolution ); QPointer printDialog = new QPrintDialog( &printer, widget() ); m_controlView->printMapScreenShot( printDialog ); delete printDialog; #endif } void MarblePart::updateMapEditButtonVisibility( const QString &mapTheme ) { Q_ASSERT( m_externalMapEditorAction ); m_externalMapEditorAction->setVisible(mapTheme == QLatin1String("earth/openstreetmap/openstreetmap.dgml")); } void MarblePart::fallBackToDefaultTheme() { m_controlView->marbleWidget()->setMapThemeId( m_controlView->defaultMapThemeId() ); } void MarblePart::showMovieCaptureDialog() { if (m_movieCaptureDialog == nullptr) { m_movieCaptureDialog = new MovieCaptureDialog(m_controlView->marbleWidget(), m_controlView->marbleWidget()); connect( m_movieCaptureDialog, SIGNAL(started()), this, SLOT(changeRecordingState())); } m_movieCaptureDialog->show(); } void MarblePart::stopRecording() { if ( m_movieCaptureDialog ) { m_movieCaptureDialog->stopRecording(); changeRecordingState(); } } void MarblePart::changeRecordingState() { m_recordMovieAction->setEnabled( !m_recordMovieAction->isEnabled() ); m_stopRecordingAction->setEnabled( !m_stopRecordingAction->isEnabled() ); } } #include "moc_marble_part.cpp" #include "marble_part.moc" diff --git a/src/apps/marble-qt/QtMainWindow.cpp b/src/apps/marble-qt/QtMainWindow.cpp index a11e39a55..e3b8fe7e7 100644 --- a/src/apps/marble-qt/QtMainWindow.cpp +++ b/src/apps/marble-qt/QtMainWindow.cpp @@ -1,1666 +1,1667 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2006-2010 Torsten Rahn // Copyright 2007 Inge Wallin // Copyright 2011-2013 Bernhard Beschow // Copyright 2012 Illya Kovalevskyy // Copyright 2012 Mohammed Nafees // #include "QtMainWindow.h" #include "MarbleDebug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "EditBookmarkDialog.h" #include "BookmarkManagerDialog.h" #include "CurrentLocationWidget.h" #include "MapViewWidget.h" #include "MarbleDirs.h" #include "MarbleAboutDialog.h" #include "QtMarbleConfigDialog.h" #include "SunControlWidget.h" #include "TimeControlWidget.h" #include "MarbleLocale.h" #include "DownloadRegionDialog.h" #include "ViewportParams.h" #include "AbstractFloatItem.h" #include "MarbleModel.h" #include "MarbleClock.h" #include "HttpDownloadManager.h" #include "BookmarkManager.h" #include "NewBookmarkFolderDialog.h" #include "GeoSceneDocument.h" #include "GeoSceneHead.h" #include "GeoDataLookAt.h" #include "GeoDataCoordinates.h" #include "GeoDataDocument.h" #include "GeoDataFolder.h" #include "GeoDataPlacemark.h" #include "GeoUriParser.h" #include "routing/RoutingManager.h" #include "routing/RoutingProfilesModel.h" #include "routing/RoutingWidget.h" #include "routing/RouteRequest.h" #include "ParseRunnerPlugin.h" #include "PositionTracking.h" #include "PositionProviderPlugin.h" #include "PluginManager.h" #include "MarbleColors.h" #include "MapThemeDownloadDialog.h" #include "MapWizard.h" #include "MarbleWidgetInputHandler.h" #include "Planet.h" #include "cloudsync/CloudSyncManager.h" #include "cloudsync/BookmarkSyncManager.h" #include "cloudsync/RouteSyncManager.h" #include "MovieCaptureDialog.h" #include "DataMigration.h" #include "TileCoordsPyramid.h" using namespace Marble; /* TRANSLATOR Marble::MainWindow */ MainWindow::MainWindow(const QString& marbleDataPath, const QVariantMap& cmdLineSettings, QWidget *parent) : QMainWindow(parent), m_controlView( nullptr ), m_savedSize( QSize(-1, -1) ), m_sunControlDialog( nullptr ), m_timeControlDialog( nullptr ), m_configDialog( nullptr ), m_downloadRegionDialog( nullptr ), m_movieCaptureDialog( nullptr ), // File Menu m_fileMenu( nullptr ), m_viewMenu( nullptr ), m_helpMenu( nullptr ), m_settingsMenu( nullptr ), m_panelMenu( nullptr ), m_viewSizeMenu( nullptr ), m_infoBoxesMenu( nullptr ), m_onlineServicesMenu( nullptr ), m_bookmarkMenu( nullptr ), m_openAction( nullptr ), m_exportMapAction( nullptr ), m_downloadAction( nullptr ), m_downloadRegionAction( nullptr ), m_printPreviewAction( nullptr ), m_printAction( nullptr ), m_workOfflineAction( nullptr ), m_quitAction( nullptr ), m_mapWizardAction( nullptr ), // Edit Menu m_copyMapAction( nullptr ), m_copyCoordinatesAction( nullptr ), m_osmEditAction( nullptr ), m_recordMovieAction( nullptr ), m_stopRecordingAction( nullptr ), // View Menu m_showCloudsAction( nullptr ),\ m_controlSunAction( nullptr ), m_controlTimeAction( nullptr ), m_reloadAction( nullptr ), // Settings Menu m_fullScreenAction( nullptr ), m_statusBarAction( nullptr ), m_configDialogAction( nullptr ), m_viewSizeActsGroup( nullptr ), // Help Menu m_whatsThisAction( nullptr ), m_aboutMarbleAction( nullptr ), m_aboutQtAction( nullptr ), m_lockFloatItemsAction( nullptr ), m_handbookAction( nullptr ), m_forumAction( nullptr ), // Status Bar m_positionLabel( nullptr ), m_distanceLabel( nullptr ), m_zoomLabel( nullptr ), m_clockLabel( nullptr ), m_downloadProgressBar( nullptr ), m_toggleTileLevelAction( nullptr ), m_angleDisplayUnitActionGroup( nullptr ), m_dmsDegreeAction( nullptr ), m_decimalDegreeAction( nullptr ), m_utmAction( nullptr ), //Bookmark Menu m_addBookmarkAction( nullptr ), m_setHomeAction( nullptr ), m_toggleBookmarkDisplayAction( nullptr ), m_manageBookmarksAction( nullptr ) { setUpdatesEnabled( false ); QString selectedPath = marbleDataPath.isEmpty() ? readMarbleDataPath() : marbleDataPath; if ( !selectedPath.isEmpty() ) MarbleDirs::setMarbleDataPath( selectedPath ); #ifdef Q_OS_WIN QPointer migration = new DataMigration(this); migration->exec(); #endif m_controlView = new ControlView( this ); setWindowIcon(QIcon(QStringLiteral(":/icons/marble.png"))); setCentralWidget( m_controlView ); // Initializing config dialog m_configDialog = new QtMarbleConfigDialog( m_controlView->marbleWidget(), m_controlView->cloudSyncManager(), this ); connect( m_configDialog, SIGNAL(settingsChanged()), this, SLOT(updateSettings()) ); connect( m_configDialog, SIGNAL(clearVolatileCacheClicked()), m_controlView->marbleWidget(), SLOT(clearVolatileTileCache()) ); connect( m_configDialog, SIGNAL(clearPersistentCacheClicked()), m_controlView->marbleModel(), SLOT(clearPersistentTileCache()) ); connect( m_configDialog, SIGNAL(syncNowClicked()), m_controlView->cloudSyncManager()->bookmarkSyncManager(), SLOT(startBookmarkSync()) ); connect(m_configDialog, SIGNAL(syncNowClicked()), m_configDialog, SLOT(disableSyncNow())); // Load bookmark file. If it does not exist, a default one will be used. m_controlView->marbleModel()->bookmarkManager()->loadFile( "bookmarks/bookmarks.kml" ); createActions(); QList const panelActions = m_controlView->setupDockWidgets( this ); createMenus( panelActions ); createStatusBar(); connect( m_controlView->marbleWidget(), SIGNAL(themeChanged(QString)), this, SLOT(updateMapEditButtonVisibility(QString)) ); connect(m_controlView->marbleModel(), SIGNAL(themeChanged(QString)), this, SLOT(updateWindowTitle())); connect( m_controlView, SIGNAL(showMapWizard()), this, SLOT(showMapWizard()) ); connect( m_controlView, SIGNAL(mapThemeDeleted()), this, SLOT(fallBackToDefaultTheme()) ); updateWindowTitle(); setUpdatesEnabled( true ); m_position = QCoreApplication::translate( "Marble", NOT_AVAILABLE ); m_distance = marbleWidget()->distanceString(); m_zoom = QString::number( marbleWidget()->tileZoomLevel() ); m_clock = QLocale().toString( m_controlView->marbleModel()->clockDateTime().addSecs( m_controlView->marbleModel()->clockTimezone() ), QLocale::ShortFormat ); QMetaObject::invokeMethod(this, "initObject", Qt::QueuedConnection, Q_ARG(QVariantMap, cmdLineSettings)); } MainWindow::~MainWindow() { delete m_movieCaptureDialog; } void MainWindow::addGeoDataFile( const QString &fileName ) { QFileInfo file( fileName ); if ( !file.exists() ) return; // delay file loading to initObject(), such that restoring view from previous session in readSettings() // doesn't interfere with focusing on these files m_commandlineFilePaths << file.absoluteFilePath(); } void MainWindow::initObject(const QVariantMap& cmdLineSettings) { QCoreApplication::processEvents (); setupStatusBar(); readSettings(cmdLineSettings); for ( const QString &path: m_commandlineFilePaths ) { m_controlView->marbleModel()->addGeoDataFile( path ); } if ( cmdLineSettings.contains( "tour" ) ) { QString const tour = cmdLineSettings.value( "tour" ).toString(); m_controlView->openTour( tour ); } m_commandlineFilePaths.clear(); } void MainWindow::createActions() { m_openAction = new QAction(QIcon(QStringLiteral(":/icons/document-open.png")), tr("&Open..."), this); m_openAction->setShortcut( tr( "Ctrl+O" ) ); m_openAction->setStatusTip( tr( "Open a file for viewing on Marble")); connect( m_openAction, SIGNAL(triggered()), this, SLOT(openFile()) ); m_downloadAction = new QAction(QIcon(QStringLiteral(":/icons/get-hot-new-stuff.png")), tr("&Download Maps..."), this); connect(m_downloadAction, SIGNAL(triggered()), this, SLOT(openMapDialog())); m_exportMapAction = new QAction(QIcon(QStringLiteral(":/icons/document-save-as.png")), tr("&Export Map..."), this); m_exportMapAction->setShortcut(tr("Ctrl+S")); m_exportMapAction->setStatusTip(tr("Save a screenshot of the map")); connect(m_exportMapAction, SIGNAL(triggered()), this, SLOT(exportMapScreenShot())); // Action: Download Region m_downloadRegionAction = new QAction( tr( "Download &Region..." ), this ); m_downloadRegionAction->setStatusTip( tr( "Download a map region in different zoom levels for offline usage" ) ); connect( m_downloadRegionAction, SIGNAL(triggered()), SLOT(showDownloadRegionDialog()) ); m_printAction = new QAction(QIcon(QStringLiteral(":/icons/document-print.png")), tr("&Print..."), this); m_printAction->setShortcut(tr("Ctrl+P")); m_printAction->setStatusTip(tr("Print a screenshot of the map")); connect(m_printAction, SIGNAL(triggered()), this, SLOT(printMapScreenShot())); m_printPreviewAction = new QAction(QIcon(QStringLiteral(":/icons/document-print-preview.png")), tr("Print Previe&w ..."), this); m_printPreviewAction->setStatusTip(tr("Print a screenshot of the map")); connect(m_printPreviewAction, SIGNAL(triggered()), m_controlView, SLOT(printPreview())); m_quitAction = new QAction(QIcon(QStringLiteral(":/icons/application-exit.png")), tr("&Quit"), this); m_quitAction->setShortcut(tr("Ctrl+Q")); m_quitAction->setStatusTip(tr("Quit the Application")); connect(m_quitAction, SIGNAL(triggered()), this, SLOT(close())); m_copyMapAction = new QAction(QIcon(QStringLiteral(":/icons/edit-copy.png")), tr("&Copy Map"), this); m_copyMapAction->setShortcut(tr("Ctrl+C")); m_copyMapAction->setStatusTip(tr("Copy a screenshot of the map")); connect(m_copyMapAction, SIGNAL(triggered()), this, SLOT(copyMap())); m_osmEditAction = new QAction(QIcon(QStringLiteral(":/icons/edit-map.png")), tr("&Edit Map"), this ); m_osmEditAction->setShortcut(tr( "Ctrl+E" ) ); m_osmEditAction->setStatusTip(tr( "Edit the current map region in an external editor" ) ); updateMapEditButtonVisibility( m_controlView->marbleWidget()->mapThemeId() ); connect( m_osmEditAction, SIGNAL(triggered()), m_controlView, SLOT(launchExternalMapEditor()) ); m_recordMovieAction = new QAction(tr("&Record Movie"), this); m_recordMovieAction->setStatusTip(tr("Records a movie of the globe")); m_recordMovieAction->setShortcut(QKeySequence("Ctrl+Shift+R")); m_recordMovieAction->setIcon(QIcon(QStringLiteral(":/icons/animator.png"))); connect(m_recordMovieAction, SIGNAL(triggered()), this, SLOT(showMovieCaptureDialog())); m_stopRecordingAction = new QAction( tr("&Stop Recording"), this ); m_stopRecordingAction->setStatusTip( tr("Stop recording a movie of the globe") ); m_stopRecordingAction->setShortcut(QKeySequence( "Ctrl+Shift+S" )); m_stopRecordingAction->setEnabled( false ); connect( m_stopRecordingAction, SIGNAL(triggered()), this, SLOT(stopRecording()) ); m_configDialogAction = new QAction(QIcon(QStringLiteral(":/icons/settings-configure.png")), tr("&Configure Marble"), this); m_configDialogAction->setStatusTip(tr("Show the configuration dialog")); connect(m_configDialogAction, SIGNAL(triggered()), this, SLOT(editSettings())); m_copyCoordinatesAction = new QAction(QIcon(QStringLiteral(":/icons/copy-coordinates.png")), tr("C&opy Coordinates"), this); m_copyCoordinatesAction->setStatusTip(tr("Copy the center coordinates as text")); connect(m_copyCoordinatesAction, SIGNAL(triggered()), this, SLOT(copyCoordinates())); m_fullScreenAction = new QAction(QIcon(QStringLiteral(":/icons/view-fullscreen.png")), tr("&Full Screen Mode"), this); m_fullScreenAction->setShortcut(tr("Ctrl+Shift+F")); m_fullScreenAction->setCheckable( true ); m_fullScreenAction->setStatusTip(tr("Full Screen Mode")); connect(m_fullScreenAction, SIGNAL(triggered(bool)), this, SLOT(showFullScreen(bool))); m_statusBarAction = new QAction( tr("&Show Status Bar"), this); m_statusBarAction->setCheckable( true ); m_statusBarAction->setStatusTip(tr("Show Status Bar")); connect(m_statusBarAction, SIGNAL(triggered(bool)), this, SLOT(showStatusBar(bool))); m_lockFloatItemsAction = new QAction(QIcon(QStringLiteral(":/icons/unlock.png")), tr("Lock Position"), this); m_lockFloatItemsAction->setCheckable( true ); m_lockFloatItemsAction->setStatusTip(tr("Lock Position of Floating Items")); connect(m_lockFloatItemsAction, SIGNAL(triggered(bool)), this, SLOT(lockPosition(bool))); m_showCloudsAction = new QAction(QIcon(QStringLiteral(":/icons/clouds.png")), tr("&Clouds"), this); m_showCloudsAction->setCheckable( true ); m_showCloudsAction->setStatusTip(tr("Show Real Time Cloud Cover")); connect(m_showCloudsAction, SIGNAL(triggered(bool)), this, SLOT(showClouds(bool))); m_workOfflineAction = new QAction(QIcon(QStringLiteral(":/icons/user-offline.png")), tr("Work Off&line"), this); m_workOfflineAction->setCheckable( true ); connect(m_workOfflineAction, SIGNAL(triggered(bool)), this, SLOT(workOffline(bool))); m_controlTimeAction = new QAction(QIcon(QStringLiteral(":/icons/clock.png")), tr("&Time Control..."), this ); m_controlTimeAction->setStatusTip( tr( "Configure Time Control " ) ); connect( m_controlTimeAction, SIGNAL(triggered()), this, SLOT(controlTime()) ); m_controlSunAction = new QAction( tr( "S&un Control..." ), this ); m_controlSunAction->setStatusTip( tr( "Configure Sun Control" ) ); connect( m_controlSunAction, SIGNAL(triggered()), this, SLOT(controlSun()) ); m_reloadAction = new QAction(QIcon(QStringLiteral(":/icons/view-refresh.png")), tr("&Redisplay"), this); m_reloadAction->setShortcut(tr("F5")); m_reloadAction->setStatusTip(tr("Reload Current Map")); connect(m_reloadAction, SIGNAL(triggered()), this, SLOT(reload())); m_handbookAction = new QAction(QIcon(QStringLiteral(":/icons/help-contents.png")), tr("Marble Virtual Globe &Handbook"), this); m_handbookAction->setShortcut(tr("F1")); m_handbookAction->setStatusTip(tr("Show the Handbook for Marble Virtual Globe")); connect(m_handbookAction, SIGNAL(triggered()), this, SLOT(handbook())); m_whatsThisAction = new QAction(QIcon(QStringLiteral(":/icons/help-whatsthis.png")), tr("What's &This"), this); m_whatsThisAction->setShortcut(tr("Shift+F1")); m_whatsThisAction->setStatusTip(tr("Show a detailed explanation of the action.")); connect(m_whatsThisAction, SIGNAL(triggered()), this, SLOT(enterWhatsThis())); m_forumAction = new QAction( tr("&Community Forum"), this); m_forumAction->setStatusTip(tr("Visit Marble's Community Forum")); connect(m_forumAction, SIGNAL(triggered()), this, SLOT(openForum())); m_aboutMarbleAction = new QAction(QIcon(QStringLiteral(":/icons/marble.png")), tr("&About Marble Virtual Globe"), this); m_aboutMarbleAction->setStatusTip(tr("Show the application's About Box")); connect(m_aboutMarbleAction, SIGNAL(triggered()), this, SLOT(aboutMarble())); m_aboutQtAction = new QAction(tr("About &Qt"), this); m_aboutQtAction->setStatusTip(tr("Show the Qt library's About box")); connect(m_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt())); //Bookmark Actions m_addBookmarkAction = new QAction(QIcon(QStringLiteral(":/icons/bookmark-new.png")), tr("&Add Bookmark"), this); m_addBookmarkAction->setShortcut(tr("Ctrl+B")); m_addBookmarkAction->setStatusTip(tr("Add Bookmark")); connect( m_addBookmarkAction, SIGNAL(triggered()), this, SLOT(openEditBookmarkDialog()) ); m_setHomeAction = new QAction(QIcon(QStringLiteral(":/icons/go-home.png")), tr("&Set Home Location"), this); m_setHomeAction->setStatusTip( tr( "&Set Home Location" ) ); connect( m_setHomeAction, SIGNAL(triggered()), this, SLOT(setHome()) ); m_toggleBookmarkDisplayAction = new QAction(tr( "Show &Bookmarks" ), this); m_toggleBookmarkDisplayAction->setStatusTip( tr( "Toggle display of Bookmarks" ) ); m_toggleBookmarkDisplayAction->setCheckable( true ); connect( m_toggleBookmarkDisplayAction, SIGNAL(triggered(bool)), this, SLOT(showBookmarks(bool)) ); m_manageBookmarksAction = new QAction(QIcon(QStringLiteral(":/icons/bookmarks-organize.png")), tr("&Manage Bookmarks"), this); m_manageBookmarksAction->setStatusTip( tr( "Manage Bookmarks" ) ); connect( m_manageBookmarksAction, SIGNAL(triggered()), this, SLOT(manageBookmarks()) ); // Map Wizard action m_mapWizardAction = new QAction(QIcon(QStringLiteral(":/icons/create-new-map.png")), tr("&Create a New Map..."), this); m_mapWizardAction->setStatusTip( tr( "A wizard guides you through the creation of your own map theme." ) ); connect( m_mapWizardAction, SIGNAL(triggered()), SLOT(showMapWizard()) ); // Statusbar Actions m_toggleTileLevelAction = new QAction( tr( "Show Tile Zoom Level" ), statusBar() ); m_toggleTileLevelAction->setCheckable( true ); m_toggleTileLevelAction->setChecked( false ); connect( m_toggleTileLevelAction, SIGNAL(triggered(bool)), this, SLOT(showZoomLevel(bool)) ); m_angleDisplayUnitActionGroup = new QActionGroup( statusBar() ); m_dmsDegreeAction = new QAction( tr( "Degree (DMS)" ), statusBar() ); m_dmsDegreeAction->setCheckable( true ); m_dmsDegreeAction->setData( (int)DMSDegree ); m_angleDisplayUnitActionGroup->addAction(m_dmsDegreeAction); m_decimalDegreeAction = new QAction( tr( "Degree (Decimal)" ), statusBar() ); m_decimalDegreeAction->setCheckable( true ); m_decimalDegreeAction->setData( (int)DecimalDegree ); m_angleDisplayUnitActionGroup->addAction(m_decimalDegreeAction); m_utmAction = new QAction( tr( "Universal Transverse Mercator (UTM)" ), statusBar() ); m_utmAction->setCheckable( true ); m_utmAction->setData( (int)UTM ); m_angleDisplayUnitActionGroup->addAction(m_utmAction); connect( m_angleDisplayUnitActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeAngleDisplayUnit(QAction*)) ); // View size actions m_viewSizeActsGroup = ControlView::createViewSizeActionGroup( this ); connect( m_viewSizeActsGroup, SIGNAL(triggered(QAction*)), this, SLOT(changeViewSize(QAction*)) ); } void MainWindow::createMenus( const QList &panelActions ) { m_fileMenu = menuBar()->addMenu(tr("&File")); m_fileMenu->addAction(m_openAction); m_fileMenu->addAction(m_downloadAction); m_fileMenu->addAction( m_downloadRegionAction ); m_fileMenu->addAction( m_mapWizardAction ); m_fileMenu->addAction(m_exportMapAction); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_printAction); m_fileMenu->addAction(m_printPreviewAction); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_workOfflineAction); m_fileMenu->addAction(m_quitAction); m_fileMenu = menuBar()->addMenu(tr("&Edit")); m_fileMenu->addAction(m_copyMapAction); m_fileMenu->addAction(m_copyCoordinatesAction); m_fileMenu->addAction( m_osmEditAction ); m_fileMenu->addSeparator(); m_fileMenu->addAction(m_recordMovieAction); m_fileMenu->addAction(m_stopRecordingAction); m_viewMenu = menuBar()->addMenu(tr("&View")); m_infoBoxesMenu = new QMenu(tr("&Info Boxes"), this); m_onlineServicesMenu = new QMenu(tr("&Online Services"), this); createPluginsMenus(); m_bookmarkMenu = menuBar()->addMenu(tr("&Bookmarks")); createBookmarkMenu(); connect( m_bookmarkMenu, SIGNAL(aboutToShow()), this, SLOT(createBookmarkMenu()) ); m_panelMenu = new QMenu(tr("&Panels"), this); for( QAction* action: panelActions ) { m_panelMenu->addAction( action ); } m_viewSizeMenu = new QMenu(tr("&View Size"), this); m_viewSizeMenu->addActions( m_viewSizeActsGroup->actions() ); m_settingsMenu = menuBar()->addMenu(tr("&Settings")); m_settingsMenu->addMenu( m_panelMenu ); m_settingsMenu->addAction(m_statusBarAction); m_settingsMenu->addSeparator(); m_settingsMenu->addMenu( m_viewSizeMenu ); m_settingsMenu->addAction(m_fullScreenAction); m_settingsMenu->addSeparator(); m_settingsMenu->addAction(m_configDialogAction); m_helpMenu = menuBar()->addMenu(tr("&Help")); m_helpMenu->addAction(m_handbookAction); m_helpMenu->addAction(m_forumAction); m_helpMenu->addSeparator(); m_helpMenu->addAction(m_whatsThisAction); m_helpMenu->addSeparator(); m_helpMenu->addAction(m_aboutMarbleAction); m_helpMenu->addAction(m_aboutQtAction); // FIXME: Discuss if this is the best place to put this QList pluginList = m_controlView->marbleWidget()->renderPlugins(); QList::const_iterator it = pluginList.constBegin(); QList::const_iterator const listEnd = pluginList.constEnd(); for (; it != listEnd; ++it ) { connect( (*it), SIGNAL(actionGroupsChanged()), this, SLOT(createPluginMenus()) ); } } void MainWindow::createPluginsMenus() { m_onlineServicesMenu->clear(); m_infoBoxesMenu->clear(); m_viewMenu->clear(); m_viewMenu->addAction(m_reloadAction); m_viewMenu->addSeparator(); // Do not create too many menu entries on a MID // FIXME: Set up another way of switching the plugins on and off. if( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) { return; } m_infoBoxesMenu->addAction(m_lockFloatItemsAction); m_infoBoxesMenu->addSeparator(); QList themeActions; QList renderPluginList = m_controlView->marbleWidget()->renderPlugins(); QList::const_iterator i = renderPluginList.constBegin(); QList::const_iterator const end = renderPluginList.constEnd(); for (; i != end; ++i ) { switch( (*i)->renderType() ) { case RenderPlugin::TopLevelRenderType: m_viewMenu->addAction( (*i)->action() ); break; case RenderPlugin::PanelRenderType: m_infoBoxesMenu->addAction( (*i)->action() ); break; case RenderPlugin::OnlineRenderType: m_onlineServicesMenu->addAction( (*i)->action() ); break; case RenderPlugin::ThemeRenderType: themeActions.append( (*i)->action() ); break; default: mDebug() << "No menu entry created for plugin with unknown render type:" << (*i)->nameId(); break; } } m_viewMenu->addMenu( m_infoBoxesMenu ); m_viewMenu->addMenu( m_onlineServicesMenu ); m_viewMenu->addActions( themeActions ); m_viewMenu->addAction( m_showCloudsAction ); m_viewMenu->addSeparator(); m_viewMenu->addAction(m_controlSunAction); m_viewMenu->addAction(m_controlTimeAction); } void MainWindow::createBookmarksListMenu( QMenu *bookmarksListMenu, const GeoDataContainer *container ) { //m_bookmarksListMenu->clear(); QVector bookmarks = container->placemarkList(); for ( const GeoDataPlacemark *placemark: bookmarks ) { QAction *bookmarkAction = new QAction( placemark->name(), this ); QVariant var; const GeoDataLookAt* lookAt = placemark->lookAt(); if ( !lookAt ) { GeoDataCoordinates coordinates = placemark->coordinate(); GeoDataLookAt coordinateToLookAt; coordinateToLookAt.setCoordinates( coordinates ); coordinateToLookAt.setRange( marbleWidget()->lookAt().range() ); var.setValue( coordinateToLookAt ); } else { var.setValue( *lookAt ); } bookmarkAction->setData( var ); bookmarksListMenu->addAction( bookmarkAction ); } } void MainWindow::createBookmarkMenu() { m_bookmarkMenu->clear(); m_bookmarkMenu->addAction( m_addBookmarkAction ); m_bookmarkMenu->addAction( m_toggleBookmarkDisplayAction ); m_toggleBookmarkDisplayAction->setChecked( m_controlView->marbleModel()->bookmarkManager()->document()->isVisible() ); m_bookmarkMenu->addAction( m_setHomeAction ); m_bookmarkMenu->addAction( m_manageBookmarksAction ); m_bookmarkMenu->addSeparator(); m_bookmarkMenu->addAction( QIcon(QStringLiteral(":/icons/go-home.png")), tr("&Home"), m_controlView->marbleWidget(), SLOT(goHome()) ); createFolderList( m_bookmarkMenu, m_controlView->marbleModel()->bookmarkManager()->document() ); } void MainWindow::createFolderList( QMenu *bookmarksListMenu, const GeoDataContainer *container ) { QVector folders = container->folderList(); if ( folders.size() == 1 && folders.first()->name() == tr("Default")) { createBookmarksListMenu( bookmarksListMenu, folders.first() ); } else { for ( const GeoDataFolder *folder: folders ) { QMenu *subMenu = bookmarksListMenu->addMenu(QIcon(QStringLiteral(":/icons/folder-bookmark.png")), folder->name()); createFolderList( subMenu, folder ); connect( subMenu, SIGNAL(triggered(QAction*)), this, SLOT(lookAtBookmark(QAction*)) ); } } createBookmarksListMenu( bookmarksListMenu, container ); connect( bookmarksListMenu, SIGNAL(triggered(QAction*)), this, SLOT(lookAtBookmark(QAction*)) ); } void MainWindow::lookAtBookmark( QAction *action) { if ( action->data().isNull() ) { return; } GeoDataLookAt temp = qvariant_cast( action->data() ) ; m_controlView->marbleWidget()->flyTo( temp ) ; mDebug() << " looking at bookmark having longitude : "<< temp.longitude(GeoDataCoordinates::Degree) << " latitude : "<< temp.latitude(GeoDataCoordinates::Degree) << " distance : " << temp.range(); } void MainWindow::manageBookmarks() { MarbleModel * const model = m_controlView->marbleModel(); QPointer dialog = new BookmarkManagerDialog( model, this ); dialog->exec(); delete dialog; } void MainWindow::setHome() { MarbleWidget *widget = m_controlView->marbleWidget(); widget->model()->setHome( widget->centerLongitude(), widget->centerLatitude(), widget->zoom() ); } void MainWindow::openEditBookmarkDialog() { MarbleWidget *widget = m_controlView->marbleWidget(); QPointer dialog = new EditBookmarkDialog( widget->model()->bookmarkManager(), widget ); dialog->setMarbleWidget( widget ); dialog->setCoordinates( widget->lookAt().coordinates() ); dialog->setRange( widget->lookAt().range() ); dialog->setReverseGeocodeName(); if ( dialog->exec() == QDialog::Accepted ) { widget->model()->bookmarkManager()->addBookmark( dialog->folder(), dialog->bookmark() ); } delete dialog; } void MainWindow::createPluginMenus() { // Remove and delete toolbars if they exist while( !m_pluginToolbars.isEmpty() ) { QToolBar* tb = m_pluginToolbars.takeFirst(); this->removeToolBar(tb); tb->deleteLater(); } // Do not create too many menu entries on a MID // FIXME: Set up another way of switching the plugins on and off. if( MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ) { return; } //remove and delete old menus if they exist while( !m_pluginMenus.isEmpty() ) { m_viewMenu->removeAction( m_pluginMenus.takeFirst() ); } QList renderPluginList = m_controlView->marbleWidget()->renderPlugins(); QList::const_iterator i = renderPluginList.constBegin(); QList::const_iterator const end = renderPluginList.constEnd(); for (; i != end; ++i ) { // menus const QList *tmp_actionGroups = (*i)->actionGroups(); if ((*i)->enabled() && tmp_actionGroups && (*i)->nameId() != QLatin1String("annotation")) { for( QActionGroup *ag: *tmp_actionGroups ) { if( !ag->actions().isEmpty() ) { m_pluginMenus.append( m_viewMenu->addSeparator() ); } for( QAction *action: ag->actions() ) { m_viewMenu->addAction( action ); m_pluginMenus.append( action ); } } } // toolbars const QList *tmp_toolbarActionGroups = (*i)->toolbarActionGroups(); if ( (*i)->enabled() && tmp_toolbarActionGroups ) { QToolBar* toolbar = new QToolBar(this); toolbar->setObjectName(QLatin1String("plugin-toolbar-") + (*i)->nameId()); for( QActionGroup* ag: *tmp_toolbarActionGroups ) { toolbar->addActions( ag->actions() ); if ( tmp_toolbarActionGroups->last() != ag ) { toolbar->addSeparator(); } } m_pluginToolbars.append( toolbar ); this->addToolBar( toolbar ); } } // FIXME: load the menus once the method has been settled on } void MainWindow::createStatusBar() { statusBar()->showMessage(tr("Ready")); statusBar()->hide(); } void MainWindow::openMapDialog() { QPointer dialog( new MapThemeDownloadDialog( m_controlView->marbleWidget() ) ); dialog->exec(); delete dialog; } void MainWindow::exportMapScreenShot() { QString fileName = QFileDialog::getSaveFileName(this, tr("Export Map"), // krazy:exclude=qclasses QDir::homePath(), tr("Images (*.jpg *.png)")); if ( !fileName.isEmpty() ) { // Take the case into account where no file format is indicated const char * format = nullptr; if ( !fileName.endsWith(QLatin1String( "png" ), Qt::CaseInsensitive) && !fileName.endsWith(QLatin1String( "jpg" ), Qt::CaseInsensitive) ) { format = "JPG"; } QPixmap mapPixmap = m_controlView->mapScreenShot(); bool success = mapPixmap.save( fileName, format ); if ( !success ) { QMessageBox::warning(this, tr("Marble"), // krazy:exclude=qclasses tr( "An error occurred while trying to save the file.\n" ), QMessageBox::Ok); } } } void MainWindow::showFullScreen( bool isChecked ) { if ( isChecked ) { setWindowState( windowState() | Qt::WindowFullScreen ); // set } else { setWindowState( windowState() & ~Qt::WindowFullScreen ); // reset } m_fullScreenAction->setChecked( isChecked ); // Sync state with the GUI } void MainWindow::copyCoordinates() { qreal lon = m_controlView->marbleWidget()->centerLongitude(); qreal lat = m_controlView->marbleWidget()->centerLatitude(); QString positionString = GeoDataCoordinates( lon, lat, 0.0, GeoDataCoordinates::Degree ).toString(); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText( positionString ); } void MainWindow::copyMap() { QPixmap mapPixmap = m_controlView->mapScreenShot(); QClipboard *clipboard = QApplication::clipboard(); clipboard->setPixmap( mapPixmap ); } void MainWindow::showStatusBar( bool isChecked ) { if ( isChecked ) { statusBar()->show(); } else { statusBar()->hide(); } m_statusBarAction->setChecked( isChecked ); // Sync state with the GUI } void MainWindow::showClouds( bool isChecked ) { m_controlView->marbleWidget()->setShowClouds( isChecked ); m_showCloudsAction->setChecked( isChecked ); // Sync state with the GUI } void MainWindow::showBookmarks( bool show ) { m_controlView->marbleModel()->bookmarkManager()->setShowBookmarks( show ); m_toggleBookmarkDisplayAction->setChecked( show ); // Sync state with the GUI } void MainWindow::workOffline( bool offline ) { m_controlView->setWorkOffline( offline ); m_workOfflineAction->setChecked( offline ); // Sync state with the GUI } void MainWindow::lockPosition( bool isChecked ) { QList floatItemList = m_controlView->marbleWidget()->floatItems(); QList::const_iterator i = floatItemList.constBegin(); QList::const_iterator const end = floatItemList.constEnd(); for (; i != end; ++i ) { // Locking one would suffice as it affects all. // Nevertheless go through all. (*i)->setPositionLocked(isChecked); } } void MainWindow::controlSun() { if (!m_sunControlDialog) { m_sunControlDialog = new SunControlWidget( m_controlView->marbleWidget(), this ); connect( m_sunControlDialog, SIGNAL(showSun(bool)), this, SLOT (showSun(bool)) ); } m_sunControlDialog->show(); m_sunControlDialog->raise(); m_sunControlDialog->activateWindow(); } void MainWindow::controlTime() { if ( !m_timeControlDialog ) { m_timeControlDialog = new TimeControlWidget( m_controlView->marbleModel()->clock() ); } /* m_timeControlDialog is a modeless dialog so that user may adjust time and interact with main application simultaneously.*/ m_timeControlDialog->show(); m_timeControlDialog->raise(); m_timeControlDialog->activateWindow(); } void MainWindow::showSun( bool active ) { m_controlView->marbleWidget()->setShowSunShading( active ); } void MainWindow::reload() { m_controlView->marbleWidget()->reloadMap(); } void MainWindow::enterWhatsThis() { QWhatsThis::enterWhatsThisMode(); } void MainWindow::aboutMarble() { MarbleAboutDialog dlg(this); dlg.setApplicationTitle( tr( "Marble Virtual Globe %1" ).arg( ControlView::applicationVersion() ) ); dlg.exec(); } void MainWindow::handbook() { const QString code = MarbleLocale::languageCode(); QUrl handbookLocation(QLatin1String("https://docs.kde.org/stable/") + code + QLatin1String("/kdeedu/marble/index.html")); // TODO: this logic seems broken. Should that check "code.isEmpty()" instead? // and how do we know there is a doc for the code? if ( handbookLocation.isEmpty() ) handbookLocation = QUrl("https://docs.kde.org/stable/en/kdeedu/marble/index.html"); if( !QDesktopServices::openUrl( handbookLocation ) ) qDebug() << "URL not opened"; } void MainWindow::openForum() { QUrl forumLocation("https://forum.kde.org/viewforum.php?f=217"); if( !QDesktopServices::openUrl( forumLocation ) ) { mDebug() << "Failed to open URL " << forumLocation.toString(); } } void MainWindow::showPosition( const QString& position ) { m_position = position; updateStatusBar(); } void MainWindow::showDistance( const QString& distance ) { m_distance = distance; updateStatusBar(); } void MainWindow::showZoom( int zoom ) { m_zoom = QString::number( zoom ); updateStatusBar(); } void MainWindow::showDateTime() { m_clock = QLocale().toString( m_controlView->marbleModel()->clockDateTime().addSecs( m_controlView->marbleModel()->clockTimezone() ), QLocale::ShortFormat ); updateStatusBar(); } void MainWindow::updateStatusBar() { if ( m_positionLabel ) m_positionLabel->setText(tr("Position: %1").arg(m_position)); if ( m_distanceLabel ) m_distanceLabel->setText(tr("Altitude: %1").arg(m_distance)); if ( m_zoomLabel ) m_zoomLabel->setText(tr("Zoom: %1").arg(m_zoom)); if ( m_clockLabel ) m_clockLabel->setText(tr("Time: %1").arg(m_clock)); switch ( m_configDialog->angleUnit() ) { case DMSDegree: m_dmsDegreeAction->setChecked( true ); break; case DecimalDegree: m_decimalDegreeAction->setChecked( true ); break; case UTM: m_utmAction->setChecked( true ); break; } } void MainWindow::openFile() { const PluginManager *const pluginManager = m_controlView->marbleModel()->pluginManager(); QStringList allFileExtensions; QStringList filters; for ( const ParseRunnerPlugin *plugin: pluginManager->parsingRunnerPlugins() ) { if (plugin->nameId() == QLatin1String("Cache")) continue; const QStringList fileExtensions = plugin->fileExtensions().replaceInStrings( QRegExp( "^" ), "*." ); const QString filter = plugin->fileFormatDescription() + QLatin1String(" (") + fileExtensions.join(QLatin1Char(' ')) + QLatin1Char(')'); filters << filter; allFileExtensions << fileExtensions; } allFileExtensions.sort(); // sort since file extensions are visible under Windows const QString allFileTypes = tr("All Supported Files") + QLatin1String(" (") + allFileExtensions.join(QLatin1Char(' ')) + QLatin1Char(')'); filters.sort(); filters.prepend( allFileTypes ); const QString filter = filters.join( ";;" ); QStringList fileNames = QFileDialog::getOpenFileNames( this, tr( "Open File" ), m_lastFileOpenPath, filter ); if ( !fileNames.isEmpty() ) { const QString firstFile = fileNames.first(); m_lastFileOpenPath = QFileInfo( firstFile ).absolutePath(); } for( const QString &fileName: fileNames ) { m_controlView->marbleModel()->addGeoDataFile( fileName ); } } void MainWindow::setupStatusBar() { statusBar()->setSizeGripEnabled( true ); statusBar()->setContextMenuPolicy( Qt::ActionsContextMenu ); statusBar()->addAction( m_toggleTileLevelAction ); QMenu *angleDisplayUnitMenu = new QMenu(this); angleDisplayUnitMenu->addActions( m_angleDisplayUnitActionGroup->actions() ); QAction *angleDisplayUnitMenuAction = new QAction( tr("&Angle Display Unit"), statusBar() ); angleDisplayUnitMenuAction->setMenu( angleDisplayUnitMenu ); statusBar()->addAction( angleDisplayUnitMenuAction ); setupDownloadProgressBar(); m_positionLabel = new QLabel( ); m_positionLabel->setIndent( 5 ); // UTM syntax is used in the template string, as it is longer than the lon/lat one QString templatePositionString = tr("Position: %1").arg(QLatin1String(" 00Z 000000.00 m E, 00000000.00 m N_")); int maxPositionWidth = fontMetrics().boundingRect(templatePositionString).width() + 2 * m_positionLabel->margin() + 2 * m_positionLabel->indent(); m_positionLabel->setFixedWidth( maxPositionWidth ); statusBar()->addPermanentWidget ( m_positionLabel ); m_distanceLabel = new QLabel( ); m_distanceLabel->setIndent( 5 ); QString templateDistanceString = tr("Altitude: %1").arg(QLatin1String(" 00.000,0 mu")); int maxDistanceWidth = fontMetrics().boundingRect(templateDistanceString).width() + 2 * m_distanceLabel->margin() + 2 * m_distanceLabel->indent(); m_distanceLabel->setFixedWidth( maxDistanceWidth ); statusBar()->addPermanentWidget ( m_distanceLabel ); m_zoomLabel = new QLabel( ); m_zoomLabel->setIndent( 5 ); QString templateZoomString = tr("Zoom: %1").arg(QLatin1String(" 00")); int maxZoomWidth = fontMetrics().boundingRect(templateZoomString).width() + 2 * m_zoomLabel->margin() + 2 * m_zoomLabel->indent(); m_zoomLabel->setFixedWidth( maxZoomWidth ); // Not added here, but activated by the user with the context menu m_clockLabel = new QLabel( ); m_clockLabel->setIndent( 5 ); QString templateDateTimeString = tr("Time: %1").arg(QLocale().toString(QDateTime::fromString( "01:01:1000", "dd:mm:yyyy"), QLocale::ShortFormat)); int maxDateTimeWidth = fontMetrics().boundingRect( templateDateTimeString ).width() + 2 * m_clockLabel->margin() + 2 * m_clockLabel->indent(); m_clockLabel->setFixedWidth( maxDateTimeWidth ); statusBar()->addPermanentWidget ( m_clockLabel ); connect( marbleWidget(), SIGNAL(mouseMoveGeoPosition(QString)), this, SLOT(showPosition(QString)) ); connect( marbleWidget(), SIGNAL(distanceChanged(QString)), this, SLOT(showDistance(QString)) ); connect( marbleWidget(), SIGNAL(tileLevelChanged(int)), this, SLOT(showZoom(int)) ); connect( m_controlView->marbleModel()->clock(), SIGNAL(timeChanged()), this, SLOT(showDateTime()) ); updateStatusBar(); } void MainWindow::setupDownloadProgressBar() { m_downloadProgressBar = new QProgressBar; m_downloadProgressBar->setVisible( true ); statusBar()->addPermanentWidget( m_downloadProgressBar ); HttpDownloadManager * const downloadManager = m_controlView->marbleModel()->downloadManager(); Q_ASSERT( downloadManager ); connect( downloadManager, SIGNAL(progressChanged(int,int)), SLOT(handleProgress(int,int)) ); connect( downloadManager, SIGNAL(jobRemoved()), SLOT(removeProgressItem()) ); } void MainWindow::handleProgress( int active, int queued ){ m_downloadProgressBar->setUpdatesEnabled( false ); if ( m_downloadProgressBar->value() < 0 ) { m_downloadProgressBar->setMaximum( 1 ); m_downloadProgressBar->setValue( 0 ); m_downloadProgressBar->setVisible( true ); } else { m_downloadProgressBar->setMaximum( qMax( m_downloadProgressBar->maximum(), active + queued ) ); } m_downloadProgressBar->setUpdatesEnabled( true ); } void MainWindow::removeProgressItem(){ m_downloadProgressBar->setUpdatesEnabled( false ); m_downloadProgressBar->setValue( m_downloadProgressBar->value() + 1 ); if ( m_downloadProgressBar->value() == m_downloadProgressBar->maximum() ) { m_downloadProgressBar->reset(); m_downloadProgressBar->setVisible( false ); } m_downloadProgressBar->setUpdatesEnabled( true ); } void MainWindow::closeEvent( QCloseEvent *event ) { writeSettings(); QCloseEvent newEvent; QCoreApplication::sendEvent( m_controlView, &newEvent ); if ( newEvent.isAccepted() ) { event->accept(); } else { event->ignore(); } } QString MainWindow::readMarbleDataPath() { QSettings settings; settings.beginGroup("MarbleWidget"); const auto marbleDataPath = settings.value("marbleDataPath", "").toString(); settings.endGroup(); return marbleDataPath; } void MainWindow::readSettings(const QVariantMap& overrideSettings) { QSettings settings; settings.beginGroup("MainWindow"); resize(settings.value("size", QSize(640, 480)).toSize()); move(settings.value("pos", QPoint(200, 200)).toPoint()); showFullScreen(settings.value("fullScreen", false ).toBool()); showStatusBar(settings.value("statusBar", false ).toBool()); showZoomLevel(settings.value("showZoomLevel",false).toBool()); show(); showClouds(settings.value("showClouds", true ).toBool()); workOffline(settings.value("workOffline", false ).toBool()); m_controlView->marbleWidget()->setShowAtmosphere(settings.value("showAtmosphere", true ).toBool()); m_lastFileOpenPath = settings.value("lastFileOpenDir", QDir::homePath()).toString(); showBookmarks( settings.value( "showBookmarks", true ).toBool() ); restoreState( settings.value("windowState").toByteArray() ); settings.endGroup(); setUpdatesEnabled(false); settings.beginGroup("MarbleWidget"); QString mapThemeId; const QVariantMap::ConstIterator mapThemeIdIt = overrideSettings.find(QLatin1String("mapTheme")); if ( mapThemeIdIt != overrideSettings.constEnd() ) { mapThemeId = mapThemeIdIt.value().toString(); } else { mapThemeId = settings.value("mapTheme", m_controlView->defaultMapThemeId() ).toString(); } mDebug() << Q_FUNC_INFO << "mapThemeId:" << mapThemeId; m_controlView->marbleWidget()->setMapThemeId( mapThemeId ); m_controlView->marbleWidget()->setProjection( (Projection)(settings.value("projection", Spherical ).toInt()) ); // Set home position m_controlView->marbleModel()->setHome( settings.value("homeLongitude", 9.4).toDouble(), settings.value("homeLatitude", 54.8).toDouble(), settings.value("homeZoom", 1050 ).toInt() ); // Center on/Distance const QVariantMap::ConstIterator distanceIt = overrideSettings.find(QLatin1String("distance")); const bool isDistanceOverwritten = (distanceIt != overrideSettings.constEnd()); const QVariantMap::ConstIterator lonLatIt = overrideSettings.find(QLatin1String("lonlat")); if ( lonLatIt != overrideSettings.constEnd() ) { const QVariantList lonLat = lonLatIt.value().toList(); m_controlView->marbleWidget()->centerOn( lonLat.at(0).toDouble(), lonLat.at(1).toDouble() ); } else { switch ( m_configDialog->onStartup() ) { case Marble::LastLocationVisited: m_controlView->marbleWidget()->centerOn( settings.value("quitLongitude", 0.0).toDouble(), settings.value("quitLatitude", 0.0).toDouble() ); if (! isDistanceOverwritten) { // set default radius to 1350 (Atlas theme's "sharp" radius) m_controlView->marbleWidget()->setRadius( settings.value("quitRadius", 1350).toInt() ); } break; case Marble::ShowHomeLocation: m_controlView->marbleWidget()->goHome(); break; default: break; } } if (isDistanceOverwritten) { m_controlView->marbleWidget()->setDistance(distanceIt.value().toDouble()); } // Geo URI parsing QString geoUriString = qvariant_cast( overrideSettings.value("geo-uri", "")); if ( !geoUriString.isEmpty() ) { m_controlView->openGeoUri( geoUriString ); } bool isLocked = settings.value( "lockFloatItemPositions", false ).toBool(); m_lockFloatItemsAction->setChecked( isLocked ); lockPosition(isLocked); settings.endGroup(); settings.beginGroup( "Sun" ); m_controlView->marbleWidget()->setShowSunShading( settings.value( "showSun", false ).toBool() ); m_controlView->marbleWidget()->setShowCityLights( settings.value( "showCitylights", false ).toBool() ); m_controlView->marbleWidget()->setLockToSubSolarPoint( settings.value( "lockToSubSolarPoint", false ).toBool() ); m_controlView->marbleWidget()->setSubSolarPointIconVisible( settings.value( "subSolarPointIconVisible", false ).toBool() ); settings.endGroup(); settings.beginGroup( "Time" ); if( settings.value( "systemTime", "true" ).toBool() == true ) { /* nothing to do */ } else if( settings.value( "lastSessionTime", "true" ).toBool() == true ) { m_controlView->marbleModel()->setClockDateTime( settings.value( "dateTime" ).toDateTime() ); m_controlView->marbleModel()->setClockSpeed( settings.value( "speedSlider", 1 ).toInt() ); } settings.endGroup(); setUpdatesEnabled(true); // Load previous route settings settings.beginGroup( "Routing" ); { RoutingManager *const routingManager = m_controlView->marbleModel()->routingManager(); routingManager->readSettings(); bool const startupWarning = settings.value( "showGuidanceModeStartupWarning", QVariant( true ) ).toBool(); routingManager->setShowGuidanceModeStartupWarning( startupWarning ); routingManager->setLastOpenPath( settings.value( "lastRouteOpenPath", QDir::homePath() ).toString() ); routingManager->setLastSavePath( settings.value( "lastRouteSavePath", QDir::homePath() ).toString() ); QColor tempColor; tempColor = QColor( settings.value( "routeColorStandard", Oxygen::skyBlue4.name() ).toString() ); tempColor.setAlpha( settings.value( "routeAlphaStandard", 200 ).toInt() ); routingManager->setRouteColorStandard( tempColor ); tempColor = QColor( settings.value( "routeColorHighlighted", Oxygen::skyBlue1.name() ).toString() ); tempColor.setAlpha( settings.value( "routeAlphaHighlighted", 200 ).toInt() ); routingManager->setRouteColorHighlighted( tempColor ); tempColor = QColor( settings.value( "routeColorAlternative", Oxygen::aluminumGray4.name() ).toString() ); tempColor.setAlpha( settings.value( "routeAlphaAlternative", 200 ).toInt() ); routingManager->setRouteColorAlternative( tempColor ); } settings.endGroup(); settings.beginGroup( "Routing Profile" ); if ( settings.contains( "Num" ) ) { QList profiles; int numProfiles = settings.value( "Num", 0 ).toInt(); for ( int i = 0; i < numProfiles; ++i ) { settings.beginGroup( QString( "Profile %0" ).arg(i) ); QString name = settings.value( "Name", tr( "Unnamed" ) ).toString(); RoutingProfile profile( name ); for ( const QString& pluginName: settings.childGroups() ) { settings.beginGroup( pluginName ); profile.pluginSettings().insert( pluginName, QHash() ); for ( const QString& key: settings.childKeys() ) { if (key != QLatin1String("Enabled")) { profile.pluginSettings()[ pluginName ].insert( key, settings.value( key ) ); } } settings.endGroup(); } profiles << profile; settings.endGroup(); } m_controlView->marbleModel()->routingManager()->profilesModel()->setProfiles( profiles ); } else { m_controlView->marbleModel()->routingManager()->profilesModel()->loadDefaultProfiles(); } int const profileIndex = settings.value( "currentIndex", 0 ).toInt(); if ( profileIndex >= 0 && profileIndex < m_controlView->marbleModel()->routingManager()->profilesModel()->rowCount() ) { RoutingProfile profile = m_controlView->marbleModel()->routingManager()->profilesModel()->profiles().at( profileIndex ); m_controlView->marbleModel()->routingManager()->routeRequest()->setRoutingProfile( profile ); } settings.endGroup(); settings.beginGroup( "Plugins"); PositionTracking* tracking = m_controlView->marbleModel()->positionTracking(); tracking->readSettings(); QString positionProvider = settings.value( "activePositionTrackingPlugin", QString() ).toString(); if ( !positionProvider.isEmpty() ) { const PluginManager* pluginManager = m_controlView->marbleModel()->pluginManager(); for( const PositionProviderPlugin* plugin: pluginManager->positionProviderPlugins() ) { if ( plugin->nameId() == positionProvider ) { PositionProviderPlugin* instance = plugin->newInstance(); tracking->setPositionProviderPlugin( instance ); break; } } } settings.endGroup(); settings.beginGroup( "Tracking" ); if ( settings.contains( "autoCenter" ) || settings.contains( "recenterMode" ) ) { CurrentLocationWidget* trackingWidget = m_controlView->currentLocationWidget(); Q_ASSERT( trackingWidget ); trackingWidget->setRecenterMode( settings.value( "recenterMode", 0 ).toInt() ); trackingWidget->setAutoZoom( settings.value( "autoZoom", false ).toBool() ); trackingWidget->setTrackVisible( settings.value( "trackVisible", true ).toBool() ); trackingWidget->setLastOpenPath( settings.value( "lastTrackOpenPath", QDir::homePath() ).toString() ); trackingWidget->setLastSavePath( settings.value( "lastTrackSavePath", QDir::homePath() ).toString() ); } settings.endGroup(); // The config dialog has to read settings. m_configDialog->readSettings(); settings.beginGroup( "Navigation" ); m_controlView->setExternalMapEditor( settings.value( "externalMapEditor", "" ).toString() ); settings.endGroup(); settings.beginGroup( "CloudSync" ); CloudSyncManager* cloudSyncManager = m_controlView->cloudSyncManager(); cloudSyncManager->setOwncloudCredentials( settings.value( "owncloudServer", "" ).toString(), settings.value( "owncloudUsername", "" ).toString(), settings.value( "owncloudPassword", "" ).toString() ); cloudSyncManager->setSyncEnabled( settings.value( "enableSync", false ).toBool() ); cloudSyncManager->routeSyncManager()->setRouteSyncEnabled( settings.value( "syncRoutes", true ).toBool() ); cloudSyncManager->bookmarkSyncManager()->setBookmarkSyncEnabled( settings.value( "syncBookmarks", true ).toBool() ); settings.endGroup(); } void MainWindow::writeSettings() { QSettings settings; settings.beginGroup( "MainWindow" ); settings.setValue( "size", size() ); settings.setValue( "pos", pos() ); settings.setValue( "fullScreen", m_fullScreenAction->isChecked() ); settings.setValue( "statusBar", m_statusBarAction->isChecked() ); settings.setValue( "showZoomLevel", m_toggleTileLevelAction->isChecked() ); settings.setValue( "showClouds", m_showCloudsAction->isChecked() ); settings.setValue( "workOffline", m_workOfflineAction->isChecked() ); settings.setValue( "showAtmosphere", m_controlView->marbleWidget()->showAtmosphere() ); settings.setValue( "lastFileOpenDir", m_lastFileOpenPath ); settings.setValue( "showBookmarks", m_toggleBookmarkDisplayAction->isChecked() ); settings.setValue( "windowState", saveState() ); settings.endGroup(); settings.beginGroup( "MarbleWidget" ); // Get the 'home' values from the widget and store them in the settings. qreal homeLon = 0; qreal homeLat = 0; int homeZoom = 0; m_controlView->marbleModel()->home( homeLon, homeLat, homeZoom ); QString mapTheme = m_controlView->marbleWidget()->mapThemeId(); int projection = (int)( m_controlView->marbleWidget()->projection() ); settings.setValue( "homeLongitude", homeLon ); settings.setValue( "homeLatitude", homeLat ); settings.setValue( "homeZoom", homeZoom ); settings.setValue( "mapTheme", mapTheme ); settings.setValue( "projection", projection ); // Get the 'quit' values from the widget and store them in the settings. qreal quitLon = m_controlView->marbleWidget()->centerLongitude(); qreal quitLat = m_controlView->marbleWidget()->centerLatitude(); const int quitRadius = m_controlView->marbleWidget()->radius(); settings.setValue( "quitLongitude", quitLon ); settings.setValue( "quitLatitude", quitLat ); settings.setValue( "quitRadius", quitRadius ); settings.setValue( "lockFloatItemPositions", m_lockFloatItemsAction->isChecked() ); settings.endGroup(); settings.beginGroup( "Sun" ); settings.setValue( "showSun", m_controlView->marbleWidget()->showSunShading() ); settings.setValue( "showCitylights", m_controlView->marbleWidget()->showCityLights() ); settings.setValue( "lockToSubSolarPoint", m_controlView->marbleWidget()->isLockedToSubSolarPoint() ); settings.setValue( "subSolarPointIconVisible", m_controlView->marbleWidget()->isSubSolarPointIconVisible() ); settings.endGroup(); settings.beginGroup( "Time" ); settings.setValue( "dateTime", m_controlView->marbleModel()->clockDateTime() ); settings.setValue( "speedSlider", m_controlView->marbleModel()->clockSpeed() ); settings.endGroup(); settings.beginGroup( "Routing Profile" ); QList profiles = m_controlView->marbleWidget() ->model()->routingManager()->profilesModel()->profiles(); settings.setValue( "Num", profiles.count() ); for ( int i = 0; i < profiles.count(); ++i ) { settings.beginGroup( QString( "Profile %0" ).arg(i) ); const RoutingProfile& profile = profiles.at( i ); settings.setValue( "Name", profile.name() ); for ( const QString& pluginName: settings.childGroups() ) { settings.beginGroup( pluginName ); settings.remove(QString()); //remove all keys settings.endGroup(); } for ( const QString &key: profile.pluginSettings().keys() ) { settings.beginGroup( key ); settings.setValue( "Enabled", true ); for ( const QString& settingKey: profile.pluginSettings()[ key ].keys() ) { Q_ASSERT(settingKey != QLatin1String("Enabled")); settings.setValue( settingKey, profile.pluginSettings()[ key ][ settingKey ] ); } settings.endGroup(); } settings.endGroup(); } RoutingProfile const profile = m_controlView->marbleWidget()->model()->routingManager()->routeRequest()->routingProfile(); settings.setValue( "currentIndex", profiles.indexOf( profile ) ); settings.endGroup(); settings.beginGroup( "Plugins"); QString positionProvider; PositionTracking* tracking = m_controlView->marbleModel()->positionTracking(); tracking->writeSettings(); if ( tracking->positionProviderPlugin() ) { positionProvider = tracking->positionProviderPlugin()->nameId(); } settings.setValue( "activePositionTrackingPlugin", positionProvider ); settings.endGroup(); settings.beginGroup( "Tracking" ); CurrentLocationWidget* trackingWidget = m_controlView->currentLocationWidget(); if ( trackingWidget ) { // Can be null due to lazy initialization settings.setValue( "recenterMode", trackingWidget->recenterMode() ); settings.setValue( "autoZoom", trackingWidget->autoZoom() ); settings.setValue( "trackVisible", trackingWidget->trackVisible() ); settings.setValue( "lastTrackOpenPath", trackingWidget->lastOpenPath() ); settings.setValue( "lastTrackSavePath", trackingWidget->lastSavePath() ); } settings.endGroup(); // The config dialog has to write settings. m_configDialog->writeSettings(); // Store current route settings settings.beginGroup( "Routing" ); { RoutingManager *const routingManager = m_controlView->marbleModel()->routingManager(); routingManager->writeSettings(); settings.setValue( "showGuidanceModeStartupWarning", routingManager->showGuidanceModeStartupWarning() ); settings.setValue( "lastRouteOpenPath", routingManager->lastOpenPath() ); settings.setValue( "lastRouteSavePath", routingManager->lastSavePath() ); settings.setValue( "routeColorStandard", routingManager->routeColorStandard().name() ); settings.setValue( "routeAlphaStandard", routingManager->routeColorStandard().alpha() ); settings.setValue( "routeColorHighlighted", routingManager->routeColorHighlighted().name() ); settings.setValue( "routeAlphaHighlighted", routingManager->routeColorHighlighted().alpha() ); settings.setValue( "routeColorAlternative", routingManager->routeColorAlternative().name() ); settings.setValue( "routeAlphaAlternative", routingManager->routeColorAlternative().alpha() ); } settings.endGroup(); settings.beginGroup( "Navigation"); settings.setValue( "externalMapEditor", m_controlView->externalMapEditor() ); settings.endGroup(); } void MainWindow::editSettings() { // Show the settings dialog. m_configDialog->show(); m_configDialog->raise(); m_configDialog->activateWindow(); } void MainWindow::updateSettings() { mDebug() << Q_FUNC_INFO << "Updating Settings ..."; // FIXME: Font doesn't get updated instantly. m_controlView->marbleWidget()->setDefaultFont( m_configDialog->mapFont() ); m_controlView->marbleWidget()->setMapQualityForViewContext( m_configDialog->stillQuality(), Marble::Still ); m_controlView->marbleWidget()->setMapQualityForViewContext( m_configDialog->animationQuality(), Marble::Animation ); m_controlView->marbleWidget()->setDefaultAngleUnit( m_configDialog->angleUnit() ); MarbleGlobal::getInstance()->locale()->setMeasurementSystem( m_configDialog->measurementSystem() ); m_distance = m_controlView->marbleWidget()->distanceString(); updateStatusBar(); m_controlView->marbleWidget()->setAnimationsEnabled( m_configDialog->animateTargetVoyage() ); m_controlView->marbleWidget()->inputHandler()->setInertialEarthRotationEnabled( m_configDialog->inertialEarthRotation() ); + m_controlView->marbleWidget()->inputHandler()->setMouseViewRotationEnabled( m_configDialog->mouseViewRotation() ); if ( !m_configDialog->externalMapEditor().isEmpty() ) { m_controlView->setExternalMapEditor( m_configDialog->externalMapEditor() ); } // Cache m_controlView->marbleModel()->setPersistentTileCacheLimit( m_configDialog->persistentTileCacheLimit() * 1024 ); m_controlView->marbleWidget()->setVolatileTileCacheLimit( m_configDialog->volatileTileCacheLimit() * 1024 ); /* m_controlView->marbleWidget()->setProxy( m_configDialog->proxyUrl(), m_configDialog->proxyPort(), m_configDialog->user(), m_configDialog->password() ); */ CloudSyncManager* cloudSyncManager = m_controlView->cloudSyncManager(); cloudSyncManager->setOwncloudCredentials( m_configDialog->owncloudServer(), m_configDialog->owncloudUsername(), m_configDialog->owncloudPassword() ); cloudSyncManager->setSyncEnabled( m_configDialog->syncEnabled() ); cloudSyncManager->routeSyncManager()->setRouteSyncEnabled( m_configDialog->syncRoutes() ); cloudSyncManager->bookmarkSyncManager()->setBookmarkSyncEnabled( m_configDialog->syncBookmarks() ); m_controlView->marbleWidget()->update(); } void MainWindow::showDownloadRegionDialog() { if ( !m_downloadRegionDialog ) { m_downloadRegionDialog = new DownloadRegionDialog( m_controlView->marbleWidget(), m_controlView ); // it might be tempting to move the connects to DownloadRegionDialog's "accepted" and // "applied" signals, be aware that the "hidden" signal might be come before the "accepted" // signal, leading to a too early disconnect. connect( m_downloadRegionDialog, SIGNAL(accepted()), SLOT(downloadRegion())); connect( m_downloadRegionDialog, SIGNAL(applied()), SLOT(downloadRegion())); } // FIXME: get allowed range from current map theme m_downloadRegionDialog->setAllowedTileLevelRange( 0, 16 ); m_downloadRegionDialog->setSelectionMethod( DownloadRegionDialog::VisibleRegionMethod ); ViewportParams const * const viewport = m_controlView->marbleWidget()->viewport(); m_downloadRegionDialog->setSpecifiedLatLonAltBox( viewport->viewLatLonAltBox() ); m_downloadRegionDialog->setVisibleLatLonAltBox( viewport->viewLatLonAltBox() ); m_downloadRegionDialog->show(); m_downloadRegionDialog->raise(); m_downloadRegionDialog->activateWindow(); } void MainWindow::downloadRegion() { Q_ASSERT( m_downloadRegionDialog ); QVector const pyramid = m_downloadRegionDialog->region(); if ( !pyramid.isEmpty() ) { m_controlView->marbleWidget()->downloadRegion( pyramid ); } } void MainWindow::printMapScreenShot() { #ifndef QT_NO_PRINTER QPrinter printer( QPrinter::HighResolution ); QPointer printDialog = new QPrintDialog( &printer, this ); m_controlView->printMapScreenShot( printDialog ); delete printDialog; #endif } void MainWindow::updateMapEditButtonVisibility( const QString &mapTheme ) { Q_ASSERT( m_osmEditAction ); QStringList osmThemes = QStringList() << "earth/openstreetmap/openstreetmap.dgml" << "earth/hikebikemap/hikebikemap.dgml" << "earth/opencyclemap/opencyclemap.dgml" << "earth/public-transport/public-transport.dgml" << "earth/openseamap/openseamap.dgml" << "earth/vectorosm/vectorosm.dgml"; m_osmEditAction->setVisible(osmThemes.contains(mapTheme)); } void MainWindow::showMovieCaptureDialog() { if (m_movieCaptureDialog == nullptr) { m_movieCaptureDialog = new MovieCaptureDialog(m_controlView->marbleWidget(), m_controlView->marbleWidget()); connect( m_movieCaptureDialog, SIGNAL(started()), this, SLOT(changeRecordingState())); } m_movieCaptureDialog->show(); } void MainWindow::stopRecording() { if ( m_movieCaptureDialog ) { m_movieCaptureDialog->stopRecording(); changeRecordingState(); } } void MainWindow::changeRecordingState() { m_recordMovieAction->setEnabled( !m_recordMovieAction->isEnabled() ); m_stopRecordingAction->setEnabled( !m_stopRecordingAction->isEnabled() ); } void MainWindow::updateWindowTitle() { GeoSceneDocument *theme = m_controlView->marbleModel()->mapTheme(); setWindowTitle(theme ? theme->head()->name() : QString()); } void MainWindow::showMapWizard() { QPointer mapWizard = new MapWizard(); QSettings settings; settings.beginGroup( "MapWizard" ); mapWizard->setWmsServers( settings.value( "wmsServers" ).toStringList() ); mapWizard->setStaticUrlServers( settings.value( "staticUrlServers" ).toStringList() ); settings.endGroup(); mapWizard->exec(); settings.beginGroup( "MapWizard" ); settings.setValue( "wmsServers", mapWizard->wmsServers() ); settings.setValue( "staticUrlServers", mapWizard->staticUrlServers() ); settings.endGroup(); mapWizard->deleteLater(); } void MainWindow::showZoomLevel(bool show) { if ( show ) { m_zoomLabel->show(); statusBar()->insertPermanentWidget( 2, m_zoomLabel ); } else { statusBar()->removeWidget( m_zoomLabel ); } // update from last modification m_toggleTileLevelAction->setChecked( show ); } void MainWindow::changeAngleDisplayUnit( QAction *action ) { m_configDialog->setAngleUnit((Marble::AngleUnit)action->data().toInt()); } void MainWindow::fallBackToDefaultTheme() { m_controlView->marbleWidget()->setMapThemeId( m_controlView->defaultMapThemeId() ); } void MainWindow::changeViewSize( QAction* action ) { if ( action->data().type() == QVariant::Size ) { if ( m_savedSize.isEmpty() ) { m_savedSize = m_controlView->size(); } m_controlView->setFixedSize( action->data().toSize() ); adjustSize(); } else { m_controlView->setMinimumSize( QSize( 0, 0 ) ); m_controlView->setMaximumSize( QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ) ); m_controlView->resize( m_savedSize ); m_controlView->setMinimumSize( m_savedSize ); adjustSize(); m_controlView->setMinimumSize( QSize( 0, 0 ) ); m_savedSize.setHeight( -1 ); } } #include "moc_QtMainWindow.cpp" diff --git a/src/bindings/python/sip/QtMarbleConfigDialog.sip b/src/bindings/python/sip/QtMarbleConfigDialog.sip index b93f49260..9d6f24c57 100644 --- a/src/bindings/python/sip/QtMarbleConfigDialog.sip +++ b/src/bindings/python/sip/QtMarbleConfigDialog.sip @@ -1,65 +1,66 @@ // Copyright 2009 Simon Edwards // Generated by twine2 // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as // published by the Free Software Foundation; either version 2, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details // You should have received a copy of the GNU Library General Public // License along with this program; if not, write to the // Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. namespace Marble { class QtMarbleConfigDialog : QDialog { %TypeHeaderCode #include %End public: explicit QtMarbleConfigDialog (Marble::MarbleWidget* marbleWidget, QWidget* parent /TransferThis/ = 0); ~QtMarbleConfigDialog (); Marble::AngleUnit angleUnit () const; Marble::MapQuality stillQuality () const; Marble::MapQuality animationQuality () const; int labelLocalization () const; QFont mapFont () const; int dragLocation () const; int onStartup () const; bool animateTargetVoyage () const; int volatileTileCacheLimit () const; int persistentTileCacheLimit () const; QString proxyUrl () const; int proxyPort () const; QString proxyUser () const; QString proxyPass () const; bool proxyType () const; bool proxyAuth () const; signals: void settingsChanged (); void clearVolatileCacheClicked (); void clearPersistentCacheClicked (); public: void readSettings (); void writeSettings (); QString externalMapEditor () const; bool systemTime () const; bool lastSessionTime () const; bool systemTimezone () const; bool UTC () const; bool customTimezone () const; int chosenTimezone () const; void initializeCustomTimezone (); QLocale::MeasurementSystem measurementSystem () const; bool inertialEarthRotation () const; + bool mouseViewRotation () const; }; }; diff --git a/src/lib/marble/MarbleInputHandler.cpp b/src/lib/marble/MarbleInputHandler.cpp index b58f91f0f..09a30410d 100644 --- a/src/lib/marble/MarbleInputHandler.cpp +++ b/src/lib/marble/MarbleInputHandler.cpp @@ -1,1010 +1,1022 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2006-2007 Torsten Rahn // Copyright 2007 Inge Wallin // Copyright 2014 Adam Dabrowski // #include "MarbleInputHandler.h" #include #include #include #include #include #include #include #include #include "kineticmodel.h" #include "MarbleGlobal.h" #include "MarbleDebug.h" #include "MarbleMap.h" #include "GeoDataCoordinates.h" #include "MarbleAbstractPresenter.h" #include "ViewportParams.h" #include "AbstractFloatItem.h" #include "AbstractDataPluginItem.h" #include "RenderPlugin.h" namespace Marble { const int TOOLTIP_START_INTERVAL = 1000; class Q_DECL_HIDDEN MarbleInputHandler::Protected { public: Protected(MarbleAbstractPresenter *marblePresenter); MarbleAbstractPresenter *const m_marblePresenter; bool m_positionSignalConnected; QTimer *m_mouseWheelTimer; Qt::MouseButtons m_disabledMouseButtons; qreal m_wheelZoomTargetDistance; bool m_panViaArrowsEnabled; bool m_inertialEarthRotation; + bool m_mouseViewRotation; int m_steps; const int m_discreteZoomSteps = 120; }; MarbleInputHandler::Protected::Protected(MarbleAbstractPresenter *marblePresenter) : m_marblePresenter( marblePresenter ), m_positionSignalConnected( false ), m_mouseWheelTimer( nullptr ), m_disabledMouseButtons( Qt::NoButton ), m_wheelZoomTargetDistance( 0.0 ), m_panViaArrowsEnabled( true ), m_inertialEarthRotation( true ), + m_mouseViewRotation( true ), m_steps(0) { } MarbleInputHandler::MarbleInputHandler(MarbleAbstractPresenter *marblePresenter) : d(new Protected(marblePresenter)) { d->m_mouseWheelTimer = new QTimer( this ); connect(d->m_mouseWheelTimer, SIGNAL(timeout()), this, SLOT(restoreViewContext())); connect(d->m_marblePresenter->map(), SIGNAL(renderPluginInitialized(RenderPlugin*)), this, SLOT(installPluginEventFilter(RenderPlugin*))); } MarbleInputHandler::~MarbleInputHandler() { delete d->m_mouseWheelTimer; delete d; } void MarbleInputHandler::setPositionSignalConnected(bool connected) { d->m_positionSignalConnected = connected; } bool MarbleInputHandler::isPositionSignalConnected() const { return d->m_positionSignalConnected; } void MarbleInputHandler::setMouseButtonPopupEnabled(Qt::MouseButton mouseButton, bool enabled) { if (enabled) { d->m_disabledMouseButtons &= ~Qt::MouseButtons(mouseButton); } else { d->m_disabledMouseButtons |= mouseButton; } } bool MarbleInputHandler::isMouseButtonPopupEnabled(Qt::MouseButton mouseButton) const { return !(d->m_disabledMouseButtons & mouseButton); } void MarbleInputHandler::setPanViaArrowsEnabled(bool enabled) { d->m_panViaArrowsEnabled = enabled; } bool MarbleInputHandler::panViaArrowsEnabled() const { return d->m_panViaArrowsEnabled; } void MarbleInputHandler::setInertialEarthRotationEnabled(bool enabled) { d->m_inertialEarthRotation = enabled; } bool MarbleInputHandler::inertialEarthRotationEnabled() const { return d->m_inertialEarthRotation; } +void MarbleInputHandler::setMouseViewRotationEnabled(bool enabled) +{ + d->m_mouseViewRotation = enabled; +} + +bool MarbleInputHandler::mouseViewRotationEnabled() const +{ + return d->m_mouseViewRotation; +} + void MarbleInputHandler::stopInertialEarthRotation() { } class Q_DECL_HIDDEN MarbleDefaultInputHandler::Private { public: Private(); ~Private(); QPixmap m_curpmtl; QPixmap m_curpmtc; QPixmap m_curpmtr; QPixmap m_curpmcr; QPixmap m_curpmcl; QPixmap m_curpmbl; QPixmap m_curpmbc; QPixmap m_curpmbr; QCursor m_arrowCur[3][3]; // Indicates if the left mouse button has been pressed already. bool m_leftPressed; // Indicates if the middle mouse button has been pressed already. bool m_midPressed; // The mouse pointer x position when the left mouse button has been pressed. int m_leftPressedX; // The mouse pointer y position when the left mouse button has been pressed. int m_leftPressedY; // The mouse pointer y position when the middle mouse button has been pressed. int m_midPressedY; int m_startingRadius; // Indicates if the right mouse button has been pressed already. bool m_rightPressed; // Point where the right mouse button has been pressed on. QPoint m_rightOrigin; // Position to calculate the heading. // Indicates previous position since mouse has been moved. QPoint m_rightPosition; // Indicates the heading when the right mouse button has been pressed // and mouse is moving. qreal m_heading; // The center longitude in radian when the left mouse button has been pressed. qreal m_leftPressedLon; // The center latitude in radian when the left mouse button has been pressed. qreal m_leftPressedLat; int m_dragThreshold; QTimer m_lmbTimer; QTimer m_pressAndHoldTimer; // Models to handle the kinetic spinning. KineticModel m_kineticSpinning; QPoint m_selectionOrigin; QPointer m_lastToolTipItem; QTimer m_toolTipTimer; QPoint m_toolTipPosition; }; MarbleDefaultInputHandler::Private::Private() : m_leftPressed(false), m_midPressed(false), m_rightPressed(false), m_heading(0), m_dragThreshold(MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen ? 15 : 3) { m_curpmtl.load(QStringLiteral(":/marble/cursor/tl.png")); m_curpmtc.load(QStringLiteral(":/marble/cursor/tc.png")); m_curpmtr.load(QStringLiteral(":/marble/cursor/tr.png")); m_curpmcr.load(QStringLiteral(":/marble/cursor/cr.png")); m_curpmcl.load(QStringLiteral(":/marble/cursor/cl.png")); m_curpmbl.load(QStringLiteral(":/marble/cursor/bl.png")); m_curpmbc.load(QStringLiteral(":/marble/cursor/bc.png")); m_curpmbr.load(QStringLiteral(":/marble/cursor/br.png")); m_arrowCur[0][0] = QCursor( m_curpmtl, 2, 2 ); m_arrowCur[1][0] = QCursor( m_curpmtc, 10, 3 ); m_arrowCur[2][0] = QCursor( m_curpmtr, 19, 2 ); m_arrowCur[0][1] = QCursor( m_curpmcl, 3, 10 ); m_arrowCur[1][1] = QCursor( Qt::OpenHandCursor ); m_arrowCur[2][1] = QCursor( m_curpmcr, 18, 10 ); m_arrowCur[0][2] = QCursor( m_curpmbl, 2, 19 ); m_arrowCur[1][2] = QCursor( m_curpmbc, 11, 18 ); m_arrowCur[2][2] = QCursor( m_curpmbr, 19, 19 ); } MarbleDefaultInputHandler::Private::~Private() { } MarbleDefaultInputHandler::MarbleDefaultInputHandler(MarbleAbstractPresenter *marblePresenter) : MarbleInputHandler(marblePresenter), d(new Private()) { d->m_toolTipTimer.setSingleShot(true); d->m_toolTipTimer.setInterval(TOOLTIP_START_INTERVAL); connect(&d->m_toolTipTimer, SIGNAL(timeout()), this, SLOT(openItemToolTip())); d->m_lmbTimer.setSingleShot(true); connect(&d->m_lmbTimer, SIGNAL(timeout()), this, SLOT(lmbTimeout())); d->m_kineticSpinning.setUpdateInterval(35); connect(&d->m_kineticSpinning, SIGNAL(positionChanged(qreal,qreal)), MarbleInputHandler::d->m_marblePresenter, SLOT(centerOn(qreal,qreal))); connect(&d->m_kineticSpinning, SIGNAL(headingChanged(qreal)), MarbleInputHandler::d->m_marblePresenter, SLOT(headingOn(qreal))); connect(&d->m_kineticSpinning, SIGNAL(finished()), SLOT(restoreViewContext())); // Left and right mouse button signals. connect(this, SIGNAL(rmbRequest(int,int)), this, SLOT(showRmbMenu(int,int))); connect(this, SIGNAL(lmbRequest(int,int)), this, SLOT(showLmbMenu(int,int))); d->m_pressAndHoldTimer.setInterval(800); d->m_pressAndHoldTimer.setSingleShot(true); connect(&d->m_pressAndHoldTimer, SIGNAL(timeout()), this, SLOT(handlePressAndHold())); } MarbleDefaultInputHandler::~MarbleDefaultInputHandler() { delete d; } void MarbleDefaultInputHandler::stopInertialEarthRotation() { d->m_kineticSpinning.stop(); } void MarbleDefaultInputHandler::lmbTimeout() { if (!selectionRubber()->isVisible()) { qreal clickedLon = 0; qreal clickedLat = 0; bool isPointOnGlobe = MarbleInputHandler::d->m_marblePresenter->map()->geoCoordinates( d->m_leftPressedX, d->m_leftPressedY, clickedLon, clickedLat, GeoDataCoordinates::Degree ); emit lmbRequest(d->m_leftPressedX, d->m_leftPressedY); /** * emit mouse click only when the clicked * position is within the globe. */ if ( isPointOnGlobe ) { emit mouseClickGeoPosition( clickedLon, clickedLat, GeoDataCoordinates::Degree ); } } } void MarbleInputHandler::restoreViewContext() { // Needs to stop the timer since it repeats otherwise. d->m_mouseWheelTimer->stop(); // Redraw the map with the quality set for Still (if necessary). d->m_marblePresenter->setViewContext(Still); d->m_marblePresenter->map()->viewport()->resetFocusPoint(); d->m_wheelZoomTargetDistance = 0.0; } void MarbleDefaultInputHandler::hideSelectionIfCtrlReleased(QEvent *e) { if (selectionRubber()->isVisible() && e->type() == QEvent::MouseMove) { QMouseEvent *event = static_cast(e); if (!(event->modifiers() & Qt::ControlModifier)) { selectionRubber()->hide(); } } } bool MarbleDefaultInputHandler::handleDoubleClick(QMouseEvent *event) { qreal mouseLon; qreal mouseLat; const bool isMouseAboveMap = MarbleInputHandler::d->m_marblePresenter->map()->geoCoordinates(event->x(), event->y(), mouseLon, mouseLat, GeoDataCoordinates::Radian); if(isMouseAboveMap) { d->m_pressAndHoldTimer.stop(); d->m_lmbTimer.stop(); MarbleInputHandler::d->m_marblePresenter->moveTo(event->pos(), 0.67); } return acceptMouse(); } bool MarbleDefaultInputHandler::handleWheel(QWheelEvent *wheelevt) { MarbleAbstractPresenter *marblePresenter = MarbleInputHandler::d->m_marblePresenter; marblePresenter->setViewContext(Animation); if( (MarbleInputHandler::d->m_steps > 0 && wheelevt->delta() < 0) || (MarbleInputHandler::d->m_steps < 0 && wheelevt->delta() > 0) ) { MarbleInputHandler::d->m_steps = wheelevt->delta(); } else { MarbleInputHandler::d->m_steps += wheelevt->delta(); } if (marblePresenter->map()->discreteZoom()) { if(qAbs(MarbleInputHandler::d->m_steps) >= MarbleInputHandler::d->m_discreteZoomSteps) { marblePresenter->zoomAtBy(wheelevt->pos(), MarbleInputHandler::d->m_steps); MarbleInputHandler::d->m_steps = 0; } } else { qreal zoom = marblePresenter->zoom(); qreal target = MarbleInputHandler::d->m_wheelZoomTargetDistance; if (marblePresenter->animationsEnabled() && target > 0.0) { // Do not use intermediate (interpolated) distance values caused by animations zoom = marblePresenter->zoomFromDistance(target); } qreal newDistance = marblePresenter->distanceFromZoom(zoom + MarbleInputHandler::d->m_steps); MarbleInputHandler::d->m_wheelZoomTargetDistance = newDistance; marblePresenter->zoomAt(wheelevt->pos(), newDistance); if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.jumpToPosition(MarbleInputHandler::d->m_marblePresenter->centerLongitude(), MarbleInputHandler::d->m_marblePresenter->centerLatitude()); } MarbleInputHandler::d->m_steps = 0; } MarbleInputHandler::d->m_mouseWheelTimer->start(400); return true; } bool MarbleDefaultInputHandler::handlePinch(const QPointF ¢er, qreal scaleFactor, Qt::GestureState state) { qreal destLat; qreal destLon; MarbleAbstractPresenter *marblePresenter = MarbleInputHandler::d->m_marblePresenter; bool isValid = marblePresenter->map()->geoCoordinates(center.x(), center.y(), destLon, destLat, GeoDataCoordinates::Radian ); if (isValid) { marblePresenter->map()->viewport()->setFocusPoint(GeoDataCoordinates(destLon, destLat)); } qreal zoom, target, newDistance; qreal zoomDelta = scaleFactor > 1.0 ? scaleFactor : -1.0/scaleFactor; switch (state) { case Qt::NoGesture: break; case Qt::GestureStarted: marblePresenter->setViewContext(Animation); d->m_pressAndHoldTimer.stop(); d->m_lmbTimer.stop(); d->m_midPressed = false; d->m_leftPressed = false; break; case Qt::GestureUpdated: zoom = marblePresenter->zoom(); target = MarbleInputHandler::d->m_wheelZoomTargetDistance; if (marblePresenter->animationsEnabled() && target > 0.0) { // Do not use intermediate (interpolated) distance values caused by animations zoom = marblePresenter->zoomFromDistance(target); } newDistance = marblePresenter->distanceFromZoom(zoom + 20 * zoomDelta); MarbleInputHandler::d->m_wheelZoomTargetDistance = newDistance; marblePresenter->zoomAt(center.toPoint(), newDistance); break; case Qt::GestureFinished: marblePresenter->map()->viewport()->resetFocusPoint(); marblePresenter->setViewContext(Still); break; case Qt::GestureCanceled: marblePresenter->map()->viewport()->resetFocusPoint(); marblePresenter->setViewContext(Still); break; } return true; } bool MarbleDefaultInputHandler::handleGesture(QGestureEvent *ge) { QPinchGesture *pinch = static_cast(ge->gesture(Qt::PinchGesture)); if (!pinch) { return false; } qreal scaleFactor = pinch->scaleFactor(); QPointF center = pinch->centerPoint(); return handlePinch(center, scaleFactor, pinch->state()); } void MarbleDefaultInputHandler::checkReleasedMove(QMouseEvent *event) { // To prevent error from lost MouseButtonRelease events if (event->type() == QEvent::MouseMove && !(event->buttons() & Qt::LeftButton)) { if (d->m_leftPressed) { d->m_leftPressed = false; if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.start(); } else { MarbleInputHandler::d->m_marblePresenter->setViewContext(Still); } } } if (event->type() == QEvent::MouseMove && !(event->buttons() & Qt::MidButton)) { d->m_midPressed = false; } } void MarbleDefaultInputHandler::handleMouseButtonPress(QMouseEvent *event) { if (event->button() == Qt::LeftButton ) { d->m_pressAndHoldTimer.start(); handleLeftMouseButtonPress(event); } if ( event->button() == Qt::MidButton ) { handleMiddleMouseButtonPress(event); } if ( event->button() == Qt::RightButton ) { handleRightMouseButtonPress(event); } } void MarbleDefaultInputHandler::handleLeftMouseButtonPress(QMouseEvent *event) { // silently enable the animation context without triggering a repaint MarbleInputHandler::d->m_marblePresenter->map()->blockSignals(true); MarbleInputHandler::d->m_marblePresenter->setViewContext(Animation); MarbleInputHandler::d->m_marblePresenter->map()->blockSignals(false); if (isMouseButtonPopupEnabled(Qt::LeftButton)) { d->m_lmbTimer.start(400); } d->m_leftPressed = true; d->m_midPressed = false; selectionRubber()->hide(); // On the single event of a mouse button press these // values get stored, to enable us to e.g. calculate the // distance of a mouse drag while the mouse button is // still down. d->m_leftPressedX = event->x(); d->m_leftPressedY = event->y(); // Calculate translation of center point d->m_leftPressedLon = MarbleInputHandler::d->m_marblePresenter->centerLongitude(); d->m_leftPressedLat = MarbleInputHandler::d->m_marblePresenter->centerLatitude(); if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.stop(); d->m_kineticSpinning.setPosition(d->m_leftPressedLon, d->m_leftPressedLat); } if (event->modifiers() & Qt::ControlModifier) { mDebug() << Q_FUNC_INFO << "Starting selection"; d->m_pressAndHoldTimer.stop(); d->m_lmbTimer.stop(); d->m_selectionOrigin = event->pos(); selectionRubber()->setGeometry(QRect(d->m_selectionOrigin, QSize())); selectionRubber()->show(); } } void MarbleDefaultInputHandler::handleMiddleMouseButtonPress(QMouseEvent *event) { d->m_midPressed = true; d->m_leftPressed = false; d->m_startingRadius = MarbleInputHandler::d->m_marblePresenter->radius(); d->m_midPressedY = event->y(); if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.start(); } selectionRubber()->hide(); MarbleInputHandler::d->m_marblePresenter->setViewContext(Animation); } void MarbleDefaultInputHandler::handleRightMouseButtonPress(QMouseEvent *event) { d->m_rightPressed = true; d->m_rightOrigin = event->pos(); d->m_rightPosition = event->pos(); d->m_heading = MarbleInputHandler::d->m_marblePresenter->map()->heading(); if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.stop(); d->m_kineticSpinning.setHeading(d->m_heading); } } void MarbleDefaultInputHandler::handleMouseButtonRelease(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { d->m_pressAndHoldTimer.stop(); //emit current coordinates to be interpreted //as requested emit mouseClickScreenPosition(d->m_leftPressedX, d->m_leftPressedY); d->m_leftPressed = false; if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.start(); } else { MarbleInputHandler::d->m_marblePresenter->setViewContext(Still); } } if (event->button() == Qt::MidButton) { d->m_midPressed = false; MarbleInputHandler::d->m_marblePresenter->setViewContext(Still); } if (event->type() == QEvent::MouseButtonRelease && event->button() == Qt::RightButton) { if (d->m_rightOrigin == event->pos()) { emit rmbRequest(event->x(), event->y()); } d->m_rightPressed = false; if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.start(); } else { MarbleInputHandler::d->m_marblePresenter->setViewContext(Still); } } if (event->type() == QEvent::MouseButtonRelease && event->button() == Qt::LeftButton && selectionRubber()->isVisible()) { mDebug() << Q_FUNC_INFO << "Leaving selection"; MarbleInputHandler::d->m_marblePresenter->setSelection(selectionRubber()->geometry()); selectionRubber()->hide(); } } void MarbleDefaultInputHandler::notifyPosition(bool isMouseAboveMap, qreal mouseLon, qreal mouseLat) { // emit the position string only if the signal got attached if (MarbleInputHandler::d->m_positionSignalConnected) { if (!isMouseAboveMap) { emit mouseMoveGeoPosition(QCoreApplication::translate( "Marble", NOT_AVAILABLE)); } else { QString position = GeoDataCoordinates(mouseLon, mouseLat).toString(); emit mouseMoveGeoPosition(position); } } } void MarbleDefaultInputHandler::adjustCursorShape(const QPoint &mousePosition, const QPoint &mouseDirection) { // Find out if there are data items and if one has defined an action QList dataItems = MarbleInputHandler::d->m_marblePresenter->map()->whichItemAt(mousePosition); bool dataAction = false; QPointer toolTipItem; QList::iterator it = dataItems.begin(); QList::iterator const end = dataItems.end(); for (; it != end && dataAction == false && toolTipItem.isNull(); ++it) { if ((*it)->action()) { dataAction = true; } if (!(*it)->toolTip().isNull() && toolTipItem.isNull()) { toolTipItem = (*it); } } if (toolTipItem.isNull()) { d->m_toolTipTimer.stop(); } else if (!( d->m_lastToolTipItem.data() == toolTipItem.data())) { d->m_toolTipTimer.start(); d->m_lastToolTipItem = toolTipItem; d->m_toolTipPosition = mousePosition; } else { if (!d->m_toolTipTimer.isActive()) { d->m_toolTipTimer.start(); } d->m_toolTipPosition = mousePosition; } if (!dataAction && !MarbleInputHandler::d->m_marblePresenter->map()->hasFeatureAt(mousePosition)) { if (!d->m_leftPressed) { d->m_arrowCur [1][1] = QCursor(Qt::OpenHandCursor); } else { d->m_arrowCur [1][1] = QCursor(Qt::ClosedHandCursor); } } else { if (!d->m_leftPressed) { d->m_arrowCur [1][1] = QCursor(Qt::PointingHandCursor); } } if (panViaArrowsEnabled()) { setCursor(d->m_arrowCur[mouseDirection.x()+1][mouseDirection.y()+1]); } else { setCursor(d->m_arrowCur[1][1]); } } QPoint MarbleDefaultInputHandler::mouseMovedOutside(QMouseEvent *event) { //Returns a 2d vector representing the direction in which the mouse left int dirX = 0; int dirY = 0; int polarity = MarbleInputHandler::d->m_marblePresenter->viewport()->polarity(); if (d->m_leftPressed) { d->m_leftPressed = false; if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.start(); } } QRect boundingRect = MarbleInputHandler::d->m_marblePresenter->viewport()->mapRegion().boundingRect(); if (boundingRect.width() != 0) { dirX = (int)( 3 * (event->x() - boundingRect.left()) / boundingRect.width()) - 1; } if (dirX > 1) { dirX = 1; } if (dirX < -1) { dirX = -1; } if (boundingRect.height() != 0) { dirY = (int)(3 * (event->y() - boundingRect.top()) / boundingRect.height()) - 1; } if (dirY > 1) { dirY = 1; } if (dirY < -1) { dirY = -1; } if (event->button() == Qt::LeftButton && event->type() == QEvent::MouseButtonPress && panViaArrowsEnabled() && !d->m_kineticSpinning.hasVelocity()) { d->m_pressAndHoldTimer.stop(); d->m_lmbTimer.stop(); qreal moveStep = MarbleInputHandler::d->m_marblePresenter->moveStep(); if (polarity < 0) { MarbleInputHandler::d->m_marblePresenter->rotateBy(-moveStep * (qreal)(+dirX), moveStep * (qreal)(+dirY)); } else { MarbleInputHandler::d->m_marblePresenter->rotateBy(-moveStep * (qreal)(-dirX), moveStep * (qreal)(+dirY)); } } if (!MarbleInputHandler::d->m_inertialEarthRotation) { MarbleInputHandler::d->m_marblePresenter->setViewContext(Still); } return QPoint(dirX, dirY); } bool MarbleDefaultInputHandler::handleMouseEvent(QMouseEvent *event) { QPoint direction; checkReleasedMove(event); // Do not handle (and therefore eat) mouse press and release events // that occur above visible float items. Mouse motion events are still // handled, however. if (event->type() != QEvent::MouseMove && !selectionRubber()->isVisible()) { auto const floatItems = MarbleInputHandler::d->m_marblePresenter->map()->floatItems(); for (AbstractFloatItem *floatItem: floatItems) { if ( floatItem->enabled() && floatItem->visible() && floatItem->contains( event->pos() ) ) { d->m_pressAndHoldTimer.stop(); d->m_lmbTimer.stop(); return false; } } } qreal mouseLon; qreal mouseLat; const bool isMouseAboveMap = MarbleInputHandler::d->m_marblePresenter->map()->geoCoordinates(event->x(), event->y(), mouseLon, mouseLat, GeoDataCoordinates::Radian); notifyPosition(isMouseAboveMap, mouseLon, mouseLat); QPoint mousePosition(event->x(), event->y()); if (isMouseAboveMap || selectionRubber()->isVisible() || MarbleInputHandler::d->m_marblePresenter->map()->hasFeatureAt(mousePosition)) { if (event->type() == QEvent::MouseButtonPress) { handleMouseButtonPress(event); } if (event->type() == QEvent::MouseButtonRelease) { handleMouseButtonRelease(event); } // Regarding all kinds of mouse moves: if (d->m_leftPressed && !selectionRubber()->isVisible()) { qreal radius = (qreal)(MarbleInputHandler::d->m_marblePresenter->radius()); qreal deltax = event->x() - d->m_leftPressedX; qreal deltay = event->y() - d->m_leftPressedY; if (qAbs(deltax) > d->m_dragThreshold || qAbs(deltay) > d->m_dragThreshold || !d->m_lmbTimer.isActive()) { MarbleInputHandler::d->m_marblePresenter->setViewContext(Animation); d->m_pressAndHoldTimer.stop(); d->m_lmbTimer.stop(); const Quaternion rotation = Quaternion::fromEuler( 0, 0, MarbleInputHandler::d->m_marblePresenter->map()->heading() * DEG2RAD ); Quaternion quat = Quaternion::fromSpherical( - M_PI/2 * deltax / radius, + M_PI/2 * deltay / radius ); quat.rotateAroundAxis( rotation ); qreal lon, lat; quat.getSpherical( lon, lat ); const qreal posLon = d->m_leftPressedLon + RAD2DEG * lon; const qreal posLat = d->m_leftPressedLat + RAD2DEG * lat; MarbleInputHandler::d->m_marblePresenter->centerOn(posLon, posLat); if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.setPosition(posLon, posLat); } } } if (d->m_midPressed) { int eventy = event->y(); int dy = d->m_midPressedY - eventy; MarbleInputHandler::d->m_marblePresenter->setRadius(d->m_startingRadius * pow(1.005, dy)); } - if (d->m_rightPressed) + if (d->m_rightPressed && MarbleInputHandler::d->m_mouseViewRotation) { qreal centerX, centerY; MarbleInputHandler::d->m_marblePresenter->map()->screenCoordinates( MarbleInputHandler::d->m_marblePresenter->centerLongitude(), MarbleInputHandler::d->m_marblePresenter->centerLatitude(), centerX, centerY); // Deltas from previous position. int dx = event->x() - d->m_rightPosition.x(); int dy = event->y() - d->m_rightPosition.y(); d->m_rightPosition = event->pos(); // Moving on the bottom should be opposite direction. int sign = event->y() > centerY ? -1 : 1; // Left top and right bottom sides for y axis should be opposite direction. if ((event->x() < centerX && event->y() < centerY) || (event->x() > centerX && event->y() > centerY)) { dy *= -1; } const qreal speedFactor = 0.3; d->m_heading += (dx + dy) * sign * speedFactor; MarbleInputHandler::d->m_marblePresenter->map()->setHeading(d->m_heading); if (MarbleInputHandler::d->m_inertialEarthRotation) { d->m_kineticSpinning.setHeading(d->m_heading); } } if (selectionRubber()->isVisible()) { // We change selection. selectionRubber()->setGeometry(QRect(d->m_selectionOrigin, event->pos()).normalized()); } } else { direction = mouseMovedOutside(event); } if (MarbleInputHandler::d->m_marblePresenter->viewContext() != Animation) { adjustCursorShape(mousePosition, direction); } return acceptMouse(); } bool MarbleDefaultInputHandler::acceptMouse() { // let others, especially float items, still process the event // Note: This caused a bug in combination with oxygen, see https://bugs.kde.org/show_bug.cgi?id=242414 // and changing it a related regression, see https://bugs.kde.org/show_bug.cgi?id=324862 return false; } bool MarbleDefaultInputHandler::eventFilter(QObject* o, QEvent* e) { Q_UNUSED(o); if (layersEventFilter(o, e)) { return true; } hideSelectionIfCtrlReleased(e); switch (e->type()) { case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: return handleTouch(static_cast(e)); case QEvent::KeyPress: return handleKeyPress(static_cast(e)); case QEvent::Gesture: return handleGesture(static_cast(e)); case QEvent::Wheel: return handleWheel(static_cast(e)); case QEvent::MouseButtonDblClick: return handleDoubleClick(static_cast(e)); case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: return handleMouseEvent(static_cast(e)); default: return false; } } bool MarbleDefaultInputHandler::handleTouch(QTouchEvent*) { return false; //reimplement to handle in cases of QML and PinchArea element } bool MarbleDefaultInputHandler::handleKeyPress(QKeyEvent* event) { if ( event->type() == QEvent::KeyPress ) { MarbleAbstractPresenter *marblePresenter = MarbleInputHandler::d->m_marblePresenter; bool handled = true; switch ( event->key() ) { case Qt::Key_Left: stopInertialEarthRotation(); marblePresenter->moveByStep(-1, 0); break; case Qt::Key_Right: stopInertialEarthRotation(); marblePresenter->moveByStep(1, 0); break; case Qt::Key_Up: stopInertialEarthRotation(); marblePresenter->moveByStep(0, -1); break; case Qt::Key_Down: stopInertialEarthRotation(); marblePresenter->moveByStep(0, 1); break; case Qt::Key_Plus: if (event->modifiers() != Qt::ControlModifier) { stopInertialEarthRotation(); marblePresenter->zoomIn(); } break; case Qt::Key_Minus: if (event->modifiers() != Qt::ControlModifier) { stopInertialEarthRotation(); marblePresenter->zoomOut(); } break; case Qt::Key_Home: stopInertialEarthRotation(); marblePresenter->goHome(); break; default: handled = false; break; } return handled; } return false; } void MarbleDefaultInputHandler::handleMouseButtonPressAndHold(const QPoint &) { // Default implementation does nothing } void MarbleDefaultInputHandler::handlePressAndHold() { handleMouseButtonPressAndHold(QPoint(d->m_leftPressedX, d->m_leftPressedY)); } const AbstractDataPluginItem *MarbleDefaultInputHandler::lastToolTipItem() const { return d->m_lastToolTipItem; } QTimer* MarbleDefaultInputHandler::toolTipTimer() { return &d->m_toolTipTimer; } QPoint MarbleDefaultInputHandler::toolTipPosition() const { return d->m_toolTipPosition; } } #include "moc_MarbleInputHandler.cpp" diff --git a/src/lib/marble/MarbleInputHandler.h b/src/lib/marble/MarbleInputHandler.h index 5b9ed31fe..ca08cf638 100644 --- a/src/lib/marble/MarbleInputHandler.h +++ b/src/lib/marble/MarbleInputHandler.h @@ -1,188 +1,192 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2005-2007 Torsten Rahn // Copyright 2007 Inge Wallin // Copyright 2014 Adam Dabrowski // #ifndef MARBLE_MARBLEINPUTHANDLER_H #define MARBLE_MARBLEINPUTHANDLER_H #include #include "marble_export.h" #include "GeoDataCoordinates.h" class QEvent; class QKeyEvent; class QMouseEvent; class QTouchEvent; class QWheelEvent; class QGestureEvent; class QCursor; class QTimer; class QString; class QRect; namespace Marble { class MarbleAbstractPresenter; class AbstractDataPluginItem; class RenderPlugin; class MARBLE_EXPORT MarbleInputHandler : public QObject { Q_OBJECT public: explicit MarbleInputHandler( MarbleAbstractPresenter* ); ~MarbleInputHandler() override; void setPositionSignalConnected( bool connected ); bool isPositionSignalConnected() const; /** // // The MarbleInputHandler handles mouse and keyboard input. // * @brief Set whether a popup menu appears on a click (not drag) with the left mouse button * @param enabled True to enable the popup menu (default), false to disable it */ void setMouseButtonPopupEnabled( Qt::MouseButton mouseButton, bool enabled ); /** * @brief Return whether the left mouse button popup menu is active * @return True iff a popup menu is shown on left mouse button clicks */ bool isMouseButtonPopupEnabled( Qt::MouseButton mouseButton ) const; void setPanViaArrowsEnabled( bool enabled ); bool panViaArrowsEnabled() const; void setInertialEarthRotationEnabled( bool enabled ); /** * @brief Returns true iff dragging the map with the mouse keeps spinning * in the chosen direction for a slightly longer time than the mouse is * actually performing the drag operation */ bool inertialEarthRotationEnabled() const; + void setMouseViewRotationEnabled( bool enabled ); + + bool mouseViewRotationEnabled() const; + /// should the map do kinetic scrolling, this would stop the operation virtual void stopInertialEarthRotation(); Q_SIGNALS: // Mouse button menus void lmbRequest( int, int ); void rmbRequest( int, int ); //Gps coordinates void mouseClickScreenPosition( int, int ); void mouseMoveGeoPosition( const QString& ); /* * To detect mouse click followed by mouse move * with no mouse move in between */ void mouseClickGeoPosition( qreal, qreal, GeoDataCoordinates::Unit ); protected Q_SLOTS: void restoreViewContext(); protected: class Protected; Protected * const d; private Q_SLOTS: virtual void installPluginEventFilter( RenderPlugin *renderPlugin ) = 0; private: Q_DISABLE_COPY( MarbleInputHandler ) }; class AbstractSelectionRubber { public: virtual ~AbstractSelectionRubber() {} virtual void show() = 0; virtual void hide() = 0; virtual bool isVisible() const = 0; virtual const QRect &geometry() const = 0; virtual void setGeometry(const QRect &geometry) = 0; }; class MARBLE_EXPORT MarbleDefaultInputHandler : public MarbleInputHandler { Q_OBJECT public: explicit MarbleDefaultInputHandler( MarbleAbstractPresenter* marblePresenter); ~MarbleDefaultInputHandler() override; void stopInertialEarthRotation() override; protected: bool eventFilter( QObject *, QEvent * ) override; bool handleMouseEvent(QMouseEvent *e); bool handlePinch(const QPointF ¢er, qreal scaleFactor, Qt::GestureState state); //FIXME - refactor (abstraction & composition) const AbstractDataPluginItem *lastToolTipItem() const; QTimer* toolTipTimer(); QPoint toolTipPosition() const; virtual bool handleKeyPress(QKeyEvent *e); virtual void handleMouseButtonPressAndHold(const QPoint &position); private Q_SLOTS: void installPluginEventFilter( RenderPlugin *renderPlugin ) override = 0; virtual void showLmbMenu( int, int ) = 0; virtual void showRmbMenu( int, int ) = 0; void handlePressAndHold(); virtual void openItemToolTip() = 0; virtual void setCursor(const QCursor &) = 0; void lmbTimeout(); private: virtual AbstractSelectionRubber *selectionRubber() = 0; virtual bool layersEventFilter(QObject *, QEvent *) = 0; virtual bool handleTouch(QTouchEvent *e); virtual bool handleDoubleClick(QMouseEvent *e); virtual bool handleWheel(QWheelEvent *e); virtual bool handleGesture(QGestureEvent *e); virtual void handleMouseButtonPress(QMouseEvent *e); virtual void handleLeftMouseButtonPress(QMouseEvent *e); virtual void handleRightMouseButtonPress(QMouseEvent *e); virtual void handleMiddleMouseButtonPress(QMouseEvent *e); virtual void handleMouseButtonRelease(QMouseEvent *e); virtual void hideSelectionIfCtrlReleased(QEvent *e); virtual void checkReleasedMove(QMouseEvent *e); //Returns whatever should be returned from mouse event handling loop virtual bool acceptMouse(); void notifyPosition(bool isAboveMap, qreal mouseLon, qreal mouseLat); QPoint mouseMovedOutside(QMouseEvent *event); void adjustCursorShape(const QPoint& mousePosition, const QPoint& mouseDirection); Q_DISABLE_COPY(MarbleDefaultInputHandler) class Private; Private * const d; }; } #endif //MARBLE_MARBLEINPUTHANDLER_H diff --git a/src/lib/marble/MarbleNavigationSettingsWidget.ui b/src/lib/marble/MarbleNavigationSettingsWidget.ui index 3b6c973ef..d5ce068d9 100644 --- a/src/lib/marble/MarbleNavigationSettingsWidget.ui +++ b/src/lib/marble/MarbleNavigationSettingsWidget.ui @@ -1,227 +1,237 @@ MarbleNavigationSettingsWidget 0 0 333 257 Dragging and Animation 0 0 118 0 &Drag location: kcfg_dragLocation false <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">While dragging the mouse there are two standard behaviours when dealing with a virtual globe:</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The location below mouse pointer will follow the cursor exactly: As a result e.g. the north pole will not stay at the top which can lead to confusion. By default Marble makes sure that north is always up which results in a dragging behaviour where the location below the mouse pointer slightly "detaches" from the cursor. </p></body></html> Keep Planet Axis Vertically Follow Mouse Pointer Use kinetic spinning when dragging the map &Inertial Globe Rotation <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">When searching for a location Marble can either move instantly to the new location or it can show a travel animation from the previous place to the new place.</p></body></html> &Animate voyage to the target + + + + Use right mouse button to rotate the camera around + + + &Mouse view rotation + + + Qt::Vertical QSizePolicy::Fixed 20 10 QFormLayout::ExpandingFieldsGrow 0 0 118 0 &On startup: kcfg_onStartup <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">By default Marble will display the home location immediately after the application has started. As an alternative it can also show the last position that was active when the user left the application. </p></body></html> Show Home Location Return to Last Location Visited 0 0 118 0 &External Editor: kcfg_onStartup <p>The application that is launched to edit maps. Potlatch (default) requires a web browser with flash support to be installed. When selecting josm or merkaartor, make sure that the respective application is installed.</p> Always ask Potlatch (Web browser) JOSM Merkaartor Qt::Vertical 20 20 diff --git a/src/lib/marble/QtMarbleConfigDialog.cpp b/src/lib/marble/QtMarbleConfigDialog.cpp index d1d100cfe..6da5af77b 100644 --- a/src/lib/marble/QtMarbleConfigDialog.cpp +++ b/src/lib/marble/QtMarbleConfigDialog.cpp @@ -1,658 +1,665 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2009 Bastian Holst // Copyright 2012 Mohammed Nafees // // Own #include "QtMarbleConfigDialog.h" #include "ui_MarbleCacheSettingsWidget.h" #include "ui_MarbleViewSettingsWidget.h" #include "ui_MarbleNavigationSettingsWidget.h" #include "ui_MarbleTimeSettingsWidget.h" #include "ui_MarbleCloudSyncSettingsWidget.h" // Qt #include #include #include #include #include #include #include #include #include // Marble #include "MarbleGlobal.h" #include "MarbleDebug.h" #include "MarbleDirs.h" #include "MarblePluginSettingsWidget.h" #include "MarbleLocale.h" #include "MarbleWidget.h" #include "MarbleModel.h" #include "RenderPlugin.h" #include "RenderPluginModel.h" #include "MarbleClock.h" #include "routing/RoutingProfilesWidget.h" #include "BookmarkSyncManager.h" #include "CloudSyncManager.h" namespace Marble { class QtMarbleConfigDialogPrivate { public: QtMarbleConfigDialogPrivate( MarbleWidget *marbleWidget, CloudSyncManager *cloudSyncManager ) : ui_viewSettings(), ui_navigationSettings(), ui_timeSettings(), ui_cacheSettings(), w_pluginSettings( nullptr ), m_cloudSyncStatusLabel( nullptr ), m_marbleWidget( marbleWidget ), m_syncManager( cloudSyncManager ? cloudSyncManager->bookmarkSyncManager() : nullptr ), m_cloudSyncManager(cloudSyncManager), m_pluginModel() { } Ui::MarbleViewSettingsWidget ui_viewSettings; Ui::MarbleNavigationSettingsWidget ui_navigationSettings; Ui::MarbleTimeSettingsWidget ui_timeSettings; Ui::MarbleCacheSettingsWidget ui_cacheSettings; Ui::MarbleCloudSyncSettingsWidget ui_cloudSyncSettings; MarblePluginSettingsWidget *w_pluginSettings; QSettings m_settings; QLabel *m_cloudSyncStatusLabel; MarbleWidget *const m_marbleWidget; BookmarkSyncManager *const m_syncManager; CloudSyncManager *const m_cloudSyncManager; RenderPluginModel m_pluginModel; QHash< int, int > m_timezone; }; QtMarbleConfigDialog::QtMarbleConfigDialog(MarbleWidget *marbleWidget, CloudSyncManager *cloudSyncManager, QWidget *parent ) : QDialog( parent ), d( new QtMarbleConfigDialogPrivate( marbleWidget, cloudSyncManager ) ) { QTabWidget *tabWidget = new QTabWidget( this ); QDialogButtonBox *buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel, Qt::Horizontal, this ); // Connect the signals of the ButtonBox // to the corresponding slots of the dialog. connect( buttons, SIGNAL(accepted()), this, SLOT(accept()) ); // Ok connect( buttons, SIGNAL(rejected()), this, SLOT(reject()) ); // Cancel connect( buttons->button( QDialogButtonBox::Apply ),SIGNAL(clicked()), this, SLOT(writeSettings()) ); // Apply // If the dialog is accepted. Save the settings. connect( this, SIGNAL(accepted()), this, SLOT(writeSettings()) ); // view page QWidget *w_viewSettings = new QWidget( this ); d->ui_viewSettings.setupUi( w_viewSettings ); tabWidget->addTab( w_viewSettings, tr( "View" ) ); d->ui_viewSettings.kcfg_labelLocalization->hide(); d->ui_viewSettings.label_labelLocalization->hide(); // navigation page QWidget *w_navigationSettings = new QWidget( this ); d->ui_navigationSettings.setupUi( w_navigationSettings ); tabWidget->addTab( w_navigationSettings, tr( "Navigation" ) ); d->ui_navigationSettings.kcfg_dragLocation->hide(); d->ui_navigationSettings.label_dragLocation->hide(); // cache page QWidget *w_cacheSettings = new QWidget( this ); d->ui_cacheSettings.setupUi( w_cacheSettings ); tabWidget->addTab( w_cacheSettings, tr( "Cache and Proxy" ) ); // Forwarding clear button signals connect( d->ui_cacheSettings.button_clearVolatileCache, SIGNAL(clicked()), SIGNAL(clearVolatileCacheClicked()) ); connect( d->ui_cacheSettings.button_clearPersistentCache, SIGNAL(clicked()), SIGNAL(clearPersistentCacheClicked()) ); // time page QWidget *w_timeSettings = new QWidget( this ); d->ui_timeSettings.setupUi( w_timeSettings ); tabWidget->addTab( w_timeSettings, tr( "Date and Time" ) ); // routing page QWidget *w_routingSettings = new RoutingProfilesWidget( marbleWidget->model() ); tabWidget->addTab( w_routingSettings, tr( "Routing" ) ); // plugin page d->m_pluginModel.setRenderPlugins( d->m_marbleWidget->renderPlugins() ); d->w_pluginSettings = new MarblePluginSettingsWidget( this ); d->w_pluginSettings->setModel( &d->m_pluginModel ); d->w_pluginSettings->setObjectName( "plugin_page" ); tabWidget->addTab( d->w_pluginSettings, tr( "Plugins" ) ); // Setting the icons for the plugin dialog. d->w_pluginSettings->setAboutIcon(QIcon(QStringLiteral(":/icons/help-about.png"))); d->w_pluginSettings->setConfigIcon(QIcon(QStringLiteral(":/icons/settings-configure.png"))); connect( this, SIGNAL(rejected()), &d->m_pluginModel, SLOT(retrievePluginState()) ); connect( this, SIGNAL(accepted()), &d->m_pluginModel, SLOT(applyPluginState()) ); QWidget *w_cloudSyncSettings = new QWidget( this ); d->ui_cloudSyncSettings.setupUi( w_cloudSyncSettings ); tabWidget->addTab( w_cloudSyncSettings, tr( "Synchronization" ) ); d->ui_cloudSyncSettings.button_syncNow->setEnabled( syncBookmarks() ); d->m_cloudSyncStatusLabel = d->ui_cloudSyncSettings.cloudSyncStatus; connect( d->ui_cloudSyncSettings.button_syncNow, SIGNAL(clicked()), SIGNAL(syncNowClicked()) ); connect( d->ui_cloudSyncSettings.testLoginButton, SIGNAL(clicked()), this, SLOT(updateCloudSyncCredentials()) ); if ( d->m_syncManager ) { connect(d->m_syncManager, SIGNAL(syncComplete()), this, SLOT(updateLastSync())); updateLastSync(); } if ( d->m_cloudSyncManager ) { connect( d->m_cloudSyncManager, SIGNAL(statusChanged(QString)), this, SLOT(updateCloudSyncStatus(QString))); } // Layout QVBoxLayout *layout = new QVBoxLayout( this ); layout->addWidget( tabWidget ); layout->addWidget( buttons ); this->setLayout( layout ); // When the settings have been changed, write to disk. connect( this, SIGNAL(settingsChanged()), this, SLOT(syncSettings()) ); initializeCustomTimezone(); } QtMarbleConfigDialog::~QtMarbleConfigDialog() { delete d; } void QtMarbleConfigDialog::syncSettings() { d->m_settings.sync(); QNetworkProxy proxy; // Make sure that no proxy is used for an empty string or the default value: if (proxyUrl().isEmpty() || proxyUrl() == QLatin1String("http://")) { proxy.setType( QNetworkProxy::NoProxy ); } else { if ( proxyType() == Marble::Socks5Proxy ) { proxy.setType( QNetworkProxy::Socks5Proxy ); } else if ( proxyType() == Marble::HttpProxy ) { proxy.setType( QNetworkProxy::HttpProxy ); } else { mDebug() << "Unknown proxy type! Using Http Proxy instead."; proxy.setType( QNetworkProxy::HttpProxy ); } } proxy.setHostName( proxyUrl() ); proxy.setPort( proxyPort() ); if ( proxyAuth() ) { proxy.setUser( proxyUser() ); proxy.setPassword( proxyPass() ); } QNetworkProxy::setApplicationProxy(proxy); } void QtMarbleConfigDialog::updateCloudSyncCredentials() { if ( d->m_cloudSyncManager ) { d->m_cloudSyncManager->setOwncloudCredentials( d->ui_cloudSyncSettings.kcfg_owncloudServer->text(), d->ui_cloudSyncSettings.kcfg_owncloudUsername->text(), d->ui_cloudSyncSettings.kcfg_owncloudPassword->text() ); } } void QtMarbleConfigDialog::disableSyncNow() { if ( !d->m_syncManager ) { return; } d->ui_cloudSyncSettings.button_syncNow->setDisabled(true); QTimer *timeoutTimer = new QTimer(this); connect(timeoutTimer, SIGNAL(timeout()), timeoutTimer, SLOT(stop())); connect(timeoutTimer, SIGNAL(timeout()), this, SLOT(enableSyncNow())); connect(d->m_syncManager, SIGNAL(syncComplete()), this, SLOT(enableSyncNow())); connect(d->m_syncManager, SIGNAL(syncComplete()), timeoutTimer, SLOT(stop())); connect(d->m_syncManager, SIGNAL(syncComplete()), timeoutTimer, SLOT(deleteLater())); timeoutTimer->start(30*1000); // 30 sec } void QtMarbleConfigDialog::enableSyncNow() { if ( !d->m_syncManager ) { return; } d->ui_cloudSyncSettings.button_syncNow->setEnabled(true); } void QtMarbleConfigDialog::updateLastSync() { if ( !d->m_syncManager ) { return; } if (!d->m_syncManager->lastSync().isValid()) { d->ui_cloudSyncSettings.labelLastSync->setText(tr("Never synchronized.")); return; } const QString title = tr("Last synchronization: %1") .arg(d->m_syncManager->lastSync().toString()); d->ui_cloudSyncSettings.labelLastSync->setText(title); } void QtMarbleConfigDialog::readSettings() { // Sync settings to make sure that we read the current settings. syncSettings(); // View d->ui_viewSettings.kcfg_distanceUnit->setCurrentIndex( measurementSystem() ); d->ui_viewSettings.kcfg_angleUnit->setCurrentIndex( angleUnit() ); d->ui_viewSettings.kcfg_stillQuality->setCurrentIndex( stillQuality() ); d->ui_viewSettings.kcfg_animationQuality->setCurrentIndex( animationQuality() ); d->ui_viewSettings.kcfg_labelLocalization->setCurrentIndex( Marble::Native ); d->ui_viewSettings.kcfg_mapFont->setCurrentFont( mapFont() ); // Navigation d->ui_navigationSettings.kcfg_dragLocation->setCurrentIndex( Marble::KeepAxisVertically ); d->ui_navigationSettings.kcfg_onStartup->setCurrentIndex( onStartup() ); d->ui_navigationSettings.kcfg_inertialEarthRotation->setChecked( inertialEarthRotation() ); + d->ui_navigationSettings.kcfg_mouseViewRotation->setChecked( mouseViewRotation() ); d->ui_navigationSettings.kcfg_animateTargetVoyage->setChecked( animateTargetVoyage() ); int editorIndex = 0; if (externalMapEditor() == QLatin1String("potlatch")) { editorIndex = 1; } else if (externalMapEditor() == QLatin1String("josm")) { editorIndex = 2; } else if (externalMapEditor() == QLatin1String("merkaartor")) { editorIndex = 3; } d->ui_navigationSettings.kcfg_externalMapEditor->setCurrentIndex( editorIndex ); // Cache d->ui_cacheSettings.kcfg_volatileTileCacheLimit->setValue( volatileTileCacheLimit() ); d->ui_cacheSettings.kcfg_persistentTileCacheLimit->setValue( persistentTileCacheLimit() ); d->ui_cacheSettings.kcfg_proxyUrl->setText( proxyUrl() ); d->ui_cacheSettings.kcfg_proxyPort->setValue( proxyPort() ); d->ui_cacheSettings.kcfg_proxyUser->setText( proxyUser() ); d->ui_cacheSettings.kcfg_proxyPass->setText( proxyPass() ); d->ui_cacheSettings.kcfg_proxyType->setCurrentIndex( proxyType() ); d->ui_cacheSettings.kcfg_proxyAuth->setChecked( proxyAuth() ); // Time d->ui_timeSettings.kcfg_systemTimezone->setChecked( systemTimezone() ); d->ui_timeSettings.kcfg_customTimezone->setChecked( customTimezone() ); d->ui_timeSettings.kcfg_chosenTimezone->setCurrentIndex( chosenTimezone() ); d->ui_timeSettings.kcfg_utc->setChecked( UTC() ); d->ui_timeSettings.kcfg_systemTime->setChecked( systemTime() ); d->ui_timeSettings.kcfg_lastSessionTime->setChecked( lastSessionTime() ); if( systemTimezone() == true ) { QDateTime localTime = QDateTime::currentDateTime().toLocalTime(); localTime.setTimeSpec( Qt::UTC ); d->m_marbleWidget->model()->setClockTimezone( QDateTime::currentDateTime().toUTC().secsTo( localTime ) ); } else if( UTC() == true ) { d->m_marbleWidget->model()->setClockTimezone( 0 ); } else if( customTimezone() == true ) { d->m_marbleWidget->model()->setClockTimezone( d->m_timezone.value( chosenTimezone() ) ); } // Routing // ownCloud d->ui_cloudSyncSettings.kcfg_enableSync->setChecked( syncEnabled() ); d->ui_cloudSyncSettings.kcfg_syncBookmarks->setChecked( syncBookmarks() ); d->ui_cloudSyncSettings.kcfg_syncRoutes->setChecked( syncRoutes() ); d->ui_cloudSyncSettings.kcfg_owncloudServer->setText( owncloudServer() ); d->ui_cloudSyncSettings.kcfg_owncloudUsername->setText( owncloudUsername() ); d->ui_cloudSyncSettings.kcfg_owncloudPassword->setText( owncloudPassword() ); // Read the settings of the plugins d->m_marbleWidget->readPluginSettings( d->m_settings ); // The settings loaded in the config dialog have been changed. emit settingsChanged(); } void QtMarbleConfigDialog::updateCloudSyncStatus( const QString &status ) { d->m_cloudSyncStatusLabel->setText(status); CloudSyncManager::Status status_type = d->m_cloudSyncManager ? d->m_cloudSyncManager->status() : CloudSyncManager::Unknown; switch (status_type) { case CloudSyncManager::Success: d->m_cloudSyncStatusLabel->setStyleSheet("QLabel { color : green; }"); break; case CloudSyncManager::Error: d->m_cloudSyncStatusLabel->setStyleSheet("QLabel { color : red; }"); break; case CloudSyncManager::Unknown: d->m_cloudSyncStatusLabel->setStyleSheet("QLabel { color : grey; }"); break; } } void QtMarbleConfigDialog::writeSettings() { syncSettings(); d->m_settings.beginGroup( "View" ); d->m_settings.setValue( "distanceUnit", d->ui_viewSettings.kcfg_distanceUnit->currentIndex() ); d->m_settings.setValue( "angleUnit", d->ui_viewSettings.kcfg_angleUnit->currentIndex() ); d->m_settings.setValue( "stillQuality", d->ui_viewSettings.kcfg_stillQuality->currentIndex() ); d->m_settings.setValue( "animationQuality", d->ui_viewSettings.kcfg_animationQuality->currentIndex() ); d->m_settings.setValue( "mapFont", d->ui_viewSettings.kcfg_mapFont->currentFont() ); d->m_settings.endGroup(); d->m_settings.beginGroup( "Navigation" ); d->m_settings.setValue( "onStartup", d->ui_navigationSettings.kcfg_onStartup->currentIndex() ); d->m_settings.setValue( "inertialEarthRotation", d->ui_navigationSettings.kcfg_inertialEarthRotation->isChecked() ); + d->m_settings.setValue( "mouseViewRotation", d->ui_navigationSettings.kcfg_mouseViewRotation->isChecked() ); d->m_settings.setValue( "animateTargetVoyage", d->ui_navigationSettings.kcfg_animateTargetVoyage->isChecked() ); if( d->ui_navigationSettings.kcfg_externalMapEditor->currentIndex() == 0 ) { d->m_settings.setValue( "externalMapEditor", "" ); } else if( d->ui_navigationSettings.kcfg_externalMapEditor->currentIndex() == 1 ) { d->m_settings.setValue( "externalMapEditor", "potlatch" ); } else if( d->ui_navigationSettings.kcfg_externalMapEditor->currentIndex() == 2 ) { d->m_settings.setValue( "externalMapEditor", "josm" ); } else if( d->ui_navigationSettings.kcfg_externalMapEditor->currentIndex() == 3 ) { d->m_settings.setValue( "externalMapEditor", "merkaartor" ); } else { Q_ASSERT( false && "Unexpected index of the external editor setting" ); } d->m_settings.endGroup(); d->m_settings.beginGroup( "Cache" ); d->m_settings.setValue( "volatileTileCacheLimit", d->ui_cacheSettings.kcfg_volatileTileCacheLimit->value() ); d->m_settings.setValue( "persistentTileCacheLimit", d->ui_cacheSettings.kcfg_persistentTileCacheLimit->value() ); d->m_settings.setValue( "proxyUrl", d->ui_cacheSettings.kcfg_proxyUrl->text() ); d->m_settings.setValue( "proxyPort", d->ui_cacheSettings.kcfg_proxyPort->value() ); d->m_settings.setValue( "proxyType", d->ui_cacheSettings.kcfg_proxyType->currentIndex() ); if ( d->ui_cacheSettings.kcfg_proxyAuth->isChecked() ) { d->m_settings.setValue( "proxyAuth", true ); d->m_settings.setValue( "proxyUser", d->ui_cacheSettings.kcfg_proxyUser->text() ); d->m_settings.setValue( "proxyPass", d->ui_cacheSettings.kcfg_proxyPass->text() ); } else { d->m_settings.setValue( "proxyAuth", false ); } d->m_settings.endGroup(); d->m_settings.beginGroup( "Time" ); d->m_settings.setValue( "systemTimezone", d->ui_timeSettings.kcfg_systemTimezone->isChecked() ); d->m_settings.setValue( "UTC", d->ui_timeSettings.kcfg_utc->isChecked() ); d->m_settings.setValue( "customTimezone", d->ui_timeSettings.kcfg_customTimezone->isChecked() ); d->m_settings.setValue( "systemTime", d->ui_timeSettings.kcfg_systemTime->isChecked() ); d->m_settings.setValue( "lastSessionTime", d->ui_timeSettings.kcfg_lastSessionTime->isChecked() ); d->m_settings.setValue( "chosenTimezone", d->ui_timeSettings.kcfg_chosenTimezone->currentIndex() ); d->m_settings.endGroup(); d->m_settings.beginGroup( "CloudSync" ); d->m_settings.setValue( "enableSync", d->ui_cloudSyncSettings.kcfg_enableSync->isChecked() ); d->m_settings.setValue( "syncBackend", "owncloud" ); d->m_settings.setValue( "syncBookmarks", d->ui_cloudSyncSettings.kcfg_syncBookmarks->isChecked() ); d->m_settings.setValue( "syncRoutes", d->ui_cloudSyncSettings.kcfg_syncRoutes->isChecked() ); d->m_settings.setValue( "owncloudServer", d->ui_cloudSyncSettings.kcfg_owncloudServer->text() ); d->m_settings.setValue( "owncloudUsername", d->ui_cloudSyncSettings.kcfg_owncloudUsername->text() ); d->m_settings.setValue( "owncloudPassword", d->ui_cloudSyncSettings.kcfg_owncloudPassword->text() ); d->m_settings.endGroup(); // Plugins d->m_marbleWidget->writePluginSettings( d->m_settings ); emit settingsChanged(); } MarbleLocale::MeasurementSystem QtMarbleConfigDialog::measurementSystem() const { if( d->m_settings.contains( "View/distanceUnit" ) ) { return (MarbleLocale::MeasurementSystem)d->m_settings.value( "View/distanceUnit" ).toInt(); } MarbleLocale *locale = MarbleGlobal::getInstance()->locale(); return locale->measurementSystem(); } Marble::AngleUnit QtMarbleConfigDialog::angleUnit() const { return (Marble::AngleUnit) d->m_settings.value( "View/angleUnit", Marble::DMSDegree ).toInt(); } void QtMarbleConfigDialog::setAngleUnit(Marble::AngleUnit unit) { d->m_settings.setValue( "View/angleUnit", (int)unit ); d->ui_viewSettings.kcfg_angleUnit->setCurrentIndex( angleUnit() ); emit settingsChanged(); } Marble::MapQuality QtMarbleConfigDialog::stillQuality() const { return (Marble::MapQuality) d->m_settings.value( "View/stillQuality", Marble::HighQuality ).toInt(); } Marble::MapQuality QtMarbleConfigDialog::animationQuality() const { return (Marble::MapQuality) d->m_settings.value( "View/animationQuality", Marble::LowQuality ).toInt(); } QFont QtMarbleConfigDialog::mapFont() const { return d->m_settings.value( "View/mapFont", QApplication::font() ).value(); } int QtMarbleConfigDialog::onStartup() const { bool smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen; int defaultValue = smallScreen ? Marble::LastLocationVisited : Marble::ShowHomeLocation; return d->m_settings.value( "Navigation/onStartup", defaultValue ).toInt(); } QString QtMarbleConfigDialog::externalMapEditor() const { return d->m_settings.value( "Navigation/externalMapEditor", "" ).toString(); } bool QtMarbleConfigDialog::animateTargetVoyage() const { const bool smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen; return d->m_settings.value( "Navigation/animateTargetVoyage", smallScreen ).toBool(); } bool QtMarbleConfigDialog::inertialEarthRotation() const { return d->m_settings.value( "Navigation/inertialEarthRotation", true ).toBool(); } +bool QtMarbleConfigDialog::mouseViewRotation() const +{ + return d->m_settings.value( "Navigation/mouseViewRotation", true ).toBool(); +} + int QtMarbleConfigDialog::volatileTileCacheLimit() const { int defaultValue = (MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen) ? 6 : 100; return d->m_settings.value( "Cache/volatileTileCacheLimit", defaultValue ).toInt(); } int QtMarbleConfigDialog::persistentTileCacheLimit() const { return d->m_settings.value( "Cache/persistentTileCacheLimit", 0 ).toInt(); // default to unlimited } QString QtMarbleConfigDialog::proxyUrl() const { return d->m_settings.value( "Cache/proxyUrl", "" ).toString(); } int QtMarbleConfigDialog::proxyPort() const { return d->m_settings.value( "Cache/proxyPort", 8080 ).toInt(); } QString QtMarbleConfigDialog::proxyUser() const { return d->m_settings.value( "Cache/proxyUser", "" ).toString(); } QString QtMarbleConfigDialog::proxyPass() const { return d->m_settings.value( "Cache/proxyPass", "" ).toString(); } bool QtMarbleConfigDialog::proxyType() const { return d->m_settings.value( "Cache/proxyType", Marble::HttpProxy ).toInt(); } bool QtMarbleConfigDialog::proxyAuth() const { return d->m_settings.value( "Cache/proxyAuth", false ).toBool(); } bool QtMarbleConfigDialog::systemTimezone() const { return d->m_settings.value( "Time/systemTimezone", true ).toBool(); } bool QtMarbleConfigDialog::customTimezone() const { return d->m_settings.value( "Time/customTimezone", false ).toBool(); } bool QtMarbleConfigDialog::UTC() const { return d->m_settings.value( "Time/UTC", false ).toBool(); } bool QtMarbleConfigDialog::systemTime() const { return d->m_settings.value( "Time/systemTime", true ).toBool(); } bool QtMarbleConfigDialog::lastSessionTime() const { return d->m_settings.value( "Time/lastSessionTime", false ).toBool(); } int QtMarbleConfigDialog::chosenTimezone() const { return d->m_settings.value( "Time/chosenTimezone", 0 ).toInt(); } void QtMarbleConfigDialog::initializeCustomTimezone() { if( d->m_timezone.count() == 0) { d->m_timezone.insert( 0, 0 ); d->m_timezone.insert( 1, 3600 ); d->m_timezone.insert( 2, 7200 ); d->m_timezone.insert( 3, 7200 ); d->m_timezone.insert( 4, 10800 ); d->m_timezone.insert( 5, 12600 ); d->m_timezone.insert( 6, 14400 ); d->m_timezone.insert( 7, 18000 ); d->m_timezone.insert( 8, 19800 ); d->m_timezone.insert( 9, 21600 ); d->m_timezone.insert( 10, 25200 ); d->m_timezone.insert( 11, 28800 ); d->m_timezone.insert( 12, 32400 ); d->m_timezone.insert( 13, 34200 ); d->m_timezone.insert( 14, 36000 ); d->m_timezone.insert( 15, 39600 ); d->m_timezone.insert( 16, 43200 ); d->m_timezone.insert( 17, -39600 ); d->m_timezone.insert( 18, -36000 ); d->m_timezone.insert( 19, -32400 ); d->m_timezone.insert( 20, -28800 ); d->m_timezone.insert( 21, -25200 ); d->m_timezone.insert( 22, -25200 ); d->m_timezone.insert( 23, -21600 ); d->m_timezone.insert( 24, -18000 ); d->m_timezone.insert( 25, -18000 ); d->m_timezone.insert( 26, -14400 ); d->m_timezone.insert( 27, -12600 ); d->m_timezone.insert( 28, -10800 ); d->m_timezone.insert( 29, -10800 ); d->m_timezone.insert( 30, -3600 ); } } bool QtMarbleConfigDialog::syncEnabled() const { return d->m_settings.value( "CloudSync/enableSync", false ).toBool(); } QString QtMarbleConfigDialog::syncBackend() const { return d->m_settings.value( "CloudSync/syncBackend", "" ).toString(); } bool QtMarbleConfigDialog::syncBookmarks() const { return d->m_settings.value( "CloudSync/syncBookmarks", true ).toBool(); } bool QtMarbleConfigDialog::syncRoutes() const { return d->m_settings.value( "CloudSync/syncRoutes", true ).toBool(); } QString QtMarbleConfigDialog::owncloudServer() const { return d->m_settings.value( "CloudSync/owncloudServer", "" ).toString(); } QString QtMarbleConfigDialog::owncloudUsername() const { return d->m_settings.value( "CloudSync/owncloudUsername", "" ).toString(); } QString QtMarbleConfigDialog::owncloudPassword() const { return d->m_settings.value( "CloudSync/owncloudPassword", "" ).toString(); } } #include "moc_QtMarbleConfigDialog.cpp" diff --git a/src/lib/marble/QtMarbleConfigDialog.h b/src/lib/marble/QtMarbleConfigDialog.h index ef33bb447..c886945a4 100644 --- a/src/lib/marble/QtMarbleConfigDialog.h +++ b/src/lib/marble/QtMarbleConfigDialog.h @@ -1,170 +1,171 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2009 Bastian Holst // #ifndef MARBLE_QTMARBLECONFIGDIALOG_H #define MARBLE_QTMARBLECONFIGDIALOG_H #include #include "marble_export.h" #include "MarbleGlobal.h" #include "MarbleLocale.h" namespace Marble { class MarbleWidget; class CloudSyncManager; class QtMarbleConfigDialogPrivate; class MARBLE_EXPORT QtMarbleConfigDialog : public QDialog { Q_OBJECT public: explicit QtMarbleConfigDialog(MarbleWidget *marbleWidget, CloudSyncManager *syncManager = nullptr, QWidget *parent = nullptr ); ~QtMarbleConfigDialog() override; // View Settings MarbleLocale::MeasurementSystem measurementSystem() const; Marble::AngleUnit angleUnit() const; void setAngleUnit(Marble::AngleUnit unit); Marble::MapQuality stillQuality() const; Marble::MapQuality animationQuality() const; QFont mapFont() const; // Navigation Settings int onStartup() const; bool animateTargetVoyage() const; QString externalMapEditor() const; bool inertialEarthRotation() const; + bool mouseViewRotation() const; // Cache Settings int volatileTileCacheLimit() const; int persistentTileCacheLimit() const; QString proxyUrl() const; int proxyPort() const; QString proxyUser() const; QString proxyPass() const; bool proxyType() const; bool proxyAuth() const; // Time Settings /** * Read the value of 'Time/systemTime' key from settings */ bool systemTime() const; /** * Read the value of 'Time/lastSessionTime' key from settings */ bool lastSessionTime() const; /** * Read the value of 'Time/systemTimezone' key from settings */ bool systemTimezone() const; /** * Read the value of 'Time/UTC' key from settings */ bool UTC() const; /** * Read the value of 'Time/customTimezone' key from settings */ bool customTimezone() const; /** * Read the value of 'Time/chosenTimezone' key from settings */ int chosenTimezone() const; void initializeCustomTimezone(); // CloudSync settings bool syncEnabled() const; QString syncBackend() const; bool syncBookmarks() const; bool syncRoutes() const; QString owncloudServer() const; QString owncloudUsername() const; QString owncloudPassword() const; Q_SIGNALS: /** * This signal is emitted when the loaded settings were changed. * Either by the user or by loading them initially from disk. */ void settingsChanged(); /** * The user clicked on the button to clear volatile tile cache. */ void clearVolatileCacheClicked(); /** * The user clicked on the button to clear persistent tile cache. */ void clearPersistentCacheClicked(); /** * The user clicked on the button to manually synchronize bookmarks. */ void syncNowClicked(); public Q_SLOTS: /** * Disable "Sync Now" button while sync or for 30 sec of timout */ void disableSyncNow(); void enableSyncNow(); /** * Sets new title for the "Last Sync" label indicator */ void updateLastSync(); /** * Read settings and update interface. */ void readSettings(); /** * Show status on cloud sync settings tab */ void updateCloudSyncStatus( const QString &status ); /** * Write settings to disk. */ void writeSettings(); private Q_SLOTS: /** * Synchronize the loaded settings with the file on hard disk. */ void syncSettings(); void updateCloudSyncCredentials(); private: Q_DISABLE_COPY( QtMarbleConfigDialog ) QtMarbleConfigDialogPrivate * const d; }; } // Marble namespace #endif