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 = ℑ 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"