File indexing completed on 2024-04-21 03:49:45

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
0004 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
0005 // SPDX-FileCopyrightText: 2010-2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
0006 // SPDX-FileCopyrightText: 2012 Mohammed Nafees <nafees.technocool@gmail.com>
0007 //
0008 
0009 #include "MarbleWidget.h"
0010 
0011 #include <qmath.h>
0012 #include <QHash>
0013 #include <QSettings>
0014 #include <QElapsedTimer>
0015 #include <QPaintEvent>
0016 #include <QPaintEngine>
0017 #include <QRegion>
0018 #include <QNetworkProxy>
0019 #include <QMetaMethod>
0020 #include "DataMigration.h"
0021 #include "FpsLayer.h"
0022 #include "FileManager.h"
0023 #include "GeoDataLatLonAltBox.h"
0024 #include "GeoDataPlacemark.h"
0025 #include "GeoDataLookAt.h"
0026 #include "GeoPainter.h"
0027 #include "MarbleClock.h"
0028 #include "MarbleDebug.h"
0029 #include "MarbleDirs.h"
0030 #include "MarbleLocale.h"
0031 #include "MarbleMap.h"
0032 #include "MarbleModel.h"
0033 #include "MarbleWidgetInputHandler.h"
0034 #include "MarbleWidgetPopupMenu.h"
0035 #include "Planet.h"
0036 #include "PopupLayer.h"
0037 #include "RenderState.h"
0038 #include "RenderPlugin.h"
0039 #include "SunLocator.h"
0040 #include "TileCreatorDialog.h"
0041 #include "ViewportParams.h"
0042 #include "routing/RoutingLayer.h"
0043 #include "MarbleAbstractPresenter.h"
0044 #include "StyleBuilder.h"
0045 
0046 namespace Marble
0047 {
0048 
0049 class MarbleWidget::CustomPaintLayer : public LayerInterface
0050 {
0051  public:
0052     explicit CustomPaintLayer( MarbleWidget *widget )
0053         : m_widget( widget )
0054     {
0055     }
0056 
0057     QStringList renderPosition() const override { return QStringList() << "USER_TOOLS"; }
0058 
0059     bool render( GeoPainter *painter, ViewportParams *viewport,
0060                          const QString &renderPos, GeoSceneLayer *layer ) override
0061     {
0062         Q_UNUSED( viewport );
0063         Q_UNUSED( renderPos );
0064         Q_UNUSED( layer );
0065 
0066         painter->setPen( Qt::black );
0067         m_widget->customPaint( painter );
0068 
0069         return true;
0070     }
0071 
0072     qreal zValue() const override { return 1.0e7; }
0073 
0074     RenderState renderState() const override { return RenderState(QStringLiteral("Custom Widget Paint")); }
0075 
0076     QString runtimeTrace() const override { return QStringLiteral("MarbleWidget::CustomPaintLayer"); }
0077 
0078  private:
0079     MarbleWidget *const m_widget;
0080 };
0081 
0082 
0083 class MarbleWidgetPrivate
0084 {
0085  public:
0086     explicit MarbleWidgetPrivate( MarbleWidget *parent ) :
0087           m_widget( parent ),
0088           m_model(),
0089           m_map( &m_model ),
0090           m_presenter( &m_map ),
0091           m_inputhandler( nullptr ),
0092           m_routingLayer( nullptr ),
0093           m_mapInfoDialog( nullptr ),
0094           m_customPaintLayer( parent ),
0095           m_popupmenu( nullptr ),
0096           m_showFrameRate( false )
0097     {
0098     }
0099 
0100     ~MarbleWidgetPrivate()
0101     {
0102         m_map.removeLayer( &m_customPaintLayer );
0103         m_map.removeLayer( m_mapInfoDialog );
0104         delete m_mapInfoDialog;
0105         delete m_popupmenu;
0106     }
0107 
0108     void  construct();
0109 
0110     void updateMapTheme();
0111 
0112     void setInputHandler();
0113     void setInputHandler( MarbleWidgetInputHandler *handler );
0114 
0115     /**
0116       * @brief Update widget flags and cause a full repaint
0117       *
0118       * The background of the widget only needs to be redrawn in certain cases. This
0119       * method sets the widget flags accordingly and triggers a repaint.
0120       */
0121     void updateSystemBackgroundAttribute();
0122 
0123     MarbleWidget    *const m_widget;
0124 
0125     MarbleModel m_model;
0126     MarbleMap m_map;
0127 
0128     MarbleAbstractPresenter m_presenter;
0129 
0130     MarbleWidgetInputHandler  *m_inputhandler;
0131 
0132     RoutingLayer     *m_routingLayer;
0133     PopupLayer    *m_mapInfoDialog;
0134     MarbleWidget::CustomPaintLayer m_customPaintLayer;
0135 
0136     MarbleWidgetPopupMenu *m_popupmenu;
0137 
0138     bool             m_showFrameRate;
0139 };
0140 
0141 
0142 
0143 MarbleWidget::MarbleWidget(QWidget *parent)
0144     : QWidget( parent ),
0145       d( new MarbleWidgetPrivate( this ) )
0146 {
0147 //    setAttribute( Qt::WA_PaintOnScreen, true );
0148     d->construct();
0149 }
0150 
0151 MarbleWidget::~MarbleWidget()
0152 {
0153     // Remove and delete an existing InputHandler
0154     // initialized in d->construct()
0155     setInputHandler( nullptr );
0156 
0157     delete d;
0158 }
0159 
0160 void MarbleWidgetPrivate::construct()
0161 {
0162     QPointer<DataMigration> dataMigration = new DataMigration( m_widget );
0163     dataMigration->exec();
0164     delete dataMigration;
0165 
0166     // Widget settings
0167     m_widget->setMinimumSize( 200, 300 );
0168     m_widget->setFocusPolicy( Qt::WheelFocus );
0169     m_widget->setFocus( Qt::OtherFocusReason );
0170 
0171     // Set background: black.
0172     m_widget->setPalette( QPalette ( Qt::black ) );
0173 
0174     // Set whether the black space gets displayed or the earth gets simply
0175     // displayed on the widget background.
0176     m_widget->setAutoFillBackground( true );
0177 
0178     // Initialize the map and forward some signals.
0179     m_map.setSize( m_widget->width(), m_widget->height() );
0180     m_map.setShowFrameRate( false );  // never let the map draw the frame rate,
0181                                        // we do this differently here in the widget
0182 
0183     m_widget->connect( &m_presenter, SIGNAL(regionSelected(GeoDataLatLonBox)), m_widget, SIGNAL(regionSelected(GeoDataLatLonBox)) );
0184 
0185     m_widget->connect( &m_presenter, SIGNAL(zoomChanged(int)), m_widget, SIGNAL(zoomChanged(int)) );
0186     m_widget->connect( &m_presenter, SIGNAL(distanceChanged(QString)), m_widget, SIGNAL(distanceChanged(QString)) );
0187 
0188     // forward some signals of m_map
0189     m_widget->connect( &m_map,   SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
0190                        m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)) );
0191     m_widget->connect( &m_map,   SIGNAL(projectionChanged(Projection)),
0192                        m_widget, SIGNAL(projectionChanged(Projection)) );
0193     m_widget->connect( &m_map,   SIGNAL(tileLevelChanged(int)),
0194                        m_widget, SIGNAL(tileLevelChanged(int)) );
0195     m_widget->connect( &m_map,   SIGNAL(framesPerSecond(qreal)),
0196                        m_widget, SIGNAL(framesPerSecond(qreal)) );
0197     m_widget->connect( &m_map,   SIGNAL(viewContextChanged(ViewContext)),
0198                        m_widget, SLOT(setViewContext(ViewContext)) );
0199 
0200     m_widget->connect( &m_map,   SIGNAL(pluginSettingsChanged()),
0201                        m_widget, SIGNAL(pluginSettingsChanged()) );
0202     m_widget->connect( &m_map,   SIGNAL(renderPluginInitialized(RenderPlugin*)),
0203                        m_widget, SIGNAL(renderPluginInitialized(RenderPlugin*)) );
0204 
0205     // react to some signals of m_map
0206     m_widget->connect( &m_map,   SIGNAL(themeChanged(QString)),
0207                        m_widget, SLOT(updateMapTheme()) );
0208     m_widget->connect( &m_map,   SIGNAL(viewContextChanged(ViewContext)),
0209                        m_widget, SIGNAL(viewContextChanged(ViewContext)) );
0210     m_widget->connect( &m_map,   SIGNAL(repaintNeeded(QRegion)),
0211                        m_widget, SLOT(update()) );
0212     m_widget->connect( &m_map,   SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
0213                        m_widget, SLOT(updateSystemBackgroundAttribute()) );
0214     m_widget->connect( &m_map,   SIGNAL(renderStatusChanged(RenderStatus)),
0215                        m_widget, SIGNAL(renderStatusChanged(RenderStatus)) );
0216     m_widget->connect( &m_map,   SIGNAL(renderStateChanged(RenderState)),
0217                        m_widget, SIGNAL(renderStateChanged(RenderState)) );
0218 
0219     m_widget->connect( &m_map,   SIGNAL(propertyValueChanged(QString,bool)),
0220                        m_widget, SIGNAL(propertyValueChanged(QString,bool)) );
0221 
0222     m_widget->connect( m_model.fileManager(), SIGNAL(centeredDocument(GeoDataLatLonBox)),
0223                        m_widget, SLOT(centerOn(GeoDataLatLonBox)) );
0224 
0225 
0226     // Show a progress dialog when the model calculates new map tiles.
0227     m_widget->connect( &m_model, SIGNAL( creatingTilesStart( TileCreator*, const QString&,
0228                                                              const QString& ) ),
0229                        m_widget, SLOT( creatingTilesStart( TileCreator*, const QString&,
0230                                                            const QString& ) ) );
0231 
0232     m_popupmenu = new MarbleWidgetPopupMenu( m_widget, &m_model );
0233 
0234     m_routingLayer = new RoutingLayer( m_widget, m_widget );
0235     m_routingLayer->setPlacemarkModel( nullptr );
0236     QObject::connect( m_routingLayer, SIGNAL(repaintNeeded(QRect)),
0237                       m_widget, SLOT(update()) );
0238 
0239     m_mapInfoDialog = new PopupLayer( m_widget, m_widget );
0240     m_mapInfoDialog->setVisible( false );
0241     m_widget->connect( m_mapInfoDialog, SIGNAL(repaintNeeded()), m_widget, SLOT(update()) );
0242     m_map.addLayer( m_mapInfoDialog );
0243 
0244     setInputHandler();
0245     m_widget->setMouseTracking( true );
0246 
0247     m_map.addLayer( &m_customPaintLayer );
0248 
0249     m_widget->connect( m_inputhandler, SIGNAL(mouseClickGeoPosition(qreal,qreal,GeoDataCoordinates::Unit)),
0250                        m_widget, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)) );
0251     m_widget->setHighlightEnabled( true );
0252 
0253 }
0254 
0255 void MarbleWidgetPrivate::setInputHandler()
0256 {
0257     setInputHandler( new MarbleWidgetInputHandler( &m_presenter, m_widget ) );
0258 }
0259 
0260 void MarbleWidgetPrivate::setInputHandler( MarbleWidgetInputHandler *handler )
0261 {
0262     delete m_inputhandler;
0263     m_inputhandler = handler;
0264 
0265     if ( m_inputhandler )
0266     {
0267         m_widget->installEventFilter( m_inputhandler );
0268 
0269         QObject::connect( m_inputhandler, SIGNAL(mouseClickScreenPosition(int,int)),
0270                m_widget,       SLOT(notifyMouseClick(int,int)) );
0271 
0272         QObject::connect( m_inputhandler, SIGNAL(mouseMoveGeoPosition(QString)),
0273                  m_widget,       SIGNAL(mouseMoveGeoPosition(QString)) );
0274     }
0275 }
0276 
0277 void MarbleWidgetPrivate::updateSystemBackgroundAttribute()
0278 {
0279     // We only have to repaint the background every time if the earth
0280     // doesn't cover the whole image.
0281     const bool isOn = m_map.viewport()->mapCoversViewport() && !m_model.mapThemeId().isEmpty();
0282     m_widget->setAttribute( Qt::WA_NoSystemBackground, isOn );
0283 }
0284 
0285 // ----------------------------------------------------------------
0286 
0287 
0288 MarbleModel *MarbleWidget::model()
0289 {
0290     return &d->m_model;
0291 }
0292 
0293 const MarbleModel *MarbleWidget::model() const
0294 {
0295     return &d->m_model;
0296 }
0297 
0298 ViewportParams* MarbleWidget::viewport()
0299 {
0300     return d->m_map.viewport();
0301 }
0302 
0303 const ViewportParams* MarbleWidget::viewport() const
0304 {
0305     return d->m_map.viewport();
0306 }
0307 
0308 MarbleWidgetPopupMenu *MarbleWidget::popupMenu()
0309 {
0310     return d->m_popupmenu;
0311 }
0312 
0313 
0314 void MarbleWidget::setInputHandler( MarbleWidgetInputHandler *handler )
0315 {
0316     d->setInputHandler(handler);
0317 }
0318 
0319 MarbleWidgetInputHandler *MarbleWidget::inputHandler() const
0320 {
0321   return d->m_inputhandler;
0322 }
0323 
0324 int MarbleWidget::radius() const
0325 {
0326     return d->m_map.radius();
0327 }
0328 
0329 void MarbleWidget::setRadius( int radius )
0330 {
0331     d->m_map.setRadius( radius );
0332 }
0333 
0334 qreal MarbleWidget::moveStep() const
0335 {
0336     return d->m_presenter.moveStep();
0337 }
0338 
0339 int MarbleWidget::zoom() const
0340 {
0341     return d->m_presenter.logzoom();
0342 }
0343 
0344 int MarbleWidget::tileZoomLevel() const
0345 {
0346     return d->m_map.tileZoomLevel();
0347 }
0348 
0349 int  MarbleWidget::minimumZoom() const
0350 {
0351     return d->m_map.minimumZoom();
0352 }
0353 
0354 int  MarbleWidget::maximumZoom() const
0355 {
0356     return d->m_map.maximumZoom();
0357 }
0358 
0359 QVector<const GeoDataFeature*> MarbleWidget::whichFeatureAt( const QPoint &curpos ) const
0360 {
0361     return d->m_map.whichFeatureAt( curpos );
0362 }
0363 
0364 QList<AbstractDataPluginItem*> MarbleWidget::whichItemAt( const QPoint &curpos ) const
0365 {
0366     return d->m_map.whichItemAt( curpos );
0367 }
0368 
0369 void MarbleWidget::addLayer( LayerInterface *layer )
0370 {
0371     d->m_map.addLayer( layer );
0372 }
0373 
0374 void MarbleWidget::removeLayer( LayerInterface *layer )
0375 {
0376     d->m_map.removeLayer( layer );
0377 }
0378 
0379 Marble::TextureLayer* MarbleWidget::textureLayer() const
0380 {
0381     return d->m_map.textureLayer();
0382 }
0383 
0384 VectorTileLayer *MarbleWidget::vectorTileLayer() const
0385 {
0386     return d->m_map.vectorTileLayer();
0387 }
0388 
0389 QPixmap MarbleWidget::mapScreenShot()
0390 {
0391     return grab();
0392 }
0393 
0394 RenderStatus MarbleWidget::renderStatus() const
0395 {
0396     return d->m_map.renderStatus();
0397 }
0398 
0399 RenderState MarbleWidget::renderState() const
0400 {
0401     return d->m_map.renderState();
0402 }
0403 
0404 void MarbleWidget::setHighlightEnabled(bool enabled)
0405 {
0406     if ( enabled ) {
0407         connect( this, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
0408                  &d->m_map, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
0409                  Qt::UniqueConnection );
0410     }
0411     else {
0412         disconnect( this, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
0413                  &d->m_map, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)) );
0414     }
0415 }
0416 
0417 bool MarbleWidget::showOverviewMap() const
0418 {
0419     return d->m_map.showOverviewMap();
0420 }
0421 
0422 bool MarbleWidget::showScaleBar() const
0423 {
0424     return d->m_map.showScaleBar();
0425 }
0426 
0427 bool MarbleWidget::showCompass() const
0428 {
0429     return d->m_map.showCompass();
0430 }
0431 
0432 bool MarbleWidget::showClouds() const
0433 {
0434     return d->m_map.showClouds();
0435 }
0436 
0437 bool MarbleWidget::showSunShading() const
0438 {
0439     return d->m_map.showSunShading();
0440 }
0441 
0442 bool MarbleWidget::showCityLights() const
0443 {
0444     return d->m_map.showCityLights();
0445 }
0446 
0447 bool MarbleWidget::isLockedToSubSolarPoint() const
0448 {
0449     return d->m_map.isLockedToSubSolarPoint();
0450 }
0451 
0452 bool MarbleWidget::isSubSolarPointIconVisible() const
0453 {
0454     return d->m_map.isSubSolarPointIconVisible();
0455 }
0456 
0457 bool MarbleWidget::showAtmosphere() const
0458 {
0459     return d->m_map.showAtmosphere();
0460 }
0461 
0462 bool MarbleWidget::showCrosshairs() const
0463 {
0464     return d->m_map.showCrosshairs();
0465 }
0466 
0467 bool MarbleWidget::showGrid() const
0468 {
0469     return d->m_map.showGrid();
0470 }
0471 
0472 bool MarbleWidget::showPlaces() const
0473 {
0474     return d->m_map.showPlaces();
0475 }
0476 
0477 bool MarbleWidget::showCities() const
0478 {
0479     return d->m_map.showCities();
0480 }
0481 
0482 bool MarbleWidget::showTerrain() const
0483 {
0484     return d->m_map.showTerrain();
0485 }
0486 
0487 bool MarbleWidget::showOtherPlaces() const
0488 {
0489     return d->m_map.showOtherPlaces();
0490 }
0491 
0492 bool MarbleWidget::showRelief() const
0493 {
0494     return d->m_map.showRelief();
0495 }
0496 
0497 bool MarbleWidget::showIceLayer() const
0498 {
0499     return d->m_map.showIceLayer();
0500 }
0501 
0502 bool MarbleWidget::showBorders() const
0503 {
0504     return d->m_map.showBorders();
0505 }
0506 
0507 bool MarbleWidget::showRivers() const
0508 {
0509     return d->m_map.showRivers();
0510 }
0511 
0512 bool MarbleWidget::showLakes() const
0513 {
0514     return d->m_map.showLakes();
0515 }
0516 
0517 bool MarbleWidget::showFrameRate() const
0518 {
0519     return d->m_showFrameRate;
0520 }
0521 
0522 bool MarbleWidget::showBackground() const
0523 {
0524     return d->m_map.showBackground();
0525 }
0526 
0527 quint64 MarbleWidget::volatileTileCacheLimit() const
0528 {
0529     return d->m_map.volatileTileCacheLimit();
0530 }
0531 
0532 
0533 void MarbleWidget::setZoom( int newZoom, FlyToMode mode )
0534 {
0535     d->m_inputhandler->stopInertialEarthRotation();
0536     d->m_presenter.setZoom( newZoom, mode );
0537 }
0538 
0539 void MarbleWidget::zoomView( int zoom, FlyToMode mode )
0540 {
0541     d->m_inputhandler->stopInertialEarthRotation();
0542     d->m_presenter.zoomView( zoom, mode );
0543 }
0544 
0545 
0546 void MarbleWidget::zoomViewBy( int zoomStep, FlyToMode mode )
0547 {
0548     d->m_inputhandler->stopInertialEarthRotation();
0549     d->m_presenter.zoomViewBy( zoomStep, mode );
0550 }
0551 
0552 
0553 void MarbleWidget::zoomIn( FlyToMode mode )
0554 {
0555     d->m_inputhandler->stopInertialEarthRotation();
0556     d->m_presenter.zoomIn( mode );
0557 }
0558 
0559 void MarbleWidget::zoomOut( FlyToMode mode )
0560 {
0561     d->m_inputhandler->stopInertialEarthRotation();
0562     d->m_presenter.zoomOut( mode );
0563 }
0564 
0565 void MarbleWidget::rotateBy( const qreal deltaLon, const qreal deltaLat, FlyToMode mode )
0566 {
0567     d->m_inputhandler->stopInertialEarthRotation();
0568     d->m_presenter.rotateBy( deltaLon, deltaLat, mode );
0569 }
0570 
0571 
0572 void MarbleWidget::centerOn( const qreal lon, const qreal lat, bool animated )
0573 {
0574     d->m_inputhandler->stopInertialEarthRotation();
0575     d->m_presenter.centerOn( lon, lat, animated );
0576 }
0577 
0578 void MarbleWidget::centerOn( const GeoDataCoordinates &position, bool animated )
0579 {
0580     d->m_inputhandler->stopInertialEarthRotation();
0581     d->m_presenter.centerOn( position, animated );
0582 }
0583 
0584 void MarbleWidget::centerOn( const GeoDataLatLonBox &box, bool animated )
0585 {
0586     d->m_inputhandler->stopInertialEarthRotation();
0587    d->m_presenter.centerOn( box, animated );
0588 }
0589 
0590 void MarbleWidget::centerOn( const GeoDataPlacemark& placemark, bool animated )
0591 {
0592     d->m_inputhandler->stopInertialEarthRotation();
0593     d->m_presenter.centerOn( placemark, animated );
0594 }
0595 
0596 void MarbleWidget::setCenterLatitude( qreal lat, FlyToMode mode )
0597 {
0598     d->m_inputhandler->stopInertialEarthRotation();
0599     d->m_presenter.setCenterLatitude( lat, mode );
0600 }
0601 
0602 void MarbleWidget::setCenterLongitude( qreal lon, FlyToMode mode )
0603 {
0604     d->m_inputhandler->stopInertialEarthRotation();
0605     d->m_presenter.setCenterLongitude( lon, mode );
0606 }
0607 
0608 Projection MarbleWidget::projection() const
0609 {
0610     return d->m_map.projection();
0611 }
0612 
0613 void MarbleWidget::setProjection( Projection projection )
0614 {
0615     d->m_map.setProjection( projection );
0616 }
0617 
0618 void MarbleWidget::setProjection( int projection )
0619 {
0620     setProjection( Projection( qAbs( projection ) % (Mercator+1) ) );
0621 }
0622 
0623 void MarbleWidget::moveLeft( FlyToMode mode )
0624 {
0625     d->m_inputhandler->stopInertialEarthRotation();
0626     d->m_presenter.moveByStep( -1, 0, mode );
0627 }
0628 
0629 void MarbleWidget::moveRight( FlyToMode mode )
0630 {
0631     d->m_inputhandler->stopInertialEarthRotation();
0632     d->m_presenter.moveByStep( 1, 0, mode );
0633 }
0634 
0635 void MarbleWidget::moveUp( FlyToMode mode )
0636 {
0637     d->m_inputhandler->stopInertialEarthRotation();
0638     d->m_presenter.moveByStep( 0, -1, mode );
0639 }
0640 
0641 void MarbleWidget::moveDown( FlyToMode mode )
0642 {
0643     d->m_inputhandler->stopInertialEarthRotation();
0644     d->m_presenter.moveByStep( 0, 1, mode );
0645 }
0646 
0647 void MarbleWidget::leaveEvent( QEvent* )
0648 {
0649     emit mouseMoveGeoPosition( QCoreApplication::translate( "Marble", NOT_AVAILABLE ) );
0650 }
0651 
0652 void MarbleWidget::resizeEvent( QResizeEvent *event )
0653 {
0654     setUpdatesEnabled( false );
0655     d->m_map.setSize( event->size() );
0656     setUpdatesEnabled( true );
0657 
0658     QWidget::resizeEvent( event );
0659 }
0660 
0661 void MarbleWidget::connectNotify( const QMetaMethod &signal )
0662 {
0663     if ( d->m_inputhandler && signal == QMetaMethod::fromSignal( &MarbleWidget::mouseMoveGeoPosition ) ) {
0664         d->m_inputhandler->setPositionSignalConnected( true );
0665     }
0666 }
0667 
0668 void MarbleWidget::disconnectNotify( const QMetaMethod &signal )
0669 {
0670     if ( d->m_inputhandler && signal == QMetaMethod::fromSignal( &MarbleWidget::mouseMoveGeoPosition ) ) {
0671         d->m_inputhandler->setPositionSignalConnected( false );
0672     }
0673 }
0674 
0675 bool MarbleWidget::screenCoordinates( qreal lon, qreal lat,
0676                                       qreal& x, qreal& y ) const
0677 {
0678     return d->m_map.screenCoordinates( lon, lat, x, y );
0679 }
0680 
0681 bool MarbleWidget::geoCoordinates( int x, int y,
0682                                    qreal& lon, qreal& lat,
0683                                    GeoDataCoordinates::Unit unit ) const
0684 {
0685     return d->m_map.geoCoordinates( x, y, lon, lat, unit );
0686 }
0687 
0688 qreal MarbleWidget::centerLatitude() const
0689 {
0690     return d->m_map.centerLatitude();
0691 }
0692 
0693 qreal MarbleWidget::centerLongitude() const
0694 {
0695     return d->m_map.centerLongitude();
0696 }
0697 
0698 QRegion MarbleWidget::mapRegion() const
0699 {
0700     return viewport()->mapRegion();
0701 }
0702 
0703 void MarbleWidget::paintEvent( QPaintEvent *evt )
0704 {
0705     QElapsedTimer t;
0706     t.start();
0707 
0708     QPaintDevice *paintDevice = this;
0709     QImage image;
0710     if (!isEnabled())
0711     {
0712         // If the globe covers fully the screen then we can use the faster
0713         // RGB32 as there are no translucent areas involved.
0714         QImage::Format imageFormat = ( d->m_map.viewport()->mapCoversViewport() )
0715                                      ? QImage::Format_RGB32
0716                                      : QImage::Format_ARGB32_Premultiplied;
0717         // Paint to an intermediate image
0718         image = QImage( rect().size(), imageFormat );
0719         image.fill( Qt::transparent );
0720         paintDevice = &image;
0721     }
0722 
0723     {
0724         // FIXME: Better way to get the GeoPainter
0725         // Create a painter that will do the painting.
0726         GeoPainter geoPainter( paintDevice, d->m_map.viewport(), d->m_map.mapQuality() );
0727 
0728         d->m_map.paint( geoPainter, evt->rect() );
0729     }
0730 
0731     if ( !isEnabled() )
0732     {
0733         // Draw a grayscale version of the intermediate image
0734         QRgb* pixel = reinterpret_cast<QRgb*>( image.scanLine( 0 ));
0735         for (int i=0; i<image.width()*image.height(); ++i, ++pixel) {
0736             int gray = qGray( *pixel );
0737             *pixel = qRgb( gray, gray, gray );
0738         }
0739 
0740         QPainter widgetPainter( this );
0741         widgetPainter.drawImage( rect(), image );
0742     }
0743 
0744     if ( d->m_showFrameRate )
0745     {
0746         QPainter painter( this );
0747         FpsLayer fpsPainter( &t );
0748         fpsPainter.paint( &painter );
0749 
0750         const qreal fps = 1000.0 / (qreal)( t.elapsed() + 1 );
0751         emit framesPerSecond( fps );
0752     }
0753 }
0754 
0755 void MarbleWidget::customPaint( GeoPainter *painter )
0756 {
0757     Q_UNUSED( painter );
0758     /* This is a NOOP in the base class*/
0759 }
0760 
0761 
0762 void MarbleWidget::goHome( FlyToMode mode )
0763 {
0764     d->m_inputhandler->stopInertialEarthRotation();
0765     d->m_presenter.goHome( mode );
0766 }
0767 
0768 QString MarbleWidget::mapThemeId() const
0769 {
0770     return d->m_model.mapThemeId();
0771 }
0772 
0773 void MarbleWidget::setMapThemeId( const QString& mapThemeId )
0774 {
0775     d->m_map.setMapThemeId( mapThemeId );
0776 }
0777 
0778 void MarbleWidgetPrivate::updateMapTheme()
0779 {
0780     m_map.removeLayer( m_routingLayer );
0781 
0782     m_widget->setRadius( m_widget->radius() ); // Corrects zoom range, if needed
0783 
0784     if (m_model.planetId() == QLatin1String("earth")) {
0785         m_map.addLayer( m_routingLayer );
0786     }
0787 
0788     emit m_widget->themeChanged( m_map.mapThemeId() );
0789 
0790     // Now we want a full repaint as the atmosphere might differ
0791     m_widget->setAttribute( Qt::WA_NoSystemBackground, false );
0792 
0793     m_widget->update();
0794 }
0795 
0796 GeoSceneDocument *MarbleWidget::mapTheme() const
0797 {
0798     return d->m_model.mapTheme();
0799 }
0800 
0801 void MarbleWidget::setPropertyValue( const QString& name, bool value )
0802 {
0803     mDebug() << "In MarbleWidget the property " << name << "was set to " << value;
0804     d->m_map.setPropertyValue( name, value );
0805 }
0806 
0807 void MarbleWidget::setShowOverviewMap( bool visible )
0808 {
0809     d->m_map.setShowOverviewMap( visible );
0810 }
0811 
0812 void MarbleWidget::setShowScaleBar( bool visible )
0813 {
0814     d->m_map.setShowScaleBar( visible );
0815 }
0816 
0817 void MarbleWidget::setShowCompass( bool visible )
0818 {
0819     d->m_map.setShowCompass( visible );
0820 }
0821 
0822 void MarbleWidget::setShowClouds( bool visible )
0823 {
0824     d->m_map.setShowClouds( visible );
0825 }
0826 
0827 void MarbleWidget::setShowSunShading( bool visible )
0828 {
0829     d->m_map.setShowSunShading( visible );
0830 }
0831 
0832 void MarbleWidget::setShowCityLights( bool visible )
0833 {
0834     d->m_map.setShowCityLights( visible );
0835 }
0836 
0837 void MarbleWidget::setLockToSubSolarPoint( bool visible )
0838 {
0839     if ( d->m_map.isLockedToSubSolarPoint() != visible ) { // Toggling input modifies event filters, so avoid that if not needed
0840         d->m_map.setLockToSubSolarPoint( visible );
0841         setInputEnabled( !d->m_map.isLockedToSubSolarPoint() );
0842     }
0843 }
0844 
0845 void MarbleWidget::setSubSolarPointIconVisible( bool visible )
0846 {
0847     if ( d->m_map.isSubSolarPointIconVisible() != visible ) {
0848         d->m_map.setSubSolarPointIconVisible( visible );
0849     }
0850 
0851     QList<RenderPlugin *> pluginList = renderPlugins();
0852     QList<RenderPlugin *>::const_iterator i = pluginList.constBegin();
0853     QList<RenderPlugin *>::const_iterator const end = pluginList.constEnd();
0854     for (; i != end; ++i ) {
0855         if ((*i)->nameId() == QLatin1String("sun")) {
0856             (*i)->setVisible( visible );
0857         }
0858     }
0859 }
0860 
0861 void MarbleWidget::setShowAtmosphere( bool visible )
0862 {
0863     d->m_map.setShowAtmosphere( visible );
0864 }
0865 
0866 void MarbleWidget::setShowCrosshairs( bool visible )
0867 {
0868     d->m_map.setShowCrosshairs( visible );
0869 }
0870 
0871 void MarbleWidget::setShowGrid( bool visible )
0872 {
0873     d->m_map.setShowGrid( visible );
0874 }
0875 
0876 void MarbleWidget::setShowPlaces( bool visible )
0877 {
0878     d->m_map.setShowPlaces( visible );
0879 }
0880 
0881 void MarbleWidget::setShowCities( bool visible )
0882 {
0883     d->m_map.setShowCities( visible );
0884 }
0885 
0886 void MarbleWidget::setShowTerrain( bool visible )
0887 {
0888     d->m_map.setShowTerrain( visible );
0889 }
0890 
0891 void MarbleWidget::setShowOtherPlaces( bool visible )
0892 {
0893     d->m_map.setShowOtherPlaces( visible );
0894 }
0895 
0896 void MarbleWidget::setShowRelief( bool visible )
0897 {
0898     d->m_map.setShowRelief( visible );
0899 }
0900 
0901 void MarbleWidget::setShowIceLayer( bool visible )
0902 {
0903     d->m_map.setShowIceLayer( visible );
0904 }
0905 
0906 void MarbleWidget::setShowBorders( bool visible )
0907 {
0908     d->m_map.setShowBorders( visible );
0909 }
0910 
0911 void MarbleWidget::setShowRivers( bool visible )
0912 {
0913     d->m_map.setShowRivers( visible );
0914 }
0915 
0916 void MarbleWidget::setShowLakes( bool visible )
0917 {
0918     d->m_map.setShowLakes( visible );
0919 }
0920 
0921 void MarbleWidget::setShowFrameRate( bool visible )
0922 {
0923     d->m_showFrameRate = visible;
0924 
0925     update();
0926 }
0927 
0928 void MarbleWidget::setShowBackground( bool visible )
0929 {
0930     d->m_map.setShowBackground( visible );
0931 }
0932 
0933 void MarbleWidget::setShowRuntimeTrace( bool visible )
0934 {
0935     d->m_map.setShowRuntimeTrace( visible );
0936 }
0937 
0938 bool MarbleWidget::showRuntimeTrace() const
0939 {
0940     return d->m_map.showRuntimeTrace();
0941 }
0942 
0943 void MarbleWidget::setShowDebugPolygons( bool visible)
0944 {
0945     d->m_map.setShowDebugPolygons( visible );
0946 }
0947 
0948 bool MarbleWidget::showDebugPolygons() const
0949 {
0950     return d->m_map.showDebugPolygons();
0951 }
0952 
0953 void MarbleWidget::setShowDebugBatchRender( bool visible)
0954 {
0955     d->m_map.setShowDebugBatchRender( visible );
0956 }
0957 
0958 bool MarbleWidget::showDebugBatchRender() const
0959 {
0960     return d->m_map.showDebugBatchRender();
0961 }
0962 
0963 void MarbleWidget::setShowDebugPlacemarks( bool visible)
0964 {
0965     d->m_map.setShowDebugPlacemarks( visible );
0966 }
0967 
0968 bool MarbleWidget::showDebugPlacemarks() const
0969 {
0970     return d->m_map.showDebugPlacemarks();
0971 }
0972 
0973 void MarbleWidget::setDebugLevelTags(bool visible)
0974 {
0975     d->m_map.setLevelTagDebugModeEnabled(visible);
0976 }
0977 
0978 bool MarbleWidget::debugLevelTags() const
0979 {
0980     return d->m_map.levelTagDebugModeEnabled();
0981 }
0982 
0983 void MarbleWidget::setShowTileId( bool visible )
0984 {
0985     d->m_map.setShowTileId( visible );
0986 }
0987 
0988 void MarbleWidget::notifyMouseClick( int x, int y)
0989 {
0990     qreal  lon   = 0;
0991     qreal  lat   = 0;
0992 
0993     bool const valid = geoCoordinates( x, y, lon, lat, GeoDataCoordinates::Radian );
0994 
0995     if ( valid ) {
0996         emit mouseClickGeoPosition( lon, lat, GeoDataCoordinates::Radian );
0997     }
0998 }
0999 
1000 void MarbleWidget::clearVolatileTileCache()
1001 {
1002     mDebug() << "About to clear VolatileTileCache";
1003     d->m_map.clearVolatileTileCache();
1004 }
1005 
1006 void MarbleWidget::setVolatileTileCacheLimit( quint64 kiloBytes )
1007 {
1008     d->m_map.setVolatileTileCacheLimit( kiloBytes );
1009 }
1010 
1011 // This slot will called when the Globe starts to create the tiles.
1012 
1013 void MarbleWidget::creatingTilesStart( TileCreator *creator,
1014                                        const QString &name, 
1015                                        const QString &description )
1016 {
1017     QPointer<TileCreatorDialog> dialog = new TileCreatorDialog( creator, this );
1018     dialog->setSummary( name, description );
1019     dialog->exec();
1020     delete dialog;
1021 }
1022 
1023 MapQuality MarbleWidget::mapQuality( ViewContext viewContext ) const
1024 {
1025     return d->m_map.mapQuality( viewContext );
1026 }
1027 
1028 void MarbleWidget::setMapQualityForViewContext( MapQuality quality, ViewContext viewContext )
1029 {
1030     d->m_map.setMapQualityForViewContext( quality, viewContext );
1031 }
1032 
1033 ViewContext MarbleWidget::viewContext() const
1034 {
1035     return d->m_map.viewContext();
1036 }
1037 
1038 void MarbleWidget::setViewContext( ViewContext viewContext )
1039 {
1040     // Inform routing layer about view context change. If not done,
1041     // the routing layer causes severe performance problems when dragging the
1042     // map. So either do not remove this line, or keep a similar call in place
1043     // when you refactor it and test your changes wrt drag performance at
1044     // high zoom level with long routes!
1045     d->m_routingLayer->setViewContext( viewContext );
1046 
1047     d->m_map.setViewContext( viewContext );
1048 }
1049 
1050 bool MarbleWidget::animationsEnabled() const
1051 {
1052     return d->m_presenter.animationsEnabled();
1053 }
1054 
1055 void MarbleWidget::setAnimationsEnabled( bool enabled )
1056 {
1057     d->m_presenter.setAnimationsEnabled( enabled );
1058 }
1059 
1060 AngleUnit MarbleWidget::defaultAngleUnit() const
1061 {
1062     return d->m_map.defaultAngleUnit();
1063 }
1064 
1065 void MarbleWidget::setDefaultAngleUnit( AngleUnit angleUnit )
1066 {
1067     d->m_map.setDefaultAngleUnit( angleUnit );
1068 }
1069 
1070 QFont MarbleWidget::defaultFont() const
1071 {
1072     return d->m_map.defaultFont();
1073 }
1074 
1075 void MarbleWidget::setDefaultFont( const QFont& font )
1076 {
1077     d->m_map.setDefaultFont( font );
1078 }
1079 
1080 void MarbleWidget::setSelection( const QRect& region )
1081 {
1082     d->m_presenter.setSelection( region );
1083 }
1084 
1085 qreal MarbleWidget::distance() const
1086 {
1087     return d->m_presenter.distance();
1088 }
1089 
1090 void MarbleWidget::setDistance( qreal newDistance )
1091 {
1092     d->m_presenter.setDistance( newDistance );
1093 }
1094 
1095 QString MarbleWidget::distanceString() const
1096 {
1097     return d->m_presenter.distanceString();
1098 }
1099 
1100 void MarbleWidget::setInputEnabled( bool enabled )
1101 {
1102     //if input is set as enabled
1103     if ( enabled )
1104     {
1105         if ( !d->m_inputhandler ) {
1106             d->setInputHandler();
1107         }
1108         else {
1109             installEventFilter( d->m_inputhandler );
1110         }
1111     }
1112 
1113     else // input is disabled
1114     {
1115         mDebug() << "MarbleWidget::disableInput";
1116         removeEventFilter( d->m_inputhandler );
1117         setCursor( Qt::ArrowCursor );
1118     }
1119 }
1120 
1121 QList<RenderPlugin *> MarbleWidget::renderPlugins() const
1122 {
1123     return d->m_map.renderPlugins();
1124 }
1125 
1126 void MarbleWidget::readPluginSettings( QSettings& settings )
1127 {
1128     for( RenderPlugin *plugin: renderPlugins() ) {
1129         settings.beginGroup(QLatin1String("plugin_") + plugin->nameId());
1130 
1131         QHash<QString,QVariant> hash;
1132 
1133         for ( const QString& key: settings.childKeys() ) {
1134             hash.insert( key, settings.value( key ) );
1135         }
1136 
1137         plugin->setSettings( hash );
1138 
1139         settings.endGroup();
1140     }
1141 }
1142 
1143 void MarbleWidget::writePluginSettings( QSettings& settings ) const
1144 {
1145     for( RenderPlugin *plugin: renderPlugins() ) {
1146         settings.beginGroup(QLatin1String("plugin_") + plugin->nameId());
1147 
1148         QHash<QString,QVariant> hash = plugin->settings();
1149 
1150         QHash<QString,QVariant>::iterator it = hash.begin();
1151         while( it != hash.end() ) {
1152             settings.setValue( it.key(), it.value() );
1153             ++it;
1154         }
1155 
1156         settings.endGroup();
1157     }
1158 }
1159 
1160 QList<AbstractFloatItem *> MarbleWidget::floatItems() const
1161 {
1162     return d->m_map.floatItems();
1163 }
1164 
1165 AbstractFloatItem * MarbleWidget::floatItem( const QString &nameId ) const
1166 {
1167     return d->m_map.floatItem( nameId );
1168 }
1169 
1170 void MarbleWidget::changeEvent( QEvent * event )
1171 {
1172     if ( event->type() == QEvent::EnabledChange )
1173     {
1174         setInputEnabled(isEnabled());
1175     }
1176 
1177     QWidget::changeEvent(event);
1178 }
1179 
1180 void MarbleWidget::flyTo( const GeoDataLookAt &newLookAt, FlyToMode mode )
1181 {
1182     d->m_inputhandler->stopInertialEarthRotation();
1183     d->m_presenter.flyTo( newLookAt, mode );
1184 }
1185 
1186 void MarbleWidget::reloadMap()
1187 {
1188     d->m_map.reload();
1189 }
1190 
1191 void MarbleWidget::downloadRegion( QVector<TileCoordsPyramid> const & pyramid )
1192 {
1193     d->m_map.downloadRegion( pyramid );
1194 }
1195 
1196 GeoDataLookAt MarbleWidget::lookAt() const
1197 {
1198     return d->m_presenter.lookAt();
1199 }
1200 
1201 GeoDataCoordinates MarbleWidget::focusPoint() const
1202 {
1203     return d->m_map.viewport()->focusPoint();
1204 }
1205 
1206 void MarbleWidget::setFocusPoint( const GeoDataCoordinates &focusPoint )
1207 {
1208     d->m_map.viewport()->setFocusPoint( focusPoint );
1209 }
1210 
1211 void MarbleWidget::resetFocusPoint()
1212 {
1213     d->m_map.viewport()->resetFocusPoint();
1214 }
1215 
1216 qreal MarbleWidget::radiusFromDistance( qreal distance ) const
1217 {
1218     return d->m_presenter.radiusFromDistance( distance );
1219 }
1220 
1221 qreal MarbleWidget::distanceFromRadius( qreal radius ) const
1222 {
1223     return d->m_presenter.distanceFromRadius( radius );
1224 }
1225 
1226 qreal MarbleWidget::zoomFromDistance( qreal distance ) const
1227 {
1228     return d->m_presenter.zoomFromDistance( distance );
1229 }
1230 
1231 qreal MarbleWidget::distanceFromZoom( qreal zoom ) const
1232 {
1233     return d->m_presenter.distanceFromZoom( zoom );
1234 }
1235 
1236 RoutingLayer* MarbleWidget::routingLayer()
1237 {
1238     return d->m_routingLayer;
1239 }
1240 
1241 PopupLayer *MarbleWidget::popupLayer()
1242 {
1243     return d->m_mapInfoDialog;
1244 }
1245 
1246 const StyleBuilder* MarbleWidget::styleBuilder() const
1247 {
1248     return d->m_map.styleBuilder();
1249 }
1250 
1251 void MarbleWidget::setHeading( qreal heading )
1252 {
1253     d->m_map.setHeading( heading );
1254 }
1255 
1256 qreal MarbleWidget::heading() const
1257 {
1258     return d->m_map.heading();
1259 }
1260 
1261 void MarbleWidget::setLevelToDebug(int level)
1262 {
1263     d->m_map.setDebugLevelTag(level);
1264 }
1265 
1266 int MarbleWidget::levelToDebug() const
1267 {
1268     return d->m_map.debugLevelTag();
1269 }
1270 
1271 }
1272 
1273 #include "moc_MarbleWidget.cpp"