1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2009 Torsten Rahn <tackat@kde.org>
4 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5 // SPDX-FileCopyrightText: 2008 Carlos Licea <carlos.licea@kdemail.net>
6 // SPDX-FileCopyrightText: 2009 Jens-Michael Hoffmann <jensmh@gmx.de>
7 // SPDX-FileCopyrightText: 2010-2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
8 //
9 
10 
11 // Own
12 #include "MarbleMap.h"
13 
14 // Posix
15 #include <cmath>
16 
17 // Qt
18 #include <QElapsedTimer>
19 #include <QtMath>
20 
21 // Marble
22 #include "layers/FloatItemsLayer.h"
23 #include "layers/FogLayer.h"
24 #include "layers/FpsLayer.h"
25 #include "layers/GeometryLayer.h"
26 #include "layers/GroundLayer.h"
27 #include "layers/MarbleSplashLayer.h"
28 #include "layers/PlacemarkLayer.h"
29 #include "layers/TextureLayer.h"
30 #include "layers/VectorTileLayer.h"
31 #include "AbstractFloatItem.h"
32 #include "DgmlAuxillaryDictionary.h"
33 #include "FileManager.h"
34 #include "GeoDataTreeModel.h"
35 #include "GeoPainter.h"
36 #include "GeoSceneDocument.h"
37 #include "GeoSceneFilter.h"
38 #include "GeoSceneGeodata.h"
39 #include "GeoSceneHead.h"
40 #include "GeoSceneLayer.h"
41 #include "GeoSceneMap.h"
42 #include "GeoScenePalette.h"
43 #include "GeoSceneSettings.h"
44 #include "GeoSceneVector.h"
45 #include "GeoSceneVectorTileDataset.h"
46 #include "GeoSceneTextureTileDataset.h"
47 #include "GeoSceneZoom.h"
48 #include "GeoDataDocument.h"
49 #include "GeoDataFeature.h"
50 #include "GeoDataStyle.h"
51 #include "GeoDataStyleMap.h"
52 #include "LayerManager.h"
53 #include "MapThemeManager.h"
54 #include "MarbleDebug.h"
55 #include "MarbleDirs.h"
56 #include "MarbleModel.h"
57 #include "PluginManager.h"
58 #include "RenderPlugin.h"
59 #include "StyleBuilder.h"
60 #include "SunLocator.h"
61 #include "TileId.h"
62 #include "TileCoordsPyramid.h"
63 #include "TileCreator.h"
64 #include "TileCreatorDialog.h"
65 #include "TileLoader.h"
66 #include "ViewParams.h"
67 #include "ViewportParams.h"
68 #include "RenderState.h"
69 #include "BookmarkManager.h"
70 
71 
72 namespace Marble
73 {
74 
75 
76 class MarbleMap::CustomPaintLayer : public LayerInterface
77 {
78 public:
CustomPaintLayer(MarbleMap * map)79     explicit CustomPaintLayer( MarbleMap *map )
80         : m_map( map )
81     {
82     }
83 
renderPosition() const84     QStringList renderPosition() const override { return QStringList() << "USER_TOOLS"; }
85 
render(GeoPainter * painter,ViewportParams * viewport,const QString & renderPos,GeoSceneLayer * layer)86     bool render( GeoPainter *painter, ViewportParams *viewport,
87                          const QString &renderPos, GeoSceneLayer *layer ) override
88     {
89         Q_UNUSED( viewport );
90         Q_UNUSED( renderPos );
91         Q_UNUSED( layer );
92 
93         m_map->customPaint( painter );
94 
95         return true;
96     }
97 
zValue() const98     qreal zValue() const override { return 1.0e6; }
99 
renderState() const100     RenderState renderState() const override { return RenderState(QStringLiteral("Custom Map Paint")); }
101 
runtimeTrace() const102     QString runtimeTrace() const override { return QStringLiteral("CustomPaint"); }
103 
104 private:
105     MarbleMap *const m_map;
106 };
107 
108 
109 class MarbleMapPrivate
110 {
111     friend class MarbleWidget;
112 
113 public:
114     explicit MarbleMapPrivate( MarbleMap *parent, MarbleModel *model );
115 
116     void updateMapTheme();
117 
118     void updateProperty( const QString &, bool );
119 
120     void setDocument( const QString& key );
121 
122     void updateTileLevel();
123 
124     void addPlugins();
125 
126     MarbleMap *const q;
127 
128     // The model we are showing.
129     MarbleModel     *const m_model;
130     bool             m_modelIsOwned;
131 
132     // Parameters for the maps appearance.
133     ViewParams       m_viewParams;
134     ViewportParams   m_viewport;
135     bool             m_showFrameRate;
136     bool             m_showDebugPolygons;
137     bool             m_showDebugBatchRender;
138     GeoDataRelation::RelationTypes m_visibleRelationTypes;
139     StyleBuilder     m_styleBuilder;
140 
141     QList<RenderPlugin *> m_renderPlugins;
142 
143     LayerManager     m_layerManager;
144     MarbleSplashLayer m_marbleSplashLayer;
145     MarbleMap::CustomPaintLayer m_customPaintLayer;
146     GeometryLayer            m_geometryLayer;
147     FloatItemsLayer          m_floatItemsLayer;
148     FogLayer                 m_fogLayer;
149     GroundLayer              m_groundLayer;
150     TextureLayer     m_textureLayer;
151     PlacemarkLayer   m_placemarkLayer;
152     VectorTileLayer  m_vectorTileLayer;
153 
154     bool m_isLockedToSubSolarPoint;
155     bool m_isSubSolarPointIconVisible;
156     RenderState m_renderState;
157 };
158 
MarbleMapPrivate(MarbleMap * parent,MarbleModel * model)159 MarbleMapPrivate::MarbleMapPrivate( MarbleMap *parent, MarbleModel *model ) :
160     q( parent ),
161     m_model( model ),
162     m_viewParams(),
163     m_showFrameRate( false ),
164     m_showDebugPolygons( false ),
165     m_showDebugBatchRender( false ),
166     m_visibleRelationTypes(GeoDataRelation::RouteFerry),
167     m_styleBuilder(),
168     m_layerManager( parent ),
169     m_customPaintLayer( parent ),
170     m_geometryLayer(model->treeModel(), &m_styleBuilder),
171     m_floatItemsLayer(parent),
172     m_textureLayer( model->downloadManager(), model->pluginManager(), model->sunLocator(), model->groundOverlayModel() ),
173     m_placemarkLayer( model->placemarkModel(), model->placemarkSelectionModel(), model->clock(), &m_styleBuilder ),
174     m_vectorTileLayer( model->downloadManager(), model->pluginManager(), model->treeModel() ),
175     m_isLockedToSubSolarPoint( false ),
176     m_isSubSolarPointIconVisible( false )
177 {
178     m_layerManager.addLayer(&m_floatItemsLayer);
179     m_layerManager.addLayer( &m_fogLayer );
180     m_layerManager.addLayer( &m_groundLayer );
181     m_layerManager.addLayer( &m_geometryLayer );
182     m_layerManager.addLayer( &m_placemarkLayer );
183     m_layerManager.addLayer( &m_customPaintLayer );
184 
185     m_model->bookmarkManager()->setStyleBuilder(&m_styleBuilder);
186 
187     QObject::connect( m_model, SIGNAL(themeChanged(QString)),
188                       parent, SLOT(updateMapTheme()) );
189     QObject::connect( m_model->fileManager(), SIGNAL(fileAdded(QString)),
190                       parent, SLOT(setDocument(QString)) );
191 
192 
193     QObject::connect( &m_placemarkLayer, SIGNAL(repaintNeeded()),
194                       parent, SIGNAL(repaintNeeded()));
195 
196     QObject::connect ( &m_layerManager, SIGNAL(pluginSettingsChanged()),
197                        parent,        SIGNAL(pluginSettingsChanged()) );
198     QObject::connect ( &m_layerManager, SIGNAL(repaintNeeded(QRegion)),
199                        parent,        SIGNAL(repaintNeeded(QRegion)) );
200     QObject::connect ( &m_layerManager, SIGNAL(renderPluginInitialized(RenderPlugin*)),
201                        parent,        SIGNAL(renderPluginInitialized(RenderPlugin*)) );
202     QObject::connect ( &m_layerManager, SIGNAL(visibilityChanged(QString,bool)),
203                        parent,        SLOT(setPropertyValue(QString,bool)) );
204 
205     QObject::connect( &m_geometryLayer, SIGNAL(repaintNeeded()),
206                       parent, SIGNAL(repaintNeeded()));
207 
208     /*
209      * Slot handleHighlight finds all placemarks
210      * that contain the clicked point.
211      * The placemarks under the clicked position may
212      * have their styleUrl set to a style map which
213      * doesn't specify any highlight styleId. Such
214      * placemarks will be fletered out in GeoGraphicsScene
215      * and will not be highlighted.
216      */
217     QObject::connect( parent, SIGNAL(highlightedPlacemarksChanged(qreal,qreal,GeoDataCoordinates::Unit)),
218                       &m_geometryLayer, SLOT(handleHighlight(qreal,qreal,GeoDataCoordinates::Unit)) );
219 
220     QObject::connect(&m_floatItemsLayer, SIGNAL(repaintNeeded(QRegion)),
221                      parent,             SIGNAL(repaintNeeded(QRegion)));
222     QObject::connect(&m_floatItemsLayer, SIGNAL(renderPluginInitialized(RenderPlugin*)),
223                      parent,             SIGNAL(renderPluginInitialized(RenderPlugin*)));
224     QObject::connect(&m_floatItemsLayer, SIGNAL(visibilityChanged(QString,bool)),
225                      parent,             SLOT(setPropertyValue(QString,bool)));
226     QObject::connect(&m_floatItemsLayer, SIGNAL(pluginSettingsChanged()),
227                      parent,             SIGNAL(pluginSettingsChanged()));
228 
229     QObject::connect( &m_textureLayer, SIGNAL(tileLevelChanged(int)),
230                       parent, SLOT(updateTileLevel()) );
231     QObject::connect( &m_vectorTileLayer, SIGNAL(tileLevelChanged(int)),
232                       parent, SLOT(updateTileLevel()) );
233     QObject::connect( parent, SIGNAL(radiusChanged(int)),
234                       parent, SLOT(updateTileLevel()) );
235 
236     QObject::connect( &m_textureLayer, SIGNAL(repaintNeeded()),
237                       parent, SIGNAL(repaintNeeded()) );
238     QObject::connect( parent, SIGNAL(visibleLatLonAltBoxChanged(GeoDataLatLonAltBox)),
239                       parent, SIGNAL(repaintNeeded()) );
240 
241     addPlugins();
242     QObject::connect(model->pluginManager(), SIGNAL(renderPluginsChanged()),
243                      parent, SLOT(addPlugins()));
244 }
245 
updateProperty(const QString & name,bool show)246 void MarbleMapPrivate::updateProperty( const QString &name, bool show )
247 {
248     // earth
249     if (name == QLatin1String("places")) {
250         m_placemarkLayer.setShowPlaces( show );
251     } else if (name == QLatin1String("cities")) {
252         m_placemarkLayer.setShowCities( show );
253     } else if (name == QLatin1String("terrain")) {
254         m_placemarkLayer.setShowTerrain( show );
255     } else if (name == QLatin1String("otherplaces")) {
256         m_placemarkLayer.setShowOtherPlaces( show );
257     }
258 
259     // other planets
260     else if (name == QLatin1String("landingsites")) {
261         m_placemarkLayer.setShowLandingSites( show );
262     } else if (name == QLatin1String("craters")) {
263         m_placemarkLayer.setShowCraters( show );
264     } else if (name == QLatin1String("maria")) {
265         m_placemarkLayer.setShowMaria( show );
266     }
267 
268     else if (name == QLatin1String("relief")) {
269         m_textureLayer.setShowRelief( show );
270     }
271 
272     for(RenderPlugin *renderPlugin: m_renderPlugins) {
273         if ( name == renderPlugin->nameId() ) {
274             if ( renderPlugin->visible() == show ) {
275                 break;
276             }
277 
278             renderPlugin->setVisible( show );
279 
280             break;
281         }
282     }
283 }
284 
addPlugins()285 void MarbleMapPrivate::addPlugins()
286 {
287     for (const RenderPlugin *factory: m_model->pluginManager()->renderPlugins()) {
288         bool alreadyCreated = false;
289         for(const RenderPlugin *existing: m_renderPlugins) {
290             if (existing->nameId() == factory->nameId()) {
291                 alreadyCreated = true;
292                 break;
293             }
294         }
295 
296         if (alreadyCreated) {
297             continue;
298         }
299 
300         RenderPlugin *const renderPlugin = factory->newInstance(m_model);
301         Q_ASSERT(renderPlugin && "Plugin must not return null when requesting a new instance.");
302         m_renderPlugins << renderPlugin;
303 
304         if (AbstractFloatItem *const floatItem = qobject_cast<AbstractFloatItem *>(renderPlugin)) {
305             m_floatItemsLayer.addFloatItem(floatItem);
306         }
307         else {
308             m_layerManager.addRenderPlugin(renderPlugin);
309         }
310     }
311 }
312 
313 // ----------------------------------------------------------------
314 
315 
MarbleMap()316 MarbleMap::MarbleMap()
317     : d( new MarbleMapPrivate( this, new MarbleModel( this ) ) )
318 {
319     // nothing to do
320 }
321 
MarbleMap(MarbleModel * model)322 MarbleMap::MarbleMap(MarbleModel *model)
323     : d( new MarbleMapPrivate( this, model ) )
324 {
325     d->m_modelIsOwned = false;
326 }
327 
~MarbleMap()328 MarbleMap::~MarbleMap()
329 {
330     MarbleModel *model = d->m_modelIsOwned ? d->m_model : nullptr;
331 
332     d->m_layerManager.removeLayer( &d->m_customPaintLayer );
333     d->m_layerManager.removeLayer( &d->m_geometryLayer );
334     d->m_layerManager.removeLayer(&d->m_floatItemsLayer);
335     d->m_layerManager.removeLayer( &d->m_fogLayer );
336     d->m_layerManager.removeLayer( &d->m_placemarkLayer );
337     d->m_layerManager.removeLayer( &d->m_textureLayer );
338     d->m_layerManager.removeLayer( &d->m_groundLayer );
339     qDeleteAll(d->m_renderPlugins);
340     delete d;
341 
342     delete model;  // delete the model after private data
343 }
344 
model() const345 MarbleModel *MarbleMap::model() const
346 {
347     return d->m_model;
348 }
349 
viewport()350 ViewportParams *MarbleMap::viewport()
351 {
352     return &d->m_viewport;
353 }
354 
viewport() const355 const ViewportParams *MarbleMap::viewport() const
356 {
357     return &d->m_viewport;
358 }
359 
360 
setMapQualityForViewContext(MapQuality quality,ViewContext viewContext)361 void MarbleMap::setMapQualityForViewContext( MapQuality quality, ViewContext viewContext )
362 {
363     d->m_viewParams.setMapQualityForViewContext( quality, viewContext );
364 
365     // Update texture map during the repaint that follows:
366     d->m_textureLayer.setNeedsUpdate();
367 }
368 
mapQuality(ViewContext viewContext) const369 MapQuality MarbleMap::mapQuality( ViewContext viewContext ) const
370 {
371     return d->m_viewParams.mapQuality( viewContext );
372 }
373 
mapQuality() const374 MapQuality MarbleMap::mapQuality() const
375 {
376     return d->m_viewParams.mapQuality();
377 }
378 
setViewContext(ViewContext viewContext)379 void MarbleMap::setViewContext( ViewContext viewContext )
380 {
381     if ( d->m_viewParams.viewContext() == viewContext ) {
382         return;
383     }
384 
385     const MapQuality oldQuality = d->m_viewParams.mapQuality();
386     d->m_viewParams.setViewContext( viewContext );
387     emit viewContextChanged( viewContext );
388 
389     if ( d->m_viewParams.mapQuality() != oldQuality ) {
390         // Update texture map during the repaint that follows:
391         d->m_textureLayer.setNeedsUpdate();
392 
393         emit repaintNeeded();
394     }
395 }
396 
viewContext() const397 ViewContext MarbleMap::viewContext() const
398 {
399     return d->m_viewParams.viewContext();
400 }
401 
402 
setSize(int width,int height)403 void MarbleMap::setSize( int width, int height )
404 {
405     setSize( QSize( width, height ) );
406 }
407 
setSize(const QSize & size)408 void MarbleMap::setSize( const QSize& size )
409 {
410     d->m_viewport.setSize( size );
411 
412     emit visibleLatLonAltBoxChanged( d->m_viewport.viewLatLonAltBox() );
413 }
414 
size() const415 QSize MarbleMap::size() const
416 {
417     return QSize( d->m_viewport.width(), d->m_viewport.height() );
418 }
419 
width() const420 int  MarbleMap::width() const
421 {
422     return d->m_viewport.width();
423 }
424 
height() const425 int  MarbleMap::height() const
426 {
427     return d->m_viewport.height();
428 }
429 
radius() const430 int MarbleMap::radius() const
431 {
432     return d->m_viewport.radius();
433 }
434 
setRadius(int radius)435 void MarbleMap::setRadius( int radius )
436 {
437     const int oldRadius = d->m_viewport.radius();
438 
439     d->m_viewport.setRadius( radius );
440 
441     if ( oldRadius != d->m_viewport.radius() ) {
442         emit radiusChanged( radius );
443         emit visibleLatLonAltBoxChanged( d->m_viewport.viewLatLonAltBox() );
444     }
445 }
446 
447 
preferredRadiusCeil(int radius) const448 int MarbleMap::preferredRadiusCeil(int radius) const
449 {
450     return d->m_textureLayer.preferredRadiusCeil( radius );
451 }
452 
453 
preferredRadiusFloor(int radius) const454 int MarbleMap::preferredRadiusFloor(int radius) const
455 {
456     return d->m_textureLayer.preferredRadiusFloor( radius );
457 }
458 
459 
tileZoomLevel() const460 int MarbleMap::tileZoomLevel() const
461 {
462     auto const tileZoomLevel = qMax(d->m_textureLayer.tileZoomLevel(), d->m_vectorTileLayer.tileZoomLevel());
463     return tileZoomLevel >= 0 ? tileZoomLevel : qMin<int>(qMax<int>(qLn(d->m_viewport.radius()*4/256)/qLn(2.0), 1), d->m_styleBuilder.maximumZoomLevel());
464 }
465 
466 
centerLatitude() const467 qreal MarbleMap::centerLatitude() const
468 {
469     // Calculate translation of center point
470     const qreal centerLat = d->m_viewport.centerLatitude();
471 
472     return centerLat * RAD2DEG;
473 }
474 
hasFeatureAt(const QPoint & position) const475 bool MarbleMap::hasFeatureAt(const QPoint &position) const
476 {
477     return d->m_placemarkLayer.hasPlacemarkAt(position) || d->m_geometryLayer.hasFeatureAt(position, viewport());
478 }
479 
centerLongitude() const480 qreal MarbleMap::centerLongitude() const
481 {
482     // Calculate translation of center point
483     const qreal centerLon = d->m_viewport.centerLongitude();
484 
485     return centerLon * RAD2DEG;
486 }
487 
minimumZoom() const488 int  MarbleMap::minimumZoom() const
489 {
490     if ( d->m_model->mapTheme() )
491         return d->m_model->mapTheme()->head()->zoom()->minimum();
492 
493     return 950;
494 }
495 
maximumZoom() const496 int  MarbleMap::maximumZoom() const
497 {
498     if ( d->m_model->mapTheme() )
499         return d->m_model->mapTheme()->head()->zoom()->maximum();
500 
501     return 2100;
502 }
503 
discreteZoom() const504 bool MarbleMap::discreteZoom() const
505 {
506     if ( d->m_model->mapTheme() )
507         return d->m_model->mapTheme()->head()->zoom()->discrete();
508 
509     return false;
510 }
511 
whichFeatureAt(const QPoint & curpos) const512 QVector<const GeoDataFeature*> MarbleMap::whichFeatureAt( const QPoint& curpos ) const
513 {
514     return d->m_placemarkLayer.whichPlacemarkAt( curpos ) + d->m_geometryLayer.whichFeatureAt( curpos, viewport() );
515 }
516 
reload()517 void MarbleMap::reload()
518 {
519     d->m_textureLayer.reload();
520     d->m_vectorTileLayer.reload();
521 }
522 
downloadRegion(QVector<TileCoordsPyramid> const & pyramid)523 void MarbleMap::downloadRegion( QVector<TileCoordsPyramid> const & pyramid )
524 {
525     Q_ASSERT( textureLayer() );
526     Q_ASSERT( !pyramid.isEmpty() );
527     QElapsedTimer t;
528     t.start();
529 
530     // When downloading a region (the author of these lines thinks) most users probably expect
531     // the download to begin with the low resolution tiles and then procede level-wise to
532     // higher resolution tiles. In order to achieve this, we start requesting downloads of
533     // high resolution tiles and request the low resolution tiles at the end because
534     // DownloadQueueSet (silly name) is implemented as stack.
535 
536 
537     int const first = 0;
538     int tilesCount = 0;
539 
540     for ( int level = pyramid[first].bottomLevel(); level >= pyramid[first].topLevel(); --level ) {
541         QSet<TileId> tileIdSet;
542         for( int i = 0; i < pyramid.size(); ++i ) {
543             QRect const coords = pyramid[i].coords( level );
544             mDebug() << "MarbleMap::downloadRegion level:" << level << "tile coords:" << coords;
545             int x1, y1, x2, y2;
546             coords.getCoords( &x1, &y1, &x2, &y2 );
547             for ( int x = x1; x <= x2; ++x ) {
548                 for ( int y = y1; y <= y2; ++y ) {
549                     TileId const stackedTileId( 0, level, x, y );
550                     tileIdSet.insert( stackedTileId );
551                     // FIXME: use lazy evaluation to not generate up to 100k tiles in one go
552                     // this can take considerable time even on very fast systems
553                     // in contrast generating the TileIds on the fly when they are needed
554                     // does not seem to affect download speed.
555                 }
556             }
557         }
558         QSetIterator<TileId> i( tileIdSet );
559         while( i.hasNext() ) {
560             TileId const tileId = i.next();
561             d->m_textureLayer.downloadStackedTile( tileId );
562         }
563         tilesCount += tileIdSet.count();
564     }
565     // Needed for downloading unique tiles only. Much faster than if tiles for each level is downloaded separately
566 
567     int const elapsedMs = t.elapsed();
568     mDebug() << "MarbleMap::downloadRegion:" << tilesCount << "tiles, " << elapsedMs << "ms";
569 }
570 
highlightRouteRelation(qint64 osmId,bool enabled)571 void MarbleMap::highlightRouteRelation(qint64 osmId, bool enabled)
572 {
573     d->m_geometryLayer.highlightRouteRelation(osmId, enabled);
574 }
575 
propertyValue(const QString & name) const576 bool MarbleMap::propertyValue( const QString& name ) const
577 {
578     bool value;
579     if ( d->m_model->mapTheme() ) {
580         d->m_model->mapTheme()->settings()->propertyValue( name, value );
581     }
582     else {
583         value = false;
584         mDebug() << "WARNING: Failed to access a map theme! Property: " << name;
585     }
586     return value;
587 }
588 
showOverviewMap() const589 bool MarbleMap::showOverviewMap() const
590 {
591     return propertyValue(QStringLiteral("overviewmap"));
592 }
593 
showScaleBar() const594 bool MarbleMap::showScaleBar() const
595 {
596     return propertyValue(QStringLiteral("scalebar"));
597 }
598 
showCompass() const599 bool MarbleMap::showCompass() const
600 {
601     return propertyValue(QStringLiteral("compass"));
602 }
603 
showGrid() const604 bool MarbleMap::showGrid() const
605 {
606     return propertyValue(QStringLiteral("coordinate-grid"));
607 }
608 
showClouds() const609 bool MarbleMap::showClouds() const
610 {
611     return d->m_viewParams.showClouds();
612 }
613 
showSunShading() const614 bool MarbleMap::showSunShading() const
615 {
616     return d->m_textureLayer.showSunShading();
617 }
618 
showCityLights() const619 bool MarbleMap::showCityLights() const
620 {
621     return d->m_textureLayer.showCityLights();
622 }
623 
isLockedToSubSolarPoint() const624 bool MarbleMap::isLockedToSubSolarPoint() const
625 {
626     return d->m_isLockedToSubSolarPoint;
627 }
628 
isSubSolarPointIconVisible() const629 bool MarbleMap::isSubSolarPointIconVisible() const
630 {
631     return d->m_isSubSolarPointIconVisible;
632 }
633 
showAtmosphere() const634 bool MarbleMap::showAtmosphere() const
635 {
636     return d->m_viewParams.showAtmosphere();
637 }
638 
showCrosshairs() const639 bool MarbleMap::showCrosshairs() const
640 {
641     bool visible = false;
642 
643     QList<RenderPlugin *> pluginList = renderPlugins();
644     QList<RenderPlugin *>::const_iterator i = pluginList.constBegin();
645     QList<RenderPlugin *>::const_iterator const end = pluginList.constEnd();
646     for (; i != end; ++i ) {
647         if ((*i)->nameId() == QLatin1String("crosshairs")) {
648             visible = (*i)->visible();
649         }
650     }
651 
652     return visible;
653 }
654 
showPlaces() const655 bool MarbleMap::showPlaces() const
656 {
657     return propertyValue(QStringLiteral("places"));
658 }
659 
showCities() const660 bool MarbleMap::showCities() const
661 {
662     return propertyValue(QStringLiteral("cities"));
663 }
664 
showTerrain() const665 bool MarbleMap::showTerrain() const
666 {
667     return propertyValue(QStringLiteral("terrain"));
668 }
669 
showOtherPlaces() const670 bool MarbleMap::showOtherPlaces() const
671 {
672     return propertyValue(QStringLiteral("otherplaces"));
673 }
674 
showRelief() const675 bool MarbleMap::showRelief() const
676 {
677     return propertyValue(QStringLiteral("relief"));
678 }
679 
showIceLayer() const680 bool MarbleMap::showIceLayer() const
681 {
682     return propertyValue(QStringLiteral("ice"));
683 }
684 
showBorders() const685 bool MarbleMap::showBorders() const
686 {
687     return propertyValue(QStringLiteral("borders"));
688 }
689 
showRivers() const690 bool MarbleMap::showRivers() const
691 {
692     return propertyValue(QStringLiteral("rivers"));
693 }
694 
showLakes() const695 bool MarbleMap::showLakes() const
696 {
697     return propertyValue(QStringLiteral("lakes"));
698 }
699 
showFrameRate() const700 bool MarbleMap::showFrameRate() const
701 {
702     return d->m_showFrameRate;
703 }
704 
showBackground() const705 bool MarbleMap::showBackground() const
706 {
707     return d->m_layerManager.showBackground();
708 }
709 
visibleRelationTypes() const710 GeoDataRelation::RelationTypes MarbleMap::visibleRelationTypes() const
711 {
712     return d->m_visibleRelationTypes;
713 }
714 
volatileTileCacheLimit() const715 quint64 MarbleMap::volatileTileCacheLimit() const
716 {
717     return d->m_textureLayer.volatileCacheLimit();
718 }
719 
720 
rotateBy(qreal deltaLon,qreal deltaLat)721 void MarbleMap::rotateBy(qreal deltaLon, qreal deltaLat)
722 {
723     centerOn( d->m_viewport.centerLongitude() * RAD2DEG + deltaLon,
724               d->m_viewport.centerLatitude()  * RAD2DEG + deltaLat );
725 }
726 
727 
centerOn(const qreal lon,const qreal lat)728 void MarbleMap::centerOn( const qreal lon, const qreal lat )
729 {
730     d->m_viewport.centerOn( lon * DEG2RAD, lat * DEG2RAD );
731 
732     emit visibleLatLonAltBoxChanged( d->m_viewport.viewLatLonAltBox() );
733 }
734 
setCenterLatitude(qreal lat)735 void MarbleMap::setCenterLatitude( qreal lat )
736 {
737     centerOn( centerLongitude(), lat );
738 }
739 
setCenterLongitude(qreal lon)740 void MarbleMap::setCenterLongitude( qreal lon )
741 {
742     centerOn( lon, centerLatitude() );
743 }
744 
projection() const745 Projection MarbleMap::projection() const
746 {
747     return d->m_viewport.projection();
748 }
749 
setProjection(Projection projection)750 void MarbleMap::setProjection( Projection projection )
751 {
752     if ( d->m_viewport.projection() == projection )
753         return;
754 
755     emit projectionChanged( projection );
756 
757     d->m_viewport.setProjection( projection );
758 
759     d->m_textureLayer.setProjection( projection );
760 
761     emit visibleLatLonAltBoxChanged( d->m_viewport.viewLatLonAltBox() );
762 }
763 
764 
screenCoordinates(qreal lon,qreal lat,qreal & x,qreal & y) const765 bool MarbleMap::screenCoordinates( qreal lon, qreal lat,
766                                    qreal& x, qreal& y ) const
767 {
768     return d->m_viewport.screenCoordinates( lon * DEG2RAD, lat * DEG2RAD, x, y );
769 }
770 
geoCoordinates(int x,int y,qreal & lon,qreal & lat,GeoDataCoordinates::Unit unit) const771 bool MarbleMap::geoCoordinates( int x, int y,
772                                 qreal& lon, qreal& lat,
773                                 GeoDataCoordinates::Unit unit ) const
774 {
775     return d->m_viewport.geoCoordinates( x, y, lon, lat, unit );
776 }
777 
setDocument(const QString & key)778 void MarbleMapPrivate::setDocument( const QString& key )
779 {
780     if ( !m_model->mapTheme() ) {
781         // Happens if no valid map theme is set or at application startup
782         // if a file is passed via command line parameters and the last
783         // map theme has not been loaded yet
784         /**
785          * @todo Do we need to queue the document and process it once a map
786          * theme becomes available?
787          */
788         return;
789     }
790 
791     GeoDataDocument* doc = m_model->fileManager()->at( key );
792 
793     for ( const GeoSceneLayer *layer: m_model->mapTheme()->map()->layers() ) {
794         if ( layer->backend() != dgml::dgmlValue_geodata
795              && layer->backend() != dgml::dgmlValue_vector )
796             continue;
797 
798         // look for documents
799         for ( const GeoSceneAbstractDataset *dataset: layer->datasets() ) {
800             const GeoSceneGeodata *data = static_cast<const GeoSceneGeodata*>( dataset );
801             QString containername = data->sourceFile();
802             QString colorize = data->colorize();
803             if( key == containername ) {
804                 if (colorize == QLatin1String("land")) {
805                     m_textureLayer.addLandDocument( doc );
806                 }
807                 if (colorize == QLatin1String("sea")) {
808                     m_textureLayer.addSeaDocument( doc );
809                 }
810 
811                 // set visibility according to theme property
812                 if( !data->property().isEmpty() ) {
813                     bool value;
814                     m_model->mapTheme()->settings()->propertyValue( data->property(), value );
815                     doc->setVisible( value );
816                     m_model->treeModel()->updateFeature( doc );
817                 }
818             }
819         }
820     }
821 }
822 
updateTileLevel()823 void MarbleMapPrivate::updateTileLevel()
824 {
825     auto const tileZoomLevel = q->tileZoomLevel();
826     m_geometryLayer.setTileLevel(tileZoomLevel);
827     m_placemarkLayer.setTileLevel(tileZoomLevel);
828     emit q->tileLevelChanged(tileZoomLevel);
829 }
830 
831 // Used to be paintEvent()
paint(GeoPainter & painter,const QRect & dirtyRect)832 void MarbleMap::paint( GeoPainter &painter, const QRect &dirtyRect )
833 {
834     Q_UNUSED( dirtyRect );
835 
836     if (d->m_showDebugPolygons ) {
837         if (viewContext() == Animation) {
838             painter.setDebugPolygonsLevel(1);
839         }
840         else {
841             painter.setDebugPolygonsLevel(2);
842         }
843     }
844     painter.setDebugBatchRender(d->m_showDebugBatchRender);
845 
846     if ( !d->m_model->mapTheme() ) {
847         mDebug() << "No theme yet!";
848         d->m_marbleSplashLayer.render( &painter, &d->m_viewport );
849         return;
850     }
851 
852     QElapsedTimer t;
853     t.start();
854 
855     RenderStatus const oldRenderStatus = d->m_renderState.status();
856     d->m_layerManager.renderLayers( &painter, &d->m_viewport );
857     d->m_renderState = d->m_layerManager.renderState();
858     bool const parsing = d->m_model->fileManager()->pendingFiles() > 0;
859     d->m_renderState.addChild(RenderState(QStringLiteral("Files"), parsing ? WaitingForData : Complete));
860     RenderStatus const newRenderStatus = d->m_renderState.status();
861     if ( oldRenderStatus != newRenderStatus ) {
862         emit renderStatusChanged( newRenderStatus );
863     }
864     emit renderStateChanged( d->m_renderState );
865 
866     if ( d->m_showFrameRate ) {
867         FpsLayer fpsPainter( &t );
868         fpsPainter.paint( &painter );
869     }
870 
871     const qreal fps = 1000.0 / (qreal)( t.elapsed() );
872     emit framesPerSecond( fps );
873 }
874 
customPaint(GeoPainter * painter)875 void MarbleMap::customPaint( GeoPainter *painter )
876 {
877     Q_UNUSED( painter );
878 }
879 
mapThemeId() const880 QString MarbleMap::mapThemeId() const
881 {
882     return d->m_model->mapThemeId();
883 }
884 
setMapThemeId(const QString & mapThemeId)885 void MarbleMap::setMapThemeId( const QString& mapThemeId )
886 {
887     d->m_model->setMapThemeId( mapThemeId );
888 }
889 
updateMapTheme()890 void MarbleMapPrivate::updateMapTheme()
891 {
892     m_layerManager.removeLayer( &m_textureLayer );
893     // FIXME Find a better way to do this reset. Maybe connect to themeChanged SIGNAL?
894     m_vectorTileLayer.reset();
895     m_layerManager.removeLayer( &m_vectorTileLayer );
896     m_layerManager.removeLayer( &m_groundLayer );
897 
898     QObject::connect( m_model->mapTheme()->settings(), SIGNAL(valueChanged(QString,bool)),
899                       q, SLOT(updateProperty(QString,bool)) );
900     QObject::connect( m_model->mapTheme()->settings(), SIGNAL(valueChanged(QString,bool)),
901                       m_model, SLOT(updateProperty(QString,bool)) );
902 
903     q->setPropertyValue(QStringLiteral("clouds_data"), m_viewParams.showClouds());
904     m_groundLayer.setColor( m_model->mapTheme()->map()->backgroundColor() );
905 
906     // Check whether there is a texture layer and vectortile layer available:
907     if ( m_model->mapTheme()->map()->hasTextureLayers() ) {
908         const GeoSceneSettings *const settings = m_model->mapTheme()->settings();
909         const GeoSceneGroup *const textureLayerSettings = settings ? settings->group( "Texture Layers" ) : nullptr;
910         const GeoSceneGroup *const vectorTileLayerSettings = settings ? settings->group( "VectorTile Layers" ) : nullptr;
911 
912         bool textureLayersOk = true;
913         bool vectorTileLayersOk = true;
914 
915         // textures will contain texture layers and
916         // vectorTiles vectortile layers
917         QVector<const GeoSceneTextureTileDataset *> textures;
918         QVector<const GeoSceneVectorTileDataset *> vectorTiles;
919 
920         for( GeoSceneLayer* layer: m_model->mapTheme()->map()->layers() ){
921             if ( layer->backend() == dgml::dgmlValue_texture ){
922 
923                 for ( const GeoSceneAbstractDataset *pos: layer->datasets() ) {
924                     const GeoSceneTextureTileDataset *const texture = dynamic_cast<GeoSceneTextureTileDataset const *>( pos );
925                     if ( !texture )
926                         continue;
927 
928                     const QString sourceDir = texture->sourceDir();
929                     const QString installMap = texture->installMap();
930                     const QString role = layer->role();
931 
932                     // If the tiles aren't already there, put up a progress dialog
933                     // while creating them.
934                     if ( !TileLoader::baseTilesAvailable( *texture )
935                          && !installMap.isEmpty() )
936                     {
937                         mDebug() << "Base tiles not available. Creating Tiles ... \n"
938                                  << "SourceDir: " << sourceDir << "InstallMap:" << installMap;
939 
940                         TileCreator *tileCreator = new TileCreator(
941                                     sourceDir,
942                                     installMap,
943                                     (role == QLatin1String("dem")) ? "true" : "false" );
944                         tileCreator->setTileFormat( texture->fileFormat().toLower() );
945 
946                         QPointer<TileCreatorDialog> tileCreatorDlg = new TileCreatorDialog( tileCreator, nullptr );
947                         tileCreatorDlg->setSummary( m_model->mapTheme()->head()->name(),
948                                                     m_model->mapTheme()->head()->description() );
949                         tileCreatorDlg->exec();
950                         if ( TileLoader::baseTilesAvailable( *texture ) ) {
951                             mDebug() << "Base tiles for" << sourceDir << "successfully created.";
952                         } else {
953                             qWarning() << "Some or all base tiles for" << sourceDir << "could not be created.";
954                         }
955 
956                         delete tileCreatorDlg;
957                     }
958 
959                     if ( TileLoader::baseTilesAvailable( *texture ) ) {
960                         textures.append( texture );
961                     } else {
962                         qWarning() << "Base tiles for" << sourceDir << "not available. Skipping all texture layers.";
963                         textureLayersOk = false;
964                     }
965                 }
966             }
967             else if ( layer->backend() == dgml::dgmlValue_vectortile ){
968 
969                 for ( const GeoSceneAbstractDataset *pos: layer->datasets() ) {
970                     const GeoSceneVectorTileDataset *const vectorTile = dynamic_cast<GeoSceneVectorTileDataset const *>( pos );
971                     if ( !vectorTile )
972                         continue;
973 
974                     const QString sourceDir = vectorTile->sourceDir();
975                     const QString installMap = vectorTile->installMap();
976                     const QString role = layer->role();
977 
978                     // If the tiles aren't already there, put up a progress dialog
979                     // while creating them.
980                     if ( !TileLoader::baseTilesAvailable( *vectorTile )
981                          && !installMap.isEmpty() )
982                     {
983                         mDebug() << "Base tiles not available. Creating Tiles ... \n"
984                                  << "SourceDir: " << sourceDir << "InstallMap:" << installMap;
985 
986                         TileCreator *tileCreator = new TileCreator(
987                                     sourceDir,
988                                     installMap,
989                                     (role == QLatin1String("dem")) ? "true" : "false" );
990                         tileCreator->setTileFormat( vectorTile->fileFormat().toLower() );
991 
992                         QPointer<TileCreatorDialog> tileCreatorDlg = new TileCreatorDialog( tileCreator, nullptr );
993                         tileCreatorDlg->setSummary( m_model->mapTheme()->head()->name(),
994                                                     m_model->mapTheme()->head()->description() );
995                         tileCreatorDlg->exec();
996                         if ( TileLoader::baseTilesAvailable( *vectorTile ) ) {
997                             qDebug() << "Base tiles for" << sourceDir << "successfully created.";
998                         } else {
999                             qDebug() << "Some or all base tiles for" << sourceDir << "could not be created.";
1000                         }
1001 
1002                         delete tileCreatorDlg;
1003                     }
1004 
1005                     if ( TileLoader::baseTilesAvailable( *vectorTile ) ) {
1006                         vectorTiles.append( vectorTile );
1007                     } else {
1008                         qWarning() << "Base tiles for" << sourceDir << "not available. Skipping all texture layers.";
1009                         vectorTileLayersOk = false;
1010                     }
1011                 }
1012             }
1013         }
1014 
1015         QString seafile, landfile;
1016         if( !m_model->mapTheme()->map()->filters().isEmpty() ) {
1017             const GeoSceneFilter *filter= m_model->mapTheme()->map()->filters().first();
1018 
1019             if (filter->type() == QLatin1String("colorize")) {
1020                 //no need to look up with MarbleDirs twice so they are left null for now
1021                 QList<const GeoScenePalette*> palette = filter->palette();
1022                 for (const GeoScenePalette *curPalette: palette ) {
1023 
1024                     if (curPalette->type() == QLatin1String("sea")) {
1025                         seafile = MarbleDirs::path( curPalette->file() );
1026                     } else if (curPalette->type() == QLatin1String("land")) {
1027                         landfile = MarbleDirs::path( curPalette->file() );
1028                     }
1029                 }
1030                 //look up locations if they are empty
1031                 if( seafile.isEmpty() )
1032                     seafile = MarbleDirs::path(QStringLiteral("seacolors.leg"));
1033                 if( landfile.isEmpty() )
1034                     landfile = MarbleDirs::path(QStringLiteral("landcolors.leg"));
1035             }
1036         }
1037 
1038         m_textureLayer.setMapTheme( textures, textureLayerSettings, seafile, landfile );
1039         m_textureLayer.setProjection( m_viewport.projection() );
1040         m_textureLayer.setShowRelief( q->showRelief() );
1041 
1042         m_vectorTileLayer.setMapTheme( vectorTiles, vectorTileLayerSettings );
1043 
1044         if (m_textureLayer.textureLayerCount() == 0) {
1045             m_layerManager.addLayer( &m_groundLayer );
1046         }
1047 
1048         if ( textureLayersOk )
1049             m_layerManager.addLayer( &m_textureLayer );
1050         if ( vectorTileLayersOk && !vectorTiles.isEmpty() )
1051             m_layerManager.addLayer( &m_vectorTileLayer );
1052     }
1053     else {
1054         m_layerManager.addLayer( &m_groundLayer );
1055         m_textureLayer.setMapTheme( QVector<const GeoSceneTextureTileDataset *>(), nullptr, "", "" );
1056         m_vectorTileLayer.setMapTheme( QVector<const GeoSceneVectorTileDataset *>(), nullptr );
1057     }
1058 
1059     // earth
1060     m_placemarkLayer.setShowPlaces( q->showPlaces() );
1061 
1062     m_placemarkLayer.setShowCities( q->showCities() );
1063     m_placemarkLayer.setShowTerrain( q->showTerrain() );
1064     m_placemarkLayer.setShowOtherPlaces( q->showOtherPlaces() );
1065     m_placemarkLayer.setShowLandingSites(q->propertyValue(QStringLiteral("landingsites")));
1066     m_placemarkLayer.setShowCraters(q->propertyValue(QStringLiteral("craters")));
1067     m_placemarkLayer.setShowMaria(q->propertyValue(QStringLiteral("maria")));
1068 
1069     m_styleBuilder.setDefaultLabelColor(m_model->mapTheme()->map()->labelColor());
1070     m_placemarkLayer.requestStyleReset();
1071 
1072     for (RenderPlugin *renderPlugin: m_renderPlugins) {
1073         bool propertyAvailable = false;
1074         m_model->mapTheme()->settings()->propertyAvailable( renderPlugin->nameId(), propertyAvailable );
1075         bool propertyValue = false;
1076         m_model->mapTheme()->settings()->propertyValue( renderPlugin->nameId(), propertyValue );
1077 
1078         if ( propertyAvailable ) {
1079             renderPlugin->setVisible( propertyValue );
1080         }
1081     }
1082 
1083     emit q->themeChanged( m_model->mapTheme()->head()->mapThemeId() );
1084 }
1085 
setPropertyValue(const QString & name,bool value)1086 void MarbleMap::setPropertyValue( const QString& name, bool value )
1087 {
1088     mDebug() << "In MarbleMap the property " << name << "was set to " << value;
1089     if ( d->m_model->mapTheme() ) {
1090         d->m_model->mapTheme()->settings()->setPropertyValue( name, value );
1091         d->m_textureLayer.setNeedsUpdate();
1092     }
1093     else {
1094         mDebug() << "WARNING: Failed to access a map theme! Property: " << name;
1095     }
1096     if (d->m_textureLayer.textureLayerCount() == 0) {
1097         d->m_layerManager.addLayer( &d->m_groundLayer );
1098     }
1099     else {
1100         d->m_layerManager.removeLayer( &d->m_groundLayer );
1101     }
1102 }
1103 
setShowOverviewMap(bool visible)1104 void MarbleMap::setShowOverviewMap( bool visible )
1105 {
1106     setPropertyValue(QStringLiteral("overviewmap"), visible);
1107 }
1108 
setShowScaleBar(bool visible)1109 void MarbleMap::setShowScaleBar( bool visible )
1110 {
1111     setPropertyValue(QStringLiteral("scalebar"), visible);
1112 }
1113 
setShowCompass(bool visible)1114 void MarbleMap::setShowCompass( bool visible )
1115 {
1116     setPropertyValue(QStringLiteral("compass"), visible);
1117 }
1118 
setShowAtmosphere(bool visible)1119 void MarbleMap::setShowAtmosphere( bool visible )
1120 {
1121     for ( RenderPlugin *plugin: renderPlugins() ) {
1122         if (plugin->nameId() == QLatin1String("atmosphere")) {
1123             plugin->setVisible( visible );
1124         }
1125     }
1126 
1127     d->m_viewParams.setShowAtmosphere( visible );
1128 }
1129 
setShowCrosshairs(bool visible)1130 void MarbleMap::setShowCrosshairs( bool visible )
1131 {
1132     QList<RenderPlugin *> pluginList = renderPlugins();
1133     QList<RenderPlugin *>::const_iterator i = pluginList.constBegin();
1134     QList<RenderPlugin *>::const_iterator const end = pluginList.constEnd();
1135     for (; i != end; ++i ) {
1136         if ((*i)->nameId() == QLatin1String("crosshairs")) {
1137             (*i)->setVisible( visible );
1138         }
1139     }
1140 }
1141 
setShowClouds(bool visible)1142 void MarbleMap::setShowClouds( bool visible )
1143 {
1144     d->m_viewParams.setShowClouds( visible );
1145 
1146     setPropertyValue(QStringLiteral("clouds_data"), visible);
1147 }
1148 
setShowSunShading(bool visible)1149 void MarbleMap::setShowSunShading( bool visible )
1150 {
1151     d->m_textureLayer.setShowSunShading( visible );
1152 }
1153 
setShowCityLights(bool visible)1154 void MarbleMap::setShowCityLights( bool visible )
1155 {
1156     d->m_textureLayer.setShowCityLights( visible );
1157     setPropertyValue(QStringLiteral("citylights"), visible);
1158 }
1159 
setLockToSubSolarPoint(bool visible)1160 void MarbleMap::setLockToSubSolarPoint( bool visible )
1161 {
1162     disconnect( d->m_model->sunLocator(), SIGNAL(positionChanged(qreal,qreal)),
1163                 this,                     SLOT(centerOn(qreal,qreal)) );
1164 
1165     if( isLockedToSubSolarPoint() != visible ) {
1166         d->m_isLockedToSubSolarPoint = visible;
1167     }
1168 
1169     if ( isLockedToSubSolarPoint() ) {
1170         connect( d->m_model->sunLocator(), SIGNAL(positionChanged(qreal,qreal)),
1171                  this,                     SLOT(centerOn(qreal,qreal)) );
1172 
1173         centerOn( d->m_model->sunLocator()->getLon(), d->m_model->sunLocator()->getLat() );
1174     } else if ( visible ) {
1175         mDebug() << "Ignoring centering on sun, since the sun plugin is not loaded.";
1176     }
1177 }
1178 
setSubSolarPointIconVisible(bool visible)1179 void MarbleMap::setSubSolarPointIconVisible( bool visible )
1180 {
1181     if ( isSubSolarPointIconVisible() != visible ) {
1182         d->m_isSubSolarPointIconVisible = visible;
1183     }
1184 }
1185 
setShowTileId(bool visible)1186 void MarbleMap::setShowTileId( bool visible )
1187 {
1188     d->m_textureLayer.setShowTileId( visible );
1189 }
1190 
setShowGrid(bool visible)1191 void MarbleMap::setShowGrid( bool visible )
1192 {
1193     setPropertyValue(QStringLiteral("coordinate-grid"), visible);
1194 }
1195 
setShowPlaces(bool visible)1196 void MarbleMap::setShowPlaces( bool visible )
1197 {
1198     setPropertyValue(QStringLiteral("places"), visible);
1199 }
1200 
setShowCities(bool visible)1201 void MarbleMap::setShowCities( bool visible )
1202 {
1203     setPropertyValue(QStringLiteral("cities"), visible);
1204 }
1205 
setShowTerrain(bool visible)1206 void MarbleMap::setShowTerrain( bool visible )
1207 {
1208     setPropertyValue(QStringLiteral("terrain"), visible);
1209 }
1210 
setShowOtherPlaces(bool visible)1211 void MarbleMap::setShowOtherPlaces( bool visible )
1212 {
1213     setPropertyValue(QStringLiteral("otherplaces"), visible);
1214 }
1215 
setShowRelief(bool visible)1216 void MarbleMap::setShowRelief( bool visible )
1217 {
1218     setPropertyValue(QStringLiteral("relief"), visible);
1219 }
1220 
setShowIceLayer(bool visible)1221 void MarbleMap::setShowIceLayer( bool visible )
1222 {
1223     setPropertyValue(QStringLiteral("ice"), visible);
1224 }
1225 
setShowBorders(bool visible)1226 void MarbleMap::setShowBorders( bool visible )
1227 {
1228     setPropertyValue(QStringLiteral("borders"), visible);
1229 }
1230 
setShowRivers(bool visible)1231 void MarbleMap::setShowRivers( bool visible )
1232 {
1233     setPropertyValue(QStringLiteral("rivers"), visible);
1234 }
1235 
setShowLakes(bool visible)1236 void MarbleMap::setShowLakes( bool visible )
1237 {
1238     setPropertyValue(QStringLiteral("lakes"), visible);
1239 }
1240 
setShowFrameRate(bool visible)1241 void MarbleMap::setShowFrameRate( bool visible )
1242 {
1243     d->m_showFrameRate = visible;
1244 }
1245 
setShowRuntimeTrace(bool visible)1246 void MarbleMap::setShowRuntimeTrace( bool visible )
1247 {
1248     if (visible != d->m_layerManager.showRuntimeTrace()) {
1249         d->m_layerManager.setShowRuntimeTrace(visible);
1250         emit repaintNeeded();
1251     }
1252 }
1253 
showRuntimeTrace() const1254 bool MarbleMap::showRuntimeTrace() const
1255 {
1256     return d->m_layerManager.showRuntimeTrace();
1257 }
1258 
setShowDebugPolygons(bool visible)1259 void MarbleMap::setShowDebugPolygons( bool visible)
1260 {
1261     if (visible != d->m_showDebugPolygons) {
1262         d->m_showDebugPolygons = visible;
1263         emit repaintNeeded();
1264     }
1265 }
1266 
showDebugPolygons() const1267 bool MarbleMap::showDebugPolygons() const
1268 {
1269     return d->m_showDebugPolygons;
1270 }
1271 
setShowDebugBatchRender(bool visible)1272 void MarbleMap::setShowDebugBatchRender( bool visible)
1273 {
1274     qDebug() << Q_FUNC_INFO << visible;
1275     if (visible != d->m_showDebugBatchRender) {
1276         d->m_showDebugBatchRender = visible;
1277         emit repaintNeeded();
1278     }
1279 }
1280 
showDebugBatchRender() const1281 bool MarbleMap::showDebugBatchRender() const
1282 {
1283     return d->m_showDebugBatchRender;
1284 }
1285 
setShowDebugPlacemarks(bool visible)1286 void MarbleMap::setShowDebugPlacemarks( bool visible)
1287 {
1288     if (visible != d->m_placemarkLayer.isDebugModeEnabled()) {
1289         d->m_placemarkLayer.setDebugModeEnabled(visible);
1290         emit repaintNeeded();
1291     }
1292 }
1293 
showDebugPlacemarks() const1294 bool MarbleMap::showDebugPlacemarks() const
1295 {
1296     return d->m_placemarkLayer.isDebugModeEnabled();
1297 }
1298 
setLevelTagDebugModeEnabled(bool visible)1299 void MarbleMap::setLevelTagDebugModeEnabled(bool visible)
1300 {
1301     if (visible != d->m_geometryLayer.levelTagDebugModeEnabled()) {
1302         d->m_geometryLayer.setLevelTagDebugModeEnabled(visible);
1303         d->m_placemarkLayer.setLevelTagDebugModeEnabled(visible);
1304         emit repaintNeeded();
1305     }
1306 }
1307 
levelTagDebugModeEnabled() const1308 bool MarbleMap::levelTagDebugModeEnabled() const
1309 {
1310     return d->m_geometryLayer.levelTagDebugModeEnabled() &&
1311            d->m_placemarkLayer.levelTagDebugModeEnabled();
1312 }
1313 
setDebugLevelTag(int level)1314 void MarbleMap::setDebugLevelTag(int level)
1315 {
1316     d->m_geometryLayer.setDebugLevelTag(level);
1317     d->m_placemarkLayer.setDebugLevelTag(level);
1318 }
1319 
debugLevelTag() const1320 int MarbleMap::debugLevelTag() const
1321 {
1322     return d->m_geometryLayer.debugLevelTag();
1323 }
1324 
setShowBackground(bool visible)1325 void MarbleMap::setShowBackground( bool visible )
1326 {
1327     d->m_layerManager.setShowBackground( visible );
1328 }
1329 
setVisibleRelationTypes(GeoDataRelation::RelationTypes relationTypes)1330 void MarbleMap::setVisibleRelationTypes(GeoDataRelation::RelationTypes relationTypes)
1331 {
1332     if (d->m_visibleRelationTypes != relationTypes) {
1333         d->m_visibleRelationTypes = relationTypes;
1334         d->m_geometryLayer.setVisibleRelationTypes(relationTypes);
1335         emit visibleRelationTypesChanged(d->m_visibleRelationTypes);
1336     }
1337 }
1338 
notifyMouseClick(int x,int y)1339 void MarbleMap::notifyMouseClick( int x, int y )
1340 {
1341     qreal  lon   = 0;
1342     qreal  lat   = 0;
1343 
1344     const bool valid = geoCoordinates( x, y, lon, lat, GeoDataCoordinates::Radian );
1345 
1346     if ( valid ) {
1347         emit mouseClickGeoPosition( lon, lat, GeoDataCoordinates::Radian );
1348     }
1349 }
1350 
clearVolatileTileCache()1351 void MarbleMap::clearVolatileTileCache()
1352 {
1353     d->m_vectorTileLayer.reset();
1354     d->m_textureLayer.reset();
1355     mDebug() << "Cleared Volatile Cache!";
1356 }
1357 
setVolatileTileCacheLimit(quint64 kilobytes)1358 void MarbleMap::setVolatileTileCacheLimit( quint64 kilobytes )
1359 {
1360     mDebug() << "kiloBytes" << kilobytes;
1361     d->m_textureLayer.setVolatileCacheLimit( kilobytes );
1362 }
1363 
defaultAngleUnit() const1364 AngleUnit MarbleMap::defaultAngleUnit() const
1365 {
1366     if ( GeoDataCoordinates::defaultNotation() == GeoDataCoordinates::Decimal ) {
1367         return DecimalDegree;
1368     } else if ( GeoDataCoordinates::defaultNotation() == GeoDataCoordinates::UTM ) {
1369     	return UTM;
1370     }
1371 
1372     return DMSDegree;
1373 }
1374 
setDefaultAngleUnit(AngleUnit angleUnit)1375 void MarbleMap::setDefaultAngleUnit( AngleUnit angleUnit )
1376 {
1377     if ( angleUnit == DecimalDegree ) {
1378         GeoDataCoordinates::setDefaultNotation( GeoDataCoordinates::Decimal );
1379         return;
1380     } else if ( angleUnit == UTM ) {
1381         GeoDataCoordinates::setDefaultNotation( GeoDataCoordinates::UTM );
1382         return;
1383     }
1384 
1385     GeoDataCoordinates::setDefaultNotation( GeoDataCoordinates::DMS );
1386 }
1387 
defaultFont() const1388 QFont MarbleMap::defaultFont() const
1389 {
1390     return d->m_styleBuilder.defaultFont();
1391 }
1392 
setDefaultFont(const QFont & font)1393 void MarbleMap::setDefaultFont( const QFont& font )
1394 {
1395     d->m_styleBuilder.setDefaultFont(font);
1396     d->m_placemarkLayer.requestStyleReset();
1397 }
1398 
renderPlugins() const1399 QList<RenderPlugin *> MarbleMap::renderPlugins() const
1400 {
1401     return d->m_renderPlugins;
1402 }
1403 
floatItems() const1404 QList<AbstractFloatItem *> MarbleMap::floatItems() const
1405 {
1406     return d->m_floatItemsLayer.floatItems();
1407 }
1408 
floatItem(const QString & nameId) const1409 AbstractFloatItem * MarbleMap::floatItem( const QString &nameId ) const
1410 {
1411     for ( AbstractFloatItem * floatItem: floatItems() ) {
1412         if ( floatItem && floatItem->nameId() == nameId ) {
1413             return floatItem;
1414         }
1415     }
1416 
1417     return nullptr; // No item found
1418 }
1419 
dataPlugins() const1420 QList<AbstractDataPlugin *> MarbleMap::dataPlugins()  const
1421 {
1422     return d->m_layerManager.dataPlugins();
1423 }
1424 
whichItemAt(const QPoint & curpos) const1425 QList<AbstractDataPluginItem *> MarbleMap::whichItemAt( const QPoint& curpos ) const
1426 {
1427     return d->m_layerManager.whichItemAt( curpos );
1428 }
1429 
addLayer(LayerInterface * layer)1430 void MarbleMap::addLayer( LayerInterface *layer )
1431 {
1432     d->m_layerManager.addLayer(layer);
1433 }
1434 
removeLayer(LayerInterface * layer)1435 void MarbleMap::removeLayer( LayerInterface *layer )
1436 {
1437     d->m_layerManager.removeLayer(layer);
1438 }
1439 
renderStatus() const1440 RenderStatus MarbleMap::renderStatus() const
1441 {
1442     return d->m_layerManager.renderState().status();
1443 }
1444 
renderState() const1445 RenderState MarbleMap::renderState() const
1446 {
1447     return d->m_layerManager.renderState();
1448 }
1449 
addTextureLayer(GeoSceneTextureTileDataset * texture)1450 QString MarbleMap::addTextureLayer(GeoSceneTextureTileDataset *texture)
1451 {
1452     return textureLayer()->addTextureLayer(texture);
1453 }
1454 
removeTextureLayer(const QString & key)1455 void  MarbleMap::removeTextureLayer(const QString &key)
1456 {
1457     textureLayer()->removeTextureLayer(key);
1458 }
1459 
1460 // this method will only temporarily "pollute" the MarbleModel class
textureLayer() const1461 TextureLayer *MarbleMap::textureLayer() const
1462 {
1463     return &d->m_textureLayer;
1464 }
1465 
styleBuilder() const1466 const StyleBuilder* MarbleMap::styleBuilder() const
1467 {
1468     return &d->m_styleBuilder;
1469 }
1470 
heading() const1471 qreal MarbleMap::heading() const
1472 {
1473     return d->m_viewport.heading() * RAD2DEG;
1474 }
1475 
setHeading(qreal heading)1476 void MarbleMap::setHeading( qreal heading )
1477 {
1478     d->m_viewport.setHeading( heading * DEG2RAD );
1479     d->m_textureLayer.setNeedsUpdate();
1480 
1481     emit visibleLatLonAltBoxChanged( d->m_viewport.viewLatLonAltBox() );
1482 }
1483 
1484 }
1485 
1486 #include "moc_MarbleMap.cpp"
1487