1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
4 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5 // SPDX-FileCopyrightText: 2010-2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
6 // SPDX-FileCopyrightText: 2012 Mohammed Nafees <nafees.technocool@gmail.com>
7 //
8 
9 #include "MarbleWidget.h"
10 
11 #include <qmath.h>
12 #include <QHash>
13 #include <QSettings>
14 #include <QElapsedTimer>
15 #include <QPaintEvent>
16 #include <QPaintEngine>
17 #include <QRegion>
18 #include <QNetworkProxy>
19 #include <QMetaMethod>
20 #include "DataMigration.h"
21 #include "FpsLayer.h"
22 #include "FileManager.h"
23 #include "GeoDataLatLonAltBox.h"
24 #include "GeoDataPlacemark.h"
25 #include "GeoDataLookAt.h"
26 #include "GeoPainter.h"
27 #include "MarbleClock.h"
28 #include "MarbleDebug.h"
29 #include "MarbleDirs.h"
30 #include "MarbleLocale.h"
31 #include "MarbleMap.h"
32 #include "MarbleModel.h"
33 #include "MarbleWidgetInputHandler.h"
34 #include "MarbleWidgetPopupMenu.h"
35 #include "Planet.h"
36 #include "PopupLayer.h"
37 #include "RenderState.h"
38 #include "RenderPlugin.h"
39 #include "SunLocator.h"
40 #include "TileCreatorDialog.h"
41 #include "ViewportParams.h"
42 #include "routing/RoutingLayer.h"
43 #include "MarbleAbstractPresenter.h"
44 #include "StyleBuilder.h"
45 
46 namespace Marble
47 {
48 
49 class MarbleWidget::CustomPaintLayer : public LayerInterface
50 {
51  public:
CustomPaintLayer(MarbleWidget * widget)52     explicit CustomPaintLayer( MarbleWidget *widget )
53         : m_widget( widget )
54     {
55     }
56 
renderPosition() const57     QStringList renderPosition() const override { return QStringList() << "USER_TOOLS"; }
58 
render(GeoPainter * painter,ViewportParams * viewport,const QString & renderPos,GeoSceneLayer * layer)59     bool render( GeoPainter *painter, ViewportParams *viewport,
60                          const QString &renderPos, GeoSceneLayer *layer ) override
61     {
62         Q_UNUSED( viewport );
63         Q_UNUSED( renderPos );
64         Q_UNUSED( layer );
65 
66         painter->setPen( Qt::black );
67         m_widget->customPaint( painter );
68 
69         return true;
70     }
71 
zValue() const72     qreal zValue() const override { return 1.0e7; }
73 
renderState() const74     RenderState renderState() const override { return RenderState(QStringLiteral("Custom Widget Paint")); }
75 
runtimeTrace() const76     QString runtimeTrace() const override { return QStringLiteral("MarbleWidget::CustomPaintLayer"); }
77 
78  private:
79     MarbleWidget *const m_widget;
80 };
81 
82 
83 class MarbleWidgetPrivate
84 {
85  public:
MarbleWidgetPrivate(MarbleWidget * parent)86     explicit MarbleWidgetPrivate( MarbleWidget *parent ) :
87           m_widget( parent ),
88           m_model(),
89           m_map( &m_model ),
90           m_presenter( &m_map ),
91           m_inputhandler( nullptr ),
92           m_routingLayer( nullptr ),
93           m_mapInfoDialog( nullptr ),
94           m_customPaintLayer( parent ),
95           m_popupmenu( nullptr ),
96           m_showFrameRate( false )
97     {
98     }
99 
~MarbleWidgetPrivate()100     ~MarbleWidgetPrivate()
101     {
102         m_map.removeLayer( &m_customPaintLayer );
103         m_map.removeLayer( m_mapInfoDialog );
104         delete m_mapInfoDialog;
105         delete m_popupmenu;
106     }
107 
108     void  construct();
109 
110     void updateMapTheme();
111 
112     void setInputHandler();
113     void setInputHandler( MarbleWidgetInputHandler *handler );
114 
115     /**
116       * @brief Update widget flags and cause a full repaint
117       *
118       * The background of the widget only needs to be redrawn in certain cases. This
119       * method sets the widget flags accordingly and triggers a repaint.
120       */
121     void updateSystemBackgroundAttribute();
122 
123     MarbleWidget    *const m_widget;
124 
125     MarbleModel m_model;
126     MarbleMap m_map;
127 
128     MarbleAbstractPresenter m_presenter;
129 
130     MarbleWidgetInputHandler  *m_inputhandler;
131 
132     RoutingLayer     *m_routingLayer;
133     PopupLayer    *m_mapInfoDialog;
134     MarbleWidget::CustomPaintLayer m_customPaintLayer;
135 
136     MarbleWidgetPopupMenu *m_popupmenu;
137 
138     bool             m_showFrameRate;
139 };
140 
141 
142 
MarbleWidget(QWidget * parent)143 MarbleWidget::MarbleWidget(QWidget *parent)
144     : QWidget( parent ),
145       d( new MarbleWidgetPrivate( this ) )
146 {
147 //    setAttribute( Qt::WA_PaintOnScreen, true );
148     d->construct();
149 }
150 
~MarbleWidget()151 MarbleWidget::~MarbleWidget()
152 {
153     // Remove and delete an existing InputHandler
154     // initialized in d->construct()
155     setInputHandler( nullptr );
156 
157     delete d;
158 }
159 
construct()160 void MarbleWidgetPrivate::construct()
161 {
162     QPointer<DataMigration> dataMigration = new DataMigration( m_widget );
163     dataMigration->exec();
164     delete dataMigration;
165 
166     // Widget settings
167     m_widget->setMinimumSize( 200, 300 );
168     m_widget->setFocusPolicy( Qt::WheelFocus );
169     m_widget->setFocus( Qt::OtherFocusReason );
170 
171     // Set background: black.
172     m_widget->setPalette( QPalette ( Qt::black ) );
173 
174     // Set whether the black space gets displayed or the earth gets simply
175     // displayed on the widget background.
176     m_widget->setAutoFillBackground( true );
177 
178     // Initialize the map and forward some signals.
179     m_map.setSize( m_widget->width(), m_widget->height() );
180     m_map.setShowFrameRate( false );  // never let the map draw the frame rate,
181                                        // we do this differently here in the widget
182 
183     m_widget->connect( &m_presenter, SIGNAL(regionSelected(GeoDataLatLonBox)), m_widget, SIGNAL(regionSelected(GeoDataLatLonBox)) );
184 
185     m_widget->connect( &m_presenter, SIGNAL(zoomChanged(int)), m_widget, SIGNAL(zoomChanged(int)) );
186     m_widget->connect( &m_presenter, SIGNAL(distanceChanged(QString)), m_widget, SIGNAL(distanceChanged(QString)) );
187 
188     // forward some signals of m_map
189     m_widget->connect( &m_map,   SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
190                        m_widget, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)) );
191     m_widget->connect( &m_map,   SIGNAL(projectionChanged(Projection)),
192                        m_widget, SIGNAL(projectionChanged(Projection)) );
193     m_widget->connect( &m_map,   SIGNAL(tileLevelChanged(int)),
194                        m_widget, SIGNAL(tileLevelChanged(int)) );
195     m_widget->connect( &m_map,   SIGNAL(framesPerSecond(qreal)),
196                        m_widget, SIGNAL(framesPerSecond(qreal)) );
197     m_widget->connect( &m_map,   SIGNAL(viewContextChanged(ViewContext)),
198                        m_widget, SLOT(setViewContext(ViewContext)) );
199 
200     m_widget->connect( &m_map,   SIGNAL(pluginSettingsChanged()),
201                        m_widget, SIGNAL(pluginSettingsChanged()) );
202     m_widget->connect( &m_map,   SIGNAL(renderPluginInitialized(RenderPlugin*)),
203                        m_widget, SIGNAL(renderPluginInitialized(RenderPlugin*)) );
204 
205     // react to some signals of m_map
206     m_widget->connect( &m_map,   SIGNAL(themeChanged(QString)),
207                        m_widget, SLOT(updateMapTheme()) );
208     m_widget->connect( &m_map,   SIGNAL(viewContextChanged(ViewContext)),
209                        m_widget, SIGNAL(viewContextChanged(ViewContext)) );
210     m_widget->connect( &m_map,   SIGNAL(repaintNeeded(QRegion)),
211                        m_widget, SLOT(update()) );
212     m_widget->connect( &m_map,   SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
213                        m_widget, SLOT(updateSystemBackgroundAttribute()) );
214     m_widget->connect( &m_map,   SIGNAL(renderStatusChanged(RenderStatus)),
215                        m_widget, SIGNAL(renderStatusChanged(RenderStatus)) );
216     m_widget->connect( &m_map,   SIGNAL(renderStateChanged(RenderState)),
217                        m_widget, SIGNAL(renderStateChanged(RenderState)) );
218 
219     m_widget->connect( m_model.fileManager(), SIGNAL(centeredDocument(GeoDataLatLonBox)),
220                        m_widget, SLOT(centerOn(GeoDataLatLonBox)) );
221 
222 
223     // Show a progress dialog when the model calculates new map tiles.
224     m_widget->connect( &m_model, SIGNAL( creatingTilesStart( TileCreator*, const QString&,
225                                                              const QString& ) ),
226                        m_widget, SLOT( creatingTilesStart( TileCreator*, const QString&,
227                                                            const QString& ) ) );
228 
229     m_popupmenu = new MarbleWidgetPopupMenu( m_widget, &m_model );
230 
231     m_routingLayer = new RoutingLayer( m_widget, m_widget );
232     m_routingLayer->setPlacemarkModel( nullptr );
233     QObject::connect( m_routingLayer, SIGNAL(repaintNeeded(QRect)),
234                       m_widget, SLOT(update()) );
235 
236     m_mapInfoDialog = new PopupLayer( m_widget, m_widget );
237     m_mapInfoDialog->setVisible( false );
238     m_widget->connect( m_mapInfoDialog, SIGNAL(repaintNeeded()), m_widget, SLOT(update()) );
239     m_map.addLayer( m_mapInfoDialog );
240 
241     setInputHandler();
242     m_widget->setMouseTracking( true );
243 
244     m_map.addLayer( &m_customPaintLayer );
245 
246     m_widget->connect( m_inputhandler, SIGNAL(mouseClickGeoPosition(qreal,qreal,GeoDataCoordinates::Unit)),
247                        m_widget, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)) );
248     m_widget->setHighlightEnabled( true );
249 
250 }
251 
setInputHandler()252 void MarbleWidgetPrivate::setInputHandler()
253 {
254     setInputHandler( new MarbleWidgetInputHandler( &m_presenter, m_widget ) );
255 }
256 
setInputHandler(MarbleWidgetInputHandler * handler)257 void MarbleWidgetPrivate::setInputHandler( MarbleWidgetInputHandler *handler )
258 {
259     delete m_inputhandler;
260     m_inputhandler = handler;
261 
262     if ( m_inputhandler )
263     {
264         m_widget->installEventFilter( m_inputhandler );
265 
266         QObject::connect( m_inputhandler, SIGNAL(mouseClickScreenPosition(int,int)),
267                m_widget,       SLOT(notifyMouseClick(int,int)) );
268 
269         QObject::connect( m_inputhandler, SIGNAL(mouseMoveGeoPosition(QString)),
270                  m_widget,       SIGNAL(mouseMoveGeoPosition(QString)) );
271     }
272 }
273 
updateSystemBackgroundAttribute()274 void MarbleWidgetPrivate::updateSystemBackgroundAttribute()
275 {
276     // We only have to repaint the background every time if the earth
277     // doesn't cover the whole image.
278     const bool isOn = m_map.viewport()->mapCoversViewport() && !m_model.mapThemeId().isEmpty();
279     m_widget->setAttribute( Qt::WA_NoSystemBackground, isOn );
280 }
281 
282 // ----------------------------------------------------------------
283 
284 
model()285 MarbleModel *MarbleWidget::model()
286 {
287     return &d->m_model;
288 }
289 
model() const290 const MarbleModel *MarbleWidget::model() const
291 {
292     return &d->m_model;
293 }
294 
viewport()295 ViewportParams* MarbleWidget::viewport()
296 {
297     return d->m_map.viewport();
298 }
299 
viewport() const300 const ViewportParams* MarbleWidget::viewport() const
301 {
302     return d->m_map.viewport();
303 }
304 
popupMenu()305 MarbleWidgetPopupMenu *MarbleWidget::popupMenu()
306 {
307     return d->m_popupmenu;
308 }
309 
310 
setInputHandler(MarbleWidgetInputHandler * handler)311 void MarbleWidget::setInputHandler( MarbleWidgetInputHandler *handler )
312 {
313     d->setInputHandler(handler);
314 }
315 
inputHandler() const316 MarbleWidgetInputHandler *MarbleWidget::inputHandler() const
317 {
318   return d->m_inputhandler;
319 }
320 
radius() const321 int MarbleWidget::radius() const
322 {
323     return d->m_map.radius();
324 }
325 
setRadius(int radius)326 void MarbleWidget::setRadius( int radius )
327 {
328     d->m_map.setRadius( radius );
329 }
330 
moveStep() const331 qreal MarbleWidget::moveStep() const
332 {
333     return d->m_presenter.moveStep();
334 }
335 
zoom() const336 int MarbleWidget::zoom() const
337 {
338     return d->m_presenter.logzoom();
339 }
340 
tileZoomLevel() const341 int MarbleWidget::tileZoomLevel() const
342 {
343     return d->m_map.tileZoomLevel();
344 }
345 
minimumZoom() const346 int  MarbleWidget::minimumZoom() const
347 {
348     return d->m_map.minimumZoom();
349 }
350 
maximumZoom() const351 int  MarbleWidget::maximumZoom() const
352 {
353     return d->m_map.maximumZoom();
354 }
355 
whichFeatureAt(const QPoint & curpos) const356 QVector<const GeoDataFeature*> MarbleWidget::whichFeatureAt( const QPoint &curpos ) const
357 {
358     return d->m_map.whichFeatureAt( curpos );
359 }
360 
whichItemAt(const QPoint & curpos) const361 QList<AbstractDataPluginItem*> MarbleWidget::whichItemAt( const QPoint &curpos ) const
362 {
363     return d->m_map.whichItemAt( curpos );
364 }
365 
addLayer(LayerInterface * layer)366 void MarbleWidget::addLayer( LayerInterface *layer )
367 {
368     d->m_map.addLayer( layer );
369 }
370 
removeLayer(LayerInterface * layer)371 void MarbleWidget::removeLayer( LayerInterface *layer )
372 {
373     d->m_map.removeLayer( layer );
374 }
375 
textureLayer() const376 Marble::TextureLayer* MarbleWidget::textureLayer() const
377 {
378     return d->m_map.textureLayer();
379 }
380 
mapScreenShot()381 QPixmap MarbleWidget::mapScreenShot()
382 {
383     return grab();
384 }
385 
renderStatus() const386 RenderStatus MarbleWidget::renderStatus() const
387 {
388     return d->m_map.renderStatus();
389 }
390 
renderState() const391 RenderState MarbleWidget::renderState() const
392 {
393     return d->m_map.renderState();
394 }
395 
setHighlightEnabled(bool enabled)396 void MarbleWidget::setHighlightEnabled(bool enabled)
397 {
398     if ( enabled ) {
399         connect( this, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
400                  &d->m_map, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
401                  Qt::UniqueConnection );
402     }
403     else {
404         disconnect( this, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
405                  &d->m_map, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)) );
406     }
407 }
408 
showOverviewMap() const409 bool MarbleWidget::showOverviewMap() const
410 {
411     return d->m_map.showOverviewMap();
412 }
413 
showScaleBar() const414 bool MarbleWidget::showScaleBar() const
415 {
416     return d->m_map.showScaleBar();
417 }
418 
showCompass() const419 bool MarbleWidget::showCompass() const
420 {
421     return d->m_map.showCompass();
422 }
423 
showClouds() const424 bool MarbleWidget::showClouds() const
425 {
426     return d->m_map.showClouds();
427 }
428 
showSunShading() const429 bool MarbleWidget::showSunShading() const
430 {
431     return d->m_map.showSunShading();
432 }
433 
showCityLights() const434 bool MarbleWidget::showCityLights() const
435 {
436     return d->m_map.showCityLights();
437 }
438 
isLockedToSubSolarPoint() const439 bool MarbleWidget::isLockedToSubSolarPoint() const
440 {
441     return d->m_map.isLockedToSubSolarPoint();
442 }
443 
isSubSolarPointIconVisible() const444 bool MarbleWidget::isSubSolarPointIconVisible() const
445 {
446     return d->m_map.isSubSolarPointIconVisible();
447 }
448 
showAtmosphere() const449 bool MarbleWidget::showAtmosphere() const
450 {
451     return d->m_map.showAtmosphere();
452 }
453 
showCrosshairs() const454 bool MarbleWidget::showCrosshairs() const
455 {
456     return d->m_map.showCrosshairs();
457 }
458 
showGrid() const459 bool MarbleWidget::showGrid() const
460 {
461     return d->m_map.showGrid();
462 }
463 
showPlaces() const464 bool MarbleWidget::showPlaces() const
465 {
466     return d->m_map.showPlaces();
467 }
468 
showCities() const469 bool MarbleWidget::showCities() const
470 {
471     return d->m_map.showCities();
472 }
473 
showTerrain() const474 bool MarbleWidget::showTerrain() const
475 {
476     return d->m_map.showTerrain();
477 }
478 
showOtherPlaces() const479 bool MarbleWidget::showOtherPlaces() const
480 {
481     return d->m_map.showOtherPlaces();
482 }
483 
showRelief() const484 bool MarbleWidget::showRelief() const
485 {
486     return d->m_map.showRelief();
487 }
488 
showIceLayer() const489 bool MarbleWidget::showIceLayer() const
490 {
491     return d->m_map.showIceLayer();
492 }
493 
showBorders() const494 bool MarbleWidget::showBorders() const
495 {
496     return d->m_map.showBorders();
497 }
498 
showRivers() const499 bool MarbleWidget::showRivers() const
500 {
501     return d->m_map.showRivers();
502 }
503 
showLakes() const504 bool MarbleWidget::showLakes() const
505 {
506     return d->m_map.showLakes();
507 }
508 
showFrameRate() const509 bool MarbleWidget::showFrameRate() const
510 {
511     return d->m_showFrameRate;
512 }
513 
showBackground() const514 bool MarbleWidget::showBackground() const
515 {
516     return d->m_map.showBackground();
517 }
518 
volatileTileCacheLimit() const519 quint64 MarbleWidget::volatileTileCacheLimit() const
520 {
521     return d->m_map.volatileTileCacheLimit();
522 }
523 
524 
setZoom(int newZoom,FlyToMode mode)525 void MarbleWidget::setZoom( int newZoom, FlyToMode mode )
526 {
527     d->m_inputhandler->stopInertialEarthRotation();
528     d->m_presenter.setZoom( newZoom, mode );
529 }
530 
zoomView(int zoom,FlyToMode mode)531 void MarbleWidget::zoomView( int zoom, FlyToMode mode )
532 {
533     d->m_inputhandler->stopInertialEarthRotation();
534     d->m_presenter.zoomView( zoom, mode );
535 }
536 
537 
zoomViewBy(int zoomStep,FlyToMode mode)538 void MarbleWidget::zoomViewBy( int zoomStep, FlyToMode mode )
539 {
540     d->m_inputhandler->stopInertialEarthRotation();
541     d->m_presenter.zoomViewBy( zoomStep, mode );
542 }
543 
544 
zoomIn(FlyToMode mode)545 void MarbleWidget::zoomIn( FlyToMode mode )
546 {
547     d->m_inputhandler->stopInertialEarthRotation();
548     d->m_presenter.zoomIn( mode );
549 }
550 
zoomOut(FlyToMode mode)551 void MarbleWidget::zoomOut( FlyToMode mode )
552 {
553     d->m_inputhandler->stopInertialEarthRotation();
554     d->m_presenter.zoomOut( mode );
555 }
556 
rotateBy(const qreal deltaLon,const qreal deltaLat,FlyToMode mode)557 void MarbleWidget::rotateBy( const qreal deltaLon, const qreal deltaLat, FlyToMode mode )
558 {
559     d->m_inputhandler->stopInertialEarthRotation();
560     d->m_presenter.rotateBy( deltaLon, deltaLat, mode );
561 }
562 
563 
centerOn(const qreal lon,const qreal lat,bool animated)564 void MarbleWidget::centerOn( const qreal lon, const qreal lat, bool animated )
565 {
566     d->m_inputhandler->stopInertialEarthRotation();
567     d->m_presenter.centerOn( lon, lat, animated );
568 }
569 
centerOn(const GeoDataCoordinates & position,bool animated)570 void MarbleWidget::centerOn( const GeoDataCoordinates &position, bool animated )
571 {
572     d->m_inputhandler->stopInertialEarthRotation();
573     d->m_presenter.centerOn( position, animated );
574 }
575 
centerOn(const GeoDataLatLonBox & box,bool animated)576 void MarbleWidget::centerOn( const GeoDataLatLonBox &box, bool animated )
577 {
578     d->m_inputhandler->stopInertialEarthRotation();
579    d->m_presenter.centerOn( box, animated );
580 }
581 
centerOn(const GeoDataPlacemark & placemark,bool animated)582 void MarbleWidget::centerOn( const GeoDataPlacemark& placemark, bool animated )
583 {
584     d->m_inputhandler->stopInertialEarthRotation();
585     d->m_presenter.centerOn( placemark, animated );
586 }
587 
setCenterLatitude(qreal lat,FlyToMode mode)588 void MarbleWidget::setCenterLatitude( qreal lat, FlyToMode mode )
589 {
590     d->m_inputhandler->stopInertialEarthRotation();
591     d->m_presenter.setCenterLatitude( lat, mode );
592 }
593 
setCenterLongitude(qreal lon,FlyToMode mode)594 void MarbleWidget::setCenterLongitude( qreal lon, FlyToMode mode )
595 {
596     d->m_inputhandler->stopInertialEarthRotation();
597     d->m_presenter.setCenterLongitude( lon, mode );
598 }
599 
projection() const600 Projection MarbleWidget::projection() const
601 {
602     return d->m_map.projection();
603 }
604 
setProjection(Projection projection)605 void MarbleWidget::setProjection( Projection projection )
606 {
607     d->m_map.setProjection( projection );
608 }
609 
setProjection(int projection)610 void MarbleWidget::setProjection( int projection )
611 {
612     setProjection( Projection( qAbs( projection ) % (Mercator+1) ) );
613 }
614 
moveLeft(FlyToMode mode)615 void MarbleWidget::moveLeft( FlyToMode mode )
616 {
617     d->m_inputhandler->stopInertialEarthRotation();
618     d->m_presenter.moveByStep( -1, 0, mode );
619 }
620 
moveRight(FlyToMode mode)621 void MarbleWidget::moveRight( FlyToMode mode )
622 {
623     d->m_inputhandler->stopInertialEarthRotation();
624     d->m_presenter.moveByStep( 1, 0, mode );
625 }
626 
moveUp(FlyToMode mode)627 void MarbleWidget::moveUp( FlyToMode mode )
628 {
629     d->m_inputhandler->stopInertialEarthRotation();
630     d->m_presenter.moveByStep( 0, -1, mode );
631 }
632 
moveDown(FlyToMode mode)633 void MarbleWidget::moveDown( FlyToMode mode )
634 {
635     d->m_inputhandler->stopInertialEarthRotation();
636     d->m_presenter.moveByStep( 0, 1, mode );
637 }
638 
leaveEvent(QEvent *)639 void MarbleWidget::leaveEvent( QEvent* )
640 {
641     emit mouseMoveGeoPosition( QCoreApplication::translate( "Marble", NOT_AVAILABLE ) );
642 }
643 
resizeEvent(QResizeEvent * event)644 void MarbleWidget::resizeEvent( QResizeEvent *event )
645 {
646     setUpdatesEnabled( false );
647     d->m_map.setSize( event->size() );
648     setUpdatesEnabled( true );
649 
650     QWidget::resizeEvent( event );
651 }
652 
connectNotify(const QMetaMethod & signal)653 void MarbleWidget::connectNotify( const QMetaMethod &signal )
654 {
655     if ( d->m_inputhandler && signal == QMetaMethod::fromSignal( &MarbleWidget::mouseMoveGeoPosition ) ) {
656         d->m_inputhandler->setPositionSignalConnected( true );
657     }
658 }
659 
disconnectNotify(const QMetaMethod & signal)660 void MarbleWidget::disconnectNotify( const QMetaMethod &signal )
661 {
662     if ( d->m_inputhandler && signal == QMetaMethod::fromSignal( &MarbleWidget::mouseMoveGeoPosition ) ) {
663         d->m_inputhandler->setPositionSignalConnected( false );
664     }
665 }
666 
screenCoordinates(qreal lon,qreal lat,qreal & x,qreal & y) const667 bool MarbleWidget::screenCoordinates( qreal lon, qreal lat,
668                                       qreal& x, qreal& y ) const
669 {
670     return d->m_map.screenCoordinates( lon, lat, x, y );
671 }
672 
geoCoordinates(int x,int y,qreal & lon,qreal & lat,GeoDataCoordinates::Unit unit) const673 bool MarbleWidget::geoCoordinates( int x, int y,
674                                    qreal& lon, qreal& lat,
675                                    GeoDataCoordinates::Unit unit ) const
676 {
677     return d->m_map.geoCoordinates( x, y, lon, lat, unit );
678 }
679 
centerLatitude() const680 qreal MarbleWidget::centerLatitude() const
681 {
682     return d->m_map.centerLatitude();
683 }
684 
centerLongitude() const685 qreal MarbleWidget::centerLongitude() const
686 {
687     return d->m_map.centerLongitude();
688 }
689 
mapRegion() const690 QRegion MarbleWidget::mapRegion() const
691 {
692     return viewport()->mapRegion();
693 }
694 
paintEvent(QPaintEvent * evt)695 void MarbleWidget::paintEvent( QPaintEvent *evt )
696 {
697     QElapsedTimer t;
698     t.start();
699 
700     QPaintDevice *paintDevice = this;
701     QImage image;
702     if (!isEnabled())
703     {
704         // If the globe covers fully the screen then we can use the faster
705         // RGB32 as there are no translucent areas involved.
706         QImage::Format imageFormat = ( d->m_map.viewport()->mapCoversViewport() )
707                                      ? QImage::Format_RGB32
708                                      : QImage::Format_ARGB32_Premultiplied;
709         // Paint to an intermediate image
710         image = QImage( rect().size(), imageFormat );
711         image.fill( Qt::transparent );
712         paintDevice = &image;
713     }
714 
715     {
716         // FIXME: Better way to get the GeoPainter
717         // Create a painter that will do the painting.
718         GeoPainter geoPainter( paintDevice, d->m_map.viewport(), d->m_map.mapQuality() );
719 
720         d->m_map.paint( geoPainter, evt->rect() );
721     }
722 
723     if ( !isEnabled() )
724     {
725         // Draw a grayscale version of the intermediate image
726         QRgb* pixel = reinterpret_cast<QRgb*>( image.scanLine( 0 ));
727         for (int i=0; i<image.width()*image.height(); ++i, ++pixel) {
728             int gray = qGray( *pixel );
729             *pixel = qRgb( gray, gray, gray );
730         }
731 
732         QPainter widgetPainter( this );
733         widgetPainter.drawImage( rect(), image );
734     }
735 
736     if ( d->m_showFrameRate )
737     {
738         QPainter painter( this );
739         FpsLayer fpsPainter( &t );
740         fpsPainter.paint( &painter );
741 
742         const qreal fps = 1000.0 / (qreal)( t.elapsed() + 1 );
743         emit framesPerSecond( fps );
744     }
745 }
746 
customPaint(GeoPainter * painter)747 void MarbleWidget::customPaint( GeoPainter *painter )
748 {
749     Q_UNUSED( painter );
750     /* This is a NOOP in the base class*/
751 }
752 
753 
goHome(FlyToMode mode)754 void MarbleWidget::goHome( FlyToMode mode )
755 {
756     d->m_inputhandler->stopInertialEarthRotation();
757     d->m_presenter.goHome( mode );
758 }
759 
mapThemeId() const760 QString MarbleWidget::mapThemeId() const
761 {
762     return d->m_model.mapThemeId();
763 }
764 
setMapThemeId(const QString & mapThemeId)765 void MarbleWidget::setMapThemeId( const QString& mapThemeId )
766 {
767     d->m_map.setMapThemeId( mapThemeId );
768 }
769 
updateMapTheme()770 void MarbleWidgetPrivate::updateMapTheme()
771 {
772     m_map.removeLayer( m_routingLayer );
773 
774     m_widget->setRadius( m_widget->radius() ); // Corrects zoom range, if needed
775 
776     if (m_model.planetId() == QLatin1String("earth")) {
777         m_map.addLayer( m_routingLayer );
778     }
779 
780     emit m_widget->themeChanged( m_map.mapThemeId() );
781 
782     // Now we want a full repaint as the atmosphere might differ
783     m_widget->setAttribute( Qt::WA_NoSystemBackground, false );
784 
785     m_widget->update();
786 }
787 
mapTheme() const788 GeoSceneDocument *MarbleWidget::mapTheme() const
789 {
790     return d->m_model.mapTheme();
791 }
792 
setPropertyValue(const QString & name,bool value)793 void MarbleWidget::setPropertyValue( const QString& name, bool value )
794 {
795     mDebug() << "In MarbleWidget the property " << name << "was set to " << value;
796     d->m_map.setPropertyValue( name, value );
797 }
798 
setShowOverviewMap(bool visible)799 void MarbleWidget::setShowOverviewMap( bool visible )
800 {
801     d->m_map.setShowOverviewMap( visible );
802 }
803 
setShowScaleBar(bool visible)804 void MarbleWidget::setShowScaleBar( bool visible )
805 {
806     d->m_map.setShowScaleBar( visible );
807 }
808 
setShowCompass(bool visible)809 void MarbleWidget::setShowCompass( bool visible )
810 {
811     d->m_map.setShowCompass( visible );
812 }
813 
setShowClouds(bool visible)814 void MarbleWidget::setShowClouds( bool visible )
815 {
816     d->m_map.setShowClouds( visible );
817 }
818 
setShowSunShading(bool visible)819 void MarbleWidget::setShowSunShading( bool visible )
820 {
821     d->m_map.setShowSunShading( visible );
822 }
823 
setShowCityLights(bool visible)824 void MarbleWidget::setShowCityLights( bool visible )
825 {
826     d->m_map.setShowCityLights( visible );
827 }
828 
setLockToSubSolarPoint(bool visible)829 void MarbleWidget::setLockToSubSolarPoint( bool visible )
830 {
831     if ( d->m_map.isLockedToSubSolarPoint() != visible ) { // Toggling input modifies event filters, so avoid that if not needed
832         d->m_map.setLockToSubSolarPoint( visible );
833         setInputEnabled( !d->m_map.isLockedToSubSolarPoint() );
834     }
835 }
836 
setSubSolarPointIconVisible(bool visible)837 void MarbleWidget::setSubSolarPointIconVisible( bool visible )
838 {
839     if ( d->m_map.isSubSolarPointIconVisible() != visible ) {
840         d->m_map.setSubSolarPointIconVisible( visible );
841     }
842 
843     QList<RenderPlugin *> pluginList = renderPlugins();
844     QList<RenderPlugin *>::const_iterator i = pluginList.constBegin();
845     QList<RenderPlugin *>::const_iterator const end = pluginList.constEnd();
846     for (; i != end; ++i ) {
847         if ((*i)->nameId() == QLatin1String("sun")) {
848             (*i)->setVisible( visible );
849         }
850     }
851 }
852 
setShowAtmosphere(bool visible)853 void MarbleWidget::setShowAtmosphere( bool visible )
854 {
855     d->m_map.setShowAtmosphere( visible );
856 }
857 
setShowCrosshairs(bool visible)858 void MarbleWidget::setShowCrosshairs( bool visible )
859 {
860     d->m_map.setShowCrosshairs( visible );
861 }
862 
setShowGrid(bool visible)863 void MarbleWidget::setShowGrid( bool visible )
864 {
865     d->m_map.setShowGrid( visible );
866 }
867 
setShowPlaces(bool visible)868 void MarbleWidget::setShowPlaces( bool visible )
869 {
870     d->m_map.setShowPlaces( visible );
871 }
872 
setShowCities(bool visible)873 void MarbleWidget::setShowCities( bool visible )
874 {
875     d->m_map.setShowCities( visible );
876 }
877 
setShowTerrain(bool visible)878 void MarbleWidget::setShowTerrain( bool visible )
879 {
880     d->m_map.setShowTerrain( visible );
881 }
882 
setShowOtherPlaces(bool visible)883 void MarbleWidget::setShowOtherPlaces( bool visible )
884 {
885     d->m_map.setShowOtherPlaces( visible );
886 }
887 
setShowRelief(bool visible)888 void MarbleWidget::setShowRelief( bool visible )
889 {
890     d->m_map.setShowRelief( visible );
891 }
892 
setShowIceLayer(bool visible)893 void MarbleWidget::setShowIceLayer( bool visible )
894 {
895     d->m_map.setShowIceLayer( visible );
896 }
897 
setShowBorders(bool visible)898 void MarbleWidget::setShowBorders( bool visible )
899 {
900     d->m_map.setShowBorders( visible );
901 }
902 
setShowRivers(bool visible)903 void MarbleWidget::setShowRivers( bool visible )
904 {
905     d->m_map.setShowRivers( visible );
906 }
907 
setShowLakes(bool visible)908 void MarbleWidget::setShowLakes( bool visible )
909 {
910     d->m_map.setShowLakes( visible );
911 }
912 
setShowFrameRate(bool visible)913 void MarbleWidget::setShowFrameRate( bool visible )
914 {
915     d->m_showFrameRate = visible;
916 
917     update();
918 }
919 
setShowBackground(bool visible)920 void MarbleWidget::setShowBackground( bool visible )
921 {
922     d->m_map.setShowBackground( visible );
923 }
924 
setShowRuntimeTrace(bool visible)925 void MarbleWidget::setShowRuntimeTrace( bool visible )
926 {
927     d->m_map.setShowRuntimeTrace( visible );
928 }
929 
showRuntimeTrace() const930 bool MarbleWidget::showRuntimeTrace() const
931 {
932     return d->m_map.showRuntimeTrace();
933 }
934 
setShowDebugPolygons(bool visible)935 void MarbleWidget::setShowDebugPolygons( bool visible)
936 {
937     d->m_map.setShowDebugPolygons( visible );
938 }
939 
showDebugPolygons() const940 bool MarbleWidget::showDebugPolygons() const
941 {
942     return d->m_map.showDebugPolygons();
943 }
944 
setShowDebugBatchRender(bool visible)945 void MarbleWidget::setShowDebugBatchRender( bool visible)
946 {
947     d->m_map.setShowDebugBatchRender( visible );
948 }
949 
showDebugBatchRender() const950 bool MarbleWidget::showDebugBatchRender() const
951 {
952     return d->m_map.showDebugBatchRender();
953 }
954 
setShowDebugPlacemarks(bool visible)955 void MarbleWidget::setShowDebugPlacemarks( bool visible)
956 {
957     d->m_map.setShowDebugPlacemarks( visible );
958 }
959 
showDebugPlacemarks() const960 bool MarbleWidget::showDebugPlacemarks() const
961 {
962     return d->m_map.showDebugPlacemarks();
963 }
964 
setDebugLevelTags(bool visible)965 void MarbleWidget::setDebugLevelTags(bool visible)
966 {
967     d->m_map.setLevelTagDebugModeEnabled(visible);
968 }
969 
debugLevelTags() const970 bool MarbleWidget::debugLevelTags() const
971 {
972     return d->m_map.levelTagDebugModeEnabled();
973 }
974 
setShowTileId(bool visible)975 void MarbleWidget::setShowTileId( bool visible )
976 {
977     d->m_map.setShowTileId( visible );
978 }
979 
notifyMouseClick(int x,int y)980 void MarbleWidget::notifyMouseClick( int x, int y)
981 {
982     qreal  lon   = 0;
983     qreal  lat   = 0;
984 
985     bool const valid = geoCoordinates( x, y, lon, lat, GeoDataCoordinates::Radian );
986 
987     if ( valid ) {
988         emit mouseClickGeoPosition( lon, lat, GeoDataCoordinates::Radian );
989     }
990 }
991 
clearVolatileTileCache()992 void MarbleWidget::clearVolatileTileCache()
993 {
994     mDebug() << "About to clear VolatileTileCache";
995     d->m_map.clearVolatileTileCache();
996 }
997 
setVolatileTileCacheLimit(quint64 kiloBytes)998 void MarbleWidget::setVolatileTileCacheLimit( quint64 kiloBytes )
999 {
1000     d->m_map.setVolatileTileCacheLimit( kiloBytes );
1001 }
1002 
1003 // This slot will called when the Globe starts to create the tiles.
1004 
creatingTilesStart(TileCreator * creator,const QString & name,const QString & description)1005 void MarbleWidget::creatingTilesStart( TileCreator *creator,
1006                                        const QString &name,
1007                                        const QString &description )
1008 {
1009     QPointer<TileCreatorDialog> dialog = new TileCreatorDialog( creator, this );
1010     dialog->setSummary( name, description );
1011     dialog->exec();
1012     delete dialog;
1013 }
1014 
mapQuality(ViewContext viewContext) const1015 MapQuality MarbleWidget::mapQuality( ViewContext viewContext ) const
1016 {
1017     return d->m_map.mapQuality( viewContext );
1018 }
1019 
setMapQualityForViewContext(MapQuality quality,ViewContext viewContext)1020 void MarbleWidget::setMapQualityForViewContext( MapQuality quality, ViewContext viewContext )
1021 {
1022     d->m_map.setMapQualityForViewContext( quality, viewContext );
1023 }
1024 
viewContext() const1025 ViewContext MarbleWidget::viewContext() const
1026 {
1027     return d->m_map.viewContext();
1028 }
1029 
setViewContext(ViewContext viewContext)1030 void MarbleWidget::setViewContext( ViewContext viewContext )
1031 {
1032     // Inform routing layer about view context change. If not done,
1033     // the routing layer causes severe performance problems when dragging the
1034     // map. So either do not remove this line, or keep a similar call in place
1035     // when you refactor it and test your changes wrt drag performance at
1036     // high zoom level with long routes!
1037     d->m_routingLayer->setViewContext( viewContext );
1038 
1039     d->m_map.setViewContext( viewContext );
1040 }
1041 
animationsEnabled() const1042 bool MarbleWidget::animationsEnabled() const
1043 {
1044     return d->m_presenter.animationsEnabled();
1045 }
1046 
setAnimationsEnabled(bool enabled)1047 void MarbleWidget::setAnimationsEnabled( bool enabled )
1048 {
1049     d->m_presenter.setAnimationsEnabled( enabled );
1050 }
1051 
defaultAngleUnit() const1052 AngleUnit MarbleWidget::defaultAngleUnit() const
1053 {
1054     return d->m_map.defaultAngleUnit();
1055 }
1056 
setDefaultAngleUnit(AngleUnit angleUnit)1057 void MarbleWidget::setDefaultAngleUnit( AngleUnit angleUnit )
1058 {
1059     d->m_map.setDefaultAngleUnit( angleUnit );
1060 }
1061 
defaultFont() const1062 QFont MarbleWidget::defaultFont() const
1063 {
1064     return d->m_map.defaultFont();
1065 }
1066 
setDefaultFont(const QFont & font)1067 void MarbleWidget::setDefaultFont( const QFont& font )
1068 {
1069     d->m_map.setDefaultFont( font );
1070 }
1071 
setSelection(const QRect & region)1072 void MarbleWidget::setSelection( const QRect& region )
1073 {
1074     d->m_presenter.setSelection( region );
1075 }
1076 
distance() const1077 qreal MarbleWidget::distance() const
1078 {
1079     return d->m_presenter.distance();
1080 }
1081 
setDistance(qreal newDistance)1082 void MarbleWidget::setDistance( qreal newDistance )
1083 {
1084     d->m_presenter.setDistance( newDistance );
1085 }
1086 
distanceString() const1087 QString MarbleWidget::distanceString() const
1088 {
1089     return d->m_presenter.distanceString();
1090 }
1091 
setInputEnabled(bool enabled)1092 void MarbleWidget::setInputEnabled( bool enabled )
1093 {
1094     //if input is set as enabled
1095     if ( enabled )
1096     {
1097         if ( !d->m_inputhandler ) {
1098             d->setInputHandler();
1099         }
1100         else {
1101             installEventFilter( d->m_inputhandler );
1102         }
1103     }
1104 
1105     else // input is disabled
1106     {
1107         mDebug() << "MarbleWidget::disableInput";
1108         removeEventFilter( d->m_inputhandler );
1109         setCursor( Qt::ArrowCursor );
1110     }
1111 }
1112 
renderPlugins() const1113 QList<RenderPlugin *> MarbleWidget::renderPlugins() const
1114 {
1115     return d->m_map.renderPlugins();
1116 }
1117 
readPluginSettings(QSettings & settings)1118 void MarbleWidget::readPluginSettings( QSettings& settings )
1119 {
1120     for( RenderPlugin *plugin: renderPlugins() ) {
1121         settings.beginGroup(QLatin1String("plugin_") + plugin->nameId());
1122 
1123         QHash<QString,QVariant> hash;
1124 
1125         for ( const QString& key: settings.childKeys() ) {
1126             hash.insert( key, settings.value( key ) );
1127         }
1128 
1129         plugin->setSettings( hash );
1130 
1131         settings.endGroup();
1132     }
1133 }
1134 
writePluginSettings(QSettings & settings) const1135 void MarbleWidget::writePluginSettings( QSettings& settings ) const
1136 {
1137     for( RenderPlugin *plugin: renderPlugins() ) {
1138         settings.beginGroup(QLatin1String("plugin_") + plugin->nameId());
1139 
1140         QHash<QString,QVariant> hash = plugin->settings();
1141 
1142         QHash<QString,QVariant>::iterator it = hash.begin();
1143         while( it != hash.end() ) {
1144             settings.setValue( it.key(), it.value() );
1145             ++it;
1146         }
1147 
1148         settings.endGroup();
1149     }
1150 }
1151 
floatItems() const1152 QList<AbstractFloatItem *> MarbleWidget::floatItems() const
1153 {
1154     return d->m_map.floatItems();
1155 }
1156 
floatItem(const QString & nameId) const1157 AbstractFloatItem * MarbleWidget::floatItem( const QString &nameId ) const
1158 {
1159     return d->m_map.floatItem( nameId );
1160 }
1161 
changeEvent(QEvent * event)1162 void MarbleWidget::changeEvent( QEvent * event )
1163 {
1164     if ( event->type() == QEvent::EnabledChange )
1165     {
1166         setInputEnabled(isEnabled());
1167     }
1168 
1169     QWidget::changeEvent(event);
1170 }
1171 
flyTo(const GeoDataLookAt & newLookAt,FlyToMode mode)1172 void MarbleWidget::flyTo( const GeoDataLookAt &newLookAt, FlyToMode mode )
1173 {
1174     d->m_inputhandler->stopInertialEarthRotation();
1175     d->m_presenter.flyTo( newLookAt, mode );
1176 }
1177 
reloadMap()1178 void MarbleWidget::reloadMap()
1179 {
1180     d->m_map.reload();
1181 }
1182 
downloadRegion(QVector<TileCoordsPyramid> const & pyramid)1183 void MarbleWidget::downloadRegion( QVector<TileCoordsPyramid> const & pyramid )
1184 {
1185     d->m_map.downloadRegion( pyramid );
1186 }
1187 
lookAt() const1188 GeoDataLookAt MarbleWidget::lookAt() const
1189 {
1190     return d->m_presenter.lookAt();
1191 }
1192 
focusPoint() const1193 GeoDataCoordinates MarbleWidget::focusPoint() const
1194 {
1195     return d->m_map.viewport()->focusPoint();
1196 }
1197 
setFocusPoint(const GeoDataCoordinates & focusPoint)1198 void MarbleWidget::setFocusPoint( const GeoDataCoordinates &focusPoint )
1199 {
1200     d->m_map.viewport()->setFocusPoint( focusPoint );
1201 }
1202 
resetFocusPoint()1203 void MarbleWidget::resetFocusPoint()
1204 {
1205     d->m_map.viewport()->resetFocusPoint();
1206 }
1207 
radiusFromDistance(qreal distance) const1208 qreal MarbleWidget::radiusFromDistance( qreal distance ) const
1209 {
1210     return d->m_presenter.radiusFromDistance( distance );
1211 }
1212 
distanceFromRadius(qreal radius) const1213 qreal MarbleWidget::distanceFromRadius( qreal radius ) const
1214 {
1215     return d->m_presenter.distanceFromRadius( radius );
1216 }
1217 
zoomFromDistance(qreal distance) const1218 qreal MarbleWidget::zoomFromDistance( qreal distance ) const
1219 {
1220     return d->m_presenter.zoomFromDistance( distance );
1221 }
1222 
distanceFromZoom(qreal zoom) const1223 qreal MarbleWidget::distanceFromZoom( qreal zoom ) const
1224 {
1225     return d->m_presenter.distanceFromZoom( zoom );
1226 }
1227 
routingLayer()1228 RoutingLayer* MarbleWidget::routingLayer()
1229 {
1230     return d->m_routingLayer;
1231 }
1232 
popupLayer()1233 PopupLayer *MarbleWidget::popupLayer()
1234 {
1235     return d->m_mapInfoDialog;
1236 }
1237 
styleBuilder() const1238 const StyleBuilder* MarbleWidget::styleBuilder() const
1239 {
1240     return d->m_map.styleBuilder();
1241 }
1242 
setHeading(qreal heading)1243 void MarbleWidget::setHeading( qreal heading )
1244 {
1245     d->m_map.setHeading( heading );
1246 }
1247 
heading() const1248 qreal MarbleWidget::heading() const
1249 {
1250     return d->m_map.heading();
1251 }
1252 
setLevelToDebug(int level)1253 void MarbleWidget::setLevelToDebug(int level)
1254 {
1255     d->m_map.setDebugLevelTag(level);
1256 }
1257 
levelToDebug() const1258 int MarbleWidget::levelToDebug() const
1259 {
1260     return d->m_map.debugLevelTag();
1261 }
1262 
1263 }
1264 
1265 #include "moc_MarbleWidget.cpp"
1266