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