1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2014 Adam Dabrowski <adabrowski@piap.pl> <adamdbrw@gmail.com>
4 //
5 
6 
7 #include <MarbleQuickItem.h>
8 #include <QPainter>
9 #include <QPaintDevice>
10 #include <QtMath>
11 #include <QQmlContext>
12 #include <QSettings>
13 
14 #include <MarbleModel.h>
15 #include <MarbleMap.h>
16 #include <ViewportParams.h>
17 #include <GeoPainter.h>
18 #include <GeoDataLookAt.h>
19 #include <Planet.h>
20 #include <MarbleAbstractPresenter.h>
21 #include <AbstractFloatItem.h>
22 #include <MarbleInputHandler.h>
23 #include <PositionTracking.h>
24 #include <PositionProviderPlugin.h>
25 #include <PluginManager.h>
26 #include <RenderPlugin.h>
27 #include <MarbleMath.h>
28 #include <GeoDataLatLonAltBox.h>
29 #include <GeoDataCoordinates.h>
30 #include <ReverseGeocodingRunnerManager.h>
31 #include <routing/RoutingManager.h>
32 #include <routing/RoutingModel.h>
33 #include <routing/Route.h>
34 #include <BookmarkManager.h>
35 #include "GeoDataRelation.h"
36 #include "osm/OsmPlacemarkData.h"
37 #include "GeoDataDocument.h"
38 
39 namespace Marble
40 {
41     //TODO - move to separate files
42     class QuickItemSelectionRubber : public AbstractSelectionRubber
43     { //TODO: support rubber selection in MarbleQuickItem
44     public:
45         QuickItemSelectionRubber();
show()46         void show() override { m_visible = true; }
hide()47         void hide() override { m_visible = false; }
isVisible() const48         bool isVisible() const override { return m_visible; }
geometry() const49         const QRect &geometry() const override { return m_geometry; }
setGeometry(const QRect &)50         void setGeometry(const QRect &/*geometry*/) override {}
51     private:
52         QRect m_geometry;
53         bool m_visible;
54     };
55 
56     //TODO - implement missing functionalities
57     class MarbleQuickInputHandler : public MarbleDefaultInputHandler
58     {
59     public:
MarbleQuickInputHandler(MarbleAbstractPresenter * marblePresenter,MarbleQuickItem * marbleQuick)60         MarbleQuickInputHandler(MarbleAbstractPresenter *marblePresenter, MarbleQuickItem *marbleQuick)
61             : MarbleDefaultInputHandler(marblePresenter)
62             ,m_marbleQuick(marbleQuick)
63         {
64             setInertialEarthRotationEnabled(false); //Disabled by default, it's buggy. TODO - fix
65         }
66 
acceptMouse()67         bool acceptMouse() override
68         {
69             return true;
70         }
71 
pinch(QPointF center,qreal scale,Qt::GestureState state)72         void pinch(QPointF center, qreal scale, Qt::GestureState state)
73         {   //TODO - this whole thing should be moved to MarbleAbstractPresenter
74             (void)handlePinch(center, scale, state);
75         }
76 
handleMouseButtonPressAndHold(const QPoint & position)77         void handleMouseButtonPressAndHold(const QPoint &position) override
78         {
79             m_marbleQuick->reverseGeocoding(position);
80         }
81 
82     private Q_SLOTS:
showLmbMenu(int x,int y)83         void showLmbMenu(int x, int y) override
84         {
85             m_marbleQuick->selectPlacemarkAt(x, y);
86             emit m_marbleQuick->lmbMenuRequested(QPoint(x,y));
87         }
88 
showRmbMenu(int x,int y)89         void showRmbMenu(int x, int y) override {
90             emit m_marbleQuick->rmbMenuRequested(QPoint(x,y));
91         }
openItemToolTip()92         void openItemToolTip() override {}
setCursor(const QCursor & cursor)93         void setCursor(const QCursor &cursor) override
94         {
95             m_marbleQuick->setCursor(cursor);
96         }
97 
98     private Q_SLOTS:
installPluginEventFilter(RenderPlugin *)99         void installPluginEventFilter(RenderPlugin *) override {}
100 
101     private:
layersEventFilter(QObject * o,QEvent * e)102         bool layersEventFilter(QObject *o, QEvent *e) override
103         {
104             return m_marbleQuick->layersEventFilter(o, e);
105         }
106 
107         //empty - don't check. It would be invalid with quick items
checkReleasedMove(QMouseEvent *)108         void checkReleasedMove(QMouseEvent *) override {}
109 
handleTouch(QTouchEvent * event)110         bool handleTouch(QTouchEvent *event) override
111         {
112             if (event->touchPoints().count() > 1)
113             {   //not handling multi-touch at all, let PinchArea or MultiPointTouchArea take care of it
114                 return false;
115             }
116 
117             if (event->touchPoints().count() == 1)
118             {   //handle - but do not accept. I.e. pinchArea still needs to get this
119                 QTouchEvent::TouchPoint p = event->touchPoints().at(0);
120                 if (event->type() == QEvent::TouchBegin)
121                 {
122                     QMouseEvent press(QMouseEvent::MouseButtonPress, p.pos(),
123                                       Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
124                     handleMouseEvent(&press);
125                 }
126                 else if (event->type() == QEvent::TouchUpdate)
127                 {
128                     QMouseEvent move(QMouseEvent::MouseMove, p.pos(),
129                                       Qt::NoButton, Qt::LeftButton, Qt::NoModifier);
130                     handleMouseEvent(&move);
131                 }
132                 else if (event->type() == QEvent::TouchEnd)
133                 {
134                     QMouseEvent release(QMouseEvent::MouseButtonRelease, p.pos(),
135                                       Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
136                     handleMouseEvent(&release);
137                 }
138             }
139             return false;
140         }
141 
selectionRubber()142         AbstractSelectionRubber *selectionRubber() override
143         {
144             return &m_selectionRubber;
145         }
146 
147         MarbleQuickItem *m_marbleQuick;
148         QuickItemSelectionRubber m_selectionRubber;
149         bool m_usePinchArea;
150     };
151 
152     class MarbleQuickItemPrivate
153     {
154     public:
MarbleQuickItemPrivate(MarbleQuickItem * marble)155         explicit MarbleQuickItemPrivate(MarbleQuickItem *marble) :
156             m_marble(marble),
157             m_model(),
158             m_map(&m_model),
159             m_presenter(&m_map),
160             m_positionVisible(false),
161             m_currentPosition(marble),
162             m_inputHandler(&m_presenter, marble),
163             m_placemarkDelegate(nullptr),
164             m_placemarkItem(nullptr),
165             m_placemark(nullptr),
166             m_reverseGeocoding(&m_model),
167             m_showScaleBar(false),
168             m_enabledRelationTypes(GeoDataRelation::RouteFerry |
169                             GeoDataRelation::RouteTrain |
170                             GeoDataRelation::RouteSubway |
171                             GeoDataRelation::RouteTram |
172                             GeoDataRelation::RouteBus |
173                             GeoDataRelation::RouteTrolleyBus |
174                             GeoDataRelation::RouteHiking),
175             m_showPublicTransport(false),
176             m_showOutdoorActivities(false),
177             m_heading(0.0),
178             m_hoverEnabled(false)
179         {
180             m_currentPosition.setName(QObject::tr("Current Location"));
181             m_relationTypeConverter["road"] = GeoDataRelation::RouteRoad;
182             m_relationTypeConverter["detour"] = GeoDataRelation::RouteDetour;
183             m_relationTypeConverter["ferry"] = GeoDataRelation::RouteFerry;
184             m_relationTypeConverter["train"] = GeoDataRelation::RouteTrain;
185             m_relationTypeConverter["subway"] = GeoDataRelation::RouteSubway;
186             m_relationTypeConverter["tram"] = GeoDataRelation::RouteTram;
187             m_relationTypeConverter["bus"] = GeoDataRelation::RouteBus;
188             m_relationTypeConverter["trolley-bus"] = GeoDataRelation::RouteTrolleyBus;
189             m_relationTypeConverter["bicycle"] = GeoDataRelation::RouteBicycle;
190             m_relationTypeConverter["mountainbike"] = GeoDataRelation::RouteMountainbike;
191             m_relationTypeConverter["foot"] = GeoDataRelation::RouteFoot;
192             m_relationTypeConverter["hiking"] = GeoDataRelation::RouteHiking;
193             m_relationTypeConverter["horse"] = GeoDataRelation::RouteHorse;
194             m_relationTypeConverter["inline-skates"] = GeoDataRelation::RouteInlineSkates;
195             m_relationTypeConverter["downhill"] = GeoDataRelation::RouteSkiDownhill;
196             m_relationTypeConverter["ski-nordic"] = GeoDataRelation::RouteSkiNordic;
197             m_relationTypeConverter["skitour"] = GeoDataRelation::RouteSkitour;
198             m_relationTypeConverter["sled"] = GeoDataRelation::RouteSled;
199         }
200 
201         void updateVisibleRoutes();
202 
203     private:
204         MarbleQuickItem *m_marble;
205         friend class MarbleQuickItem;
206         MarbleModel m_model;
207         MarbleMap m_map;
208         MarbleAbstractPresenter m_presenter;
209         bool m_positionVisible;
210         Placemark m_currentPosition;
211 
212         MarbleQuickInputHandler m_inputHandler;
213         QQmlComponent* m_placemarkDelegate;
214         QQuickItem* m_placemarkItem;
215         Placemark* m_placemark;
216         ReverseGeocodingRunnerManager m_reverseGeocoding;
217 
218         bool m_showScaleBar;
219         QMap<QString, GeoDataRelation::RelationType> m_relationTypeConverter;
220         GeoDataRelation::RelationTypes m_enabledRelationTypes;
221         bool m_showPublicTransport;
222         bool m_showOutdoorActivities;
223         qreal m_heading;
224         bool m_hoverEnabled;
225     };
226 
MarbleQuickItem(QQuickItem * parent)227     MarbleQuickItem::MarbleQuickItem(QQuickItem *parent) : QQuickPaintedItem(parent)
228       ,d(new MarbleQuickItemPrivate(this))
229     {
230         setRenderTarget(QQuickPaintedItem::FramebufferObject);
231         setOpaquePainting(true);
232         qRegisterMetaType<Placemark*>("Placemark*");
233         d->m_map.setMapQualityForViewContext(NormalQuality, Animation);
234 
235         for (AbstractFloatItem *item: d->m_map.floatItems()) {
236             if (item->nameId() == QLatin1String("license")) {
237                 item->setPosition(QPointF(5.0, -10.0));
238             } else {
239                 item->hide();
240             }
241         }
242 
243         d->m_model.positionTracking()->setTrackVisible(false);
244 
245         connect(&d->m_map, SIGNAL(repaintNeeded(QRegion)), this, SLOT(update()));
246         connect(this, &MarbleQuickItem::widthChanged, this, &MarbleQuickItem::resizeMap);
247         connect(this, &MarbleQuickItem::heightChanged, this, &MarbleQuickItem::resizeMap);
248         connect(&d->m_map, &MarbleMap::visibleLatLonAltBoxChanged, this, &MarbleQuickItem::updatePositionVisibility);
249         connect(&d->m_map, &MarbleMap::visibleLatLonAltBoxChanged, this, &MarbleQuickItem::visibleLatLonAltBoxChanged);
250         connect(&d->m_map, &MarbleMap::radiusChanged, this, &MarbleQuickItem::radiusChanged);
251         connect(&d->m_map, &MarbleMap::radiusChanged, this, &MarbleQuickItem::zoomChanged);
252         connect(&d->m_reverseGeocoding, SIGNAL(reverseGeocodingFinished(GeoDataCoordinates,GeoDataPlacemark)),
253                 this, SLOT(handleReverseGeocoding(GeoDataCoordinates,GeoDataPlacemark)));
254         connect(&d->m_map, &MarbleMap::visibleLatLonAltBoxChanged, this, &MarbleQuickItem::handleVisibleLatLonAltBoxChanged);
255 
256         setAcceptedMouseButtons(Qt::AllButtons);
257         installEventFilter(&d->m_inputHandler);
258     }
259 
resizeMap()260     void MarbleQuickItem::resizeMap()
261     {
262         d->m_map.setSize(qMax(100, int(width())), qMax(100, int(height())));
263         update();
264         updatePositionVisibility();
265     }
266 
positionDataStatusChanged(PositionProviderStatus status)267     void MarbleQuickItem::positionDataStatusChanged(PositionProviderStatus status)
268     {
269         bool const positionAvailable = status == PositionProviderStatusAvailable;
270         emit positionAvailableChanged(positionAvailable);
271         updatePositionVisibility();
272     }
273 
positionChanged(const GeoDataCoordinates &,GeoDataAccuracy)274     void MarbleQuickItem::positionChanged(const GeoDataCoordinates &, GeoDataAccuracy)
275     {
276        updatePositionVisibility();
277     }
278 
updatePositionVisibility()279     void MarbleQuickItem::updatePositionVisibility()
280     {
281         updatePlacemarks();
282         bool isVisible = false;
283         if ( positionAvailable() ) {
284             qreal x, y;
285             bool globeHidesPoint;
286             bool const valid = d->m_map.viewport()->screenCoordinates(d->m_model.positionTracking()->currentLocation(), x, y, globeHidesPoint);
287             isVisible = valid && !globeHidesPoint;
288         }
289 
290         if ( isVisible != d->m_positionVisible ) {
291             d->m_positionVisible = isVisible;
292             emit positionVisibleChanged( isVisible );
293         }
294     }
295 
updateCurrentPosition(const GeoDataCoordinates & coordinates)296     void MarbleQuickItem::updateCurrentPosition(const GeoDataCoordinates &coordinates)
297     {
298         d->m_currentPosition.placemark().setCoordinate(coordinates);
299         emit currentPositionChanged(&d->m_currentPosition);
300     }
301 
updatePlacemarks()302     void MarbleQuickItem::updatePlacemarks()
303     {
304         if (!d->m_placemarkDelegate || !d->m_placemark) {
305             return;
306         }
307 
308         if (!d->m_placemarkItem) {
309             QQmlContext * context = new QQmlContext(qmlContext(d->m_placemarkDelegate));
310             QObject * component = d->m_placemarkDelegate->create(context);
311             d->m_placemarkItem = qobject_cast<QQuickItem*>( component );
312             if (d->m_placemarkItem) {
313                 d->m_placemarkItem->setParentItem( this );
314                 d->m_placemarkItem->setProperty("placemark", QVariant::fromValue(d->m_placemark));
315             } else {
316                 delete component;
317                 return;
318             }
319         }
320 
321         qreal x = 0;
322         qreal y = 0;
323         const bool visible = d->m_map.viewport()->screenCoordinates(d->m_placemark->placemark().coordinate(), x, y);
324         d->m_placemarkItem->setVisible(visible);
325         if (visible) {
326             d->m_placemarkItem->setProperty("xPos", QVariant(x));
327             d->m_placemarkItem->setProperty("yPos", QVariant(y));
328         }
329     }
330 
handleReverseGeocoding(const GeoDataCoordinates & coordinates,const GeoDataPlacemark & placemark)331     void MarbleQuickItem::handleReverseGeocoding(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark)
332     {
333         if (d->m_placemark && d->m_placemark->placemark().coordinate() == coordinates) {
334             d->m_placemark->setGeoDataPlacemark(placemark);
335             updatePlacemarks();
336         }
337     }
338 
handleVisibleLatLonAltBoxChanged(const GeoDataLatLonAltBox & latLonAltBox)339     void MarbleQuickItem::handleVisibleLatLonAltBoxChanged(const GeoDataLatLonAltBox &latLonAltBox)
340     {
341         Q_UNUSED(latLonAltBox)
342 
343         if (d->m_heading != d->m_map.heading()) {
344             d->m_heading = d->m_map.heading();
345             emit headingChanged(d->m_heading);
346         }
347     }
348 
paint(QPainter * painter)349     void MarbleQuickItem::paint(QPainter *painter)
350     {   //TODO - much to be done here still, i.e paint !enabled version
351         QPaintDevice *paintDevice = painter->device();
352         QRect rect = contentsBoundingRect().toRect();
353 
354         painter->end();
355         {
356             GeoPainter geoPainter(paintDevice, d->m_map.viewport(), d->m_map.mapQuality());
357             d->m_map.paint(geoPainter, rect);
358         }
359         painter->begin(paintDevice);
360     }
361 
classBegin()362     void MarbleQuickItem::classBegin()
363     {
364     }
365 
componentComplete()366     void MarbleQuickItem::componentComplete()
367     {
368     }
369 
hoverMoveEvent(QHoverEvent * event)370     void Marble::MarbleQuickItem::MarbleQuickItem::hoverMoveEvent(QHoverEvent *event) {
371         if (d->m_hoverEnabled) {
372             emit hoverPositionChanged(event->pos());
373         }
374         QQuickItem::hoverMoveEvent(event);
375     }
376 
mapWidth() const377     int MarbleQuickItem::mapWidth() const
378     {
379         return d->m_map.width();
380     }
381 
mapHeight() const382     int MarbleQuickItem::mapHeight() const
383     {
384         return d->m_map.height();
385     }
386 
showFrameRate() const387     bool MarbleQuickItem::showFrameRate() const
388     {
389         return d->m_map.showFrameRate();
390     }
391 
projection() const392     MarbleQuickItem::Projection MarbleQuickItem::projection() const
393     {
394         return Projection(d->m_map.projection());
395     }
396 
mapThemeId() const397     QString MarbleQuickItem::mapThemeId() const
398     {
399         return d->m_map.mapThemeId();
400     }
401 
showAtmosphere() const402     bool MarbleQuickItem::showAtmosphere() const
403     {
404         return d->m_map.showAtmosphere();
405     }
406 
showCompass() const407     bool MarbleQuickItem::showCompass() const
408     {
409         return d->m_map.showCompass();
410     }
411 
showClouds() const412     bool MarbleQuickItem::showClouds() const
413     {
414         return d->m_map.showClouds();
415     }
416 
showCrosshairs() const417     bool MarbleQuickItem::showCrosshairs() const
418     {
419         return d->m_map.showCrosshairs();
420     }
421 
showGrid() const422     bool MarbleQuickItem::showGrid() const
423     {
424         return d->m_map.showGrid();
425     }
426 
showOverviewMap() const427     bool MarbleQuickItem::showOverviewMap() const
428     {
429         return d->m_map.showOverviewMap();
430     }
431 
showOtherPlaces() const432     bool MarbleQuickItem::showOtherPlaces() const
433     {
434         return d->m_map.showOtherPlaces();
435     }
436 
showScaleBar() const437     bool MarbleQuickItem::showScaleBar() const
438     {
439         return d->m_showScaleBar;
440     }
441 
showBackground() const442     bool MarbleQuickItem::showBackground() const
443     {
444         return d->m_map.showBackground();
445     }
446 
showPositionMarker() const447     bool MarbleQuickItem::showPositionMarker() const
448     {
449         QList<RenderPlugin *> plugins = d->m_map.renderPlugins();
450         for (const RenderPlugin * plugin: plugins) {
451             if (plugin->nameId() == QLatin1String("positionMarker")) {
452                 return plugin->visible();
453             }
454         }
455         return false;
456     }
457 
showPublicTransport() const458     bool MarbleQuickItem::showPublicTransport() const
459     {
460         return d->m_showPublicTransport;
461     }
462 
showOutdoorActivities() const463     bool MarbleQuickItem::showOutdoorActivities() const
464     {
465         return d->m_showOutdoorActivities;
466     }
467 
positionProvider() const468     QString MarbleQuickItem::positionProvider() const
469     {
470         if ( d->m_model.positionTracking()->positionProviderPlugin() ) {
471             return d->m_model.positionTracking()->positionProviderPlugin()->nameId();
472         }
473 
474         return QString();
475     }
476 
model()477     MarbleModel* MarbleQuickItem::model()
478     {
479         return &d->m_model;
480     }
481 
model() const482     const MarbleModel* MarbleQuickItem::model() const
483     {
484         return &d->m_model;
485     }
486 
map()487     MarbleMap* MarbleQuickItem::map()
488     {
489         return &d->m_map;
490     }
491 
map() const492     const MarbleMap* MarbleQuickItem::map() const
493     {
494         return &d->m_map;
495     }
496 
inertialGlobeRotation() const497     bool MarbleQuickItem::inertialGlobeRotation() const
498     {
499         return d->m_inputHandler.inertialEarthRotationEnabled();
500     }
501 
animationViewContext() const502     bool MarbleQuickItem::animationViewContext() const
503     {
504         return d->m_map.viewContext() == Animation;
505     }
506 
animationsEnabled() const507     bool MarbleQuickItem::animationsEnabled() const
508     {
509         return d->m_presenter.animationsEnabled();
510     }
511 
placemarkDelegate() const512     QQmlComponent *MarbleQuickItem::placemarkDelegate() const
513     {
514         return d->m_placemarkDelegate;
515     }
516 
reverseGeocoding(const QPoint & point)517     void MarbleQuickItem::reverseGeocoding(const QPoint &point)
518     {
519         qreal lon, lat;
520         d->m_map.viewport()->geoCoordinates(point.x(), point.y(), lon, lat);
521         auto const coordinates = GeoDataCoordinates(lon, lat, 0.0, GeoDataCoordinates::Degree);
522         delete d->m_placemarkItem;
523         d->m_placemarkItem = nullptr;
524         delete d->m_placemark;
525         d->m_placemark = new Placemark(this);
526         d->m_placemark->placemark().setCoordinate(coordinates);
527         d->m_reverseGeocoding.reverseGeocoding(coordinates);
528     }
529 
hoverEnabled() const530     bool MarbleQuickItem::hoverEnabled() const
531     {
532         return d->m_hoverEnabled;
533     }
534 
moveUp()535     void MarbleQuickItem::moveUp()
536     {
537         d->m_presenter.moveByStep( 0, -1, Marble::Automatic );
538     }
539 
moveDown()540     void MarbleQuickItem::moveDown()
541     {
542         d->m_presenter.moveByStep( 0, 1, Marble::Automatic );
543     }
544 
moveLeft()545     void MarbleQuickItem::moveLeft()
546     {
547         d->m_presenter.moveByStep( -1, 0, Marble::Automatic );
548     }
549 
moveRight()550     void MarbleQuickItem::moveRight()
551     {
552         d->m_presenter.moveByStep( 1, 0, Marble::Automatic );
553     }
554 
speed() const555     qreal MarbleQuickItem::speed() const
556     {
557         return d->m_model.positionTracking()->speed();
558     }
559 
angle() const560     qreal MarbleQuickItem::angle() const
561     {
562         bool routeExists = d->m_model.routingManager()->routingModel()->route().distance() != 0.0;
563         bool onRoute = !d->m_model.routingManager()->routingModel()->deviatedFromRoute();
564         if ( routeExists && onRoute) {
565             GeoDataCoordinates curPoint = d->m_model.positionTracking()->positionProviderPlugin()->position();
566             return d->m_model.routingManager()->routingModel()->route().currentSegment().projectedDirection(curPoint);
567         } else {
568             return d->m_model.positionTracking()->direction();
569         }
570     }
571 
positionAvailable() const572     bool MarbleQuickItem::positionAvailable() const
573     {
574         return d->m_model.positionTracking()->status() == PositionProviderStatusAvailable;
575     }
576 
positionVisible() const577     bool MarbleQuickItem::positionVisible() const
578     {
579         return d->m_positionVisible;
580     }
581 
distanceFromPointToCurrentLocation(const QPoint & position) const582     qreal MarbleQuickItem::distanceFromPointToCurrentLocation(const QPoint & position) const
583     {
584         if ( positionAvailable() ) {
585             qreal lon1;
586             qreal lat1;
587             d->m_map.viewport()->geoCoordinates(position.x(), position.y(), lon1, lat1, GeoDataCoordinates::Radian );
588 
589             GeoDataCoordinates currentCoordinates = d->m_model.positionTracking()->currentLocation();
590             qreal lon2 = currentCoordinates.longitude();
591             qreal lat2 = currentCoordinates.latitude();
592 
593             return distanceSphere(lon1, lat1, lon2, lat2) * d->m_model.planetRadius();
594         }
595         return 0;
596     }
597 
angleFromPointToCurrentLocation(const QPoint & position) const598     qreal MarbleQuickItem::angleFromPointToCurrentLocation( const QPoint & position ) const
599     {
600         if ( positionAvailable() ) {
601             qreal x, y;
602             PositionTracking const * positionTracking = d->m_model.positionTracking();
603             map()->viewport()->screenCoordinates( positionTracking->currentLocation(), x, y );
604             return atan2( y-position.y(), x-position.x() ) * RAD2DEG;
605         }
606         return 0;
607     }
608 
currentPosition() const609     Placemark * MarbleQuickItem::currentPosition() const
610     {
611         return &d->m_currentPosition;
612     }
613 
screenCoordinatesFromCoordinate(Coordinate * coordinate) const614     QPointF MarbleQuickItem::screenCoordinatesFromCoordinate(Coordinate * coordinate) const
615     {
616         qreal x, y;
617         bool globeHidesPoint;
618         bool const valid = d->m_map.viewport()->screenCoordinates(coordinate->coordinates(), x, y, globeHidesPoint);
619         bool isVisible = valid && !globeHidesPoint;
620         return isVisible ? QPointF(x, y) : QPointF();
621     }
622 
screenCoordinatesFromGeoDataCoordinates(const GeoDataCoordinates & coordinates) const623     QPointF MarbleQuickItem::screenCoordinatesFromGeoDataCoordinates(const GeoDataCoordinates & coordinates) const
624     {
625         qreal x, y;
626         bool globeHidesPoint;
627         d->m_map.viewport()->screenCoordinates(coordinates, x, y, globeHidesPoint);
628         return !globeHidesPoint ? QPointF(x, y) : QPointF();
629     }
630 
screenCoordinatesFromGeoDataLineString(const GeoDataLineString & lineString,QVector<QPolygonF * > & polygons) const631     bool MarbleQuickItem::screenCoordinatesFromGeoDataLineString(const GeoDataLineString &lineString, QVector<QPolygonF *> &polygons) const
632     {
633         return d->m_map.viewport()->screenCoordinates(lineString, polygons);
634     }
635 
screenCoordinatesToCoordinate(const QPoint & point,Coordinate * coordinate)636     bool MarbleQuickItem::screenCoordinatesToCoordinate(const QPoint & point, Coordinate * coordinate)
637     {
638         GeoDataCoordinates geoDataCoordinates;
639         bool success = screenCoordinatesToGeoDataCoordinates(point, geoDataCoordinates);
640         if (!qobject_cast<Coordinate*>(coordinate)){
641             Coordinate * tmp(coordinate);
642             coordinate = new Coordinate(geoDataCoordinates.longitude(), geoDataCoordinates.latitude(), 0, nullptr);
643             QQmlEngine::setObjectOwnership(coordinate, QQmlEngine::JavaScriptOwnership);
644             delete tmp;
645         }
646         else {
647             coordinate->setLongitude(geoDataCoordinates.longitude());
648             coordinate->setLatitude(geoDataCoordinates.latitude());
649         }
650 
651         return success;
652     }
653 
screenCoordinatesToGeoDataCoordinates(const QPoint & point,GeoDataCoordinates & coordinates)654     bool MarbleQuickItem::screenCoordinatesToGeoDataCoordinates(const QPoint & point, GeoDataCoordinates & coordinates)
655     {
656         qreal lon = 0.0 , lat = 0.0;
657         bool const valid = d->m_map.viewport()->geoCoordinates(point.x(), point.y(), lon, lat);
658         coordinates.setLongitude(lon);
659         coordinates.setLatitude(lat);
660         return valid;
661     }
662 
setRadius(int radius)663     void MarbleQuickItem::setRadius(int radius)
664     {
665         d->m_map.setRadius(radius);
666     }
667 
setHeading(qreal heading)668     void MarbleQuickItem::setHeading(qreal heading)
669     {
670         if (qFuzzyCompare(d->m_heading, heading))
671             return;
672 
673         d->m_map.setHeading(heading);
674         d->m_heading = heading;
675 
676         emit headingChanged(d->m_heading);
677     }
678 
setHoverEnabled(bool hoverEnabled)679     void MarbleQuickItem::setHoverEnabled(bool hoverEnabled)
680     {
681         if (d->m_hoverEnabled == hoverEnabled)
682             return;
683 
684         d->m_hoverEnabled = hoverEnabled;
685 
686         setAcceptHoverEvents(hoverEnabled);
687         setFlag(ItemAcceptsInputMethod, hoverEnabled);
688 
689         emit hoverEnabledChanged(d->m_hoverEnabled);
690     }
691 
setZoom(int newZoom,FlyToMode mode)692     void MarbleQuickItem::setZoom(int newZoom, FlyToMode mode)
693     {
694         d->m_presenter.setZoom(newZoom, mode);
695     }
696 
setZoomToMaximumLevel()697     void MarbleQuickItem::setZoomToMaximumLevel()
698     {
699         d->m_presenter.setZoom(d->m_map.maximumZoom());
700     }
701 
centerOn(const GeoDataPlacemark & placemark,bool animated)702     void MarbleQuickItem::centerOn(const GeoDataPlacemark& placemark, bool animated)
703     {
704         d->m_presenter.centerOn(placemark, animated);
705     }
706 
centerOn(const GeoDataLatLonBox & box,bool animated)707     void MarbleQuickItem::centerOn(const GeoDataLatLonBox& box, bool animated)
708     {
709         d->m_presenter.centerOn(box, animated);
710     }
711 
centerOn(const GeoDataCoordinates & coordinate)712     void MarbleQuickItem::centerOn(const GeoDataCoordinates &coordinate)
713     {
714         GeoDataLookAt target = d->m_presenter.lookAt();
715         target.setCoordinates(coordinate);
716         d->m_presenter.flyTo(target, Automatic);
717     }
718 
centerOn(qreal longitude,qreal latitude)719     void MarbleQuickItem::centerOn(qreal longitude, qreal latitude)
720     {
721         d->m_presenter.centerOn(longitude, latitude);
722     }
723 
centerOnCoordinates(qreal longitude,qreal latitude)724     void MarbleQuickItem::centerOnCoordinates(qreal longitude, qreal latitude) {
725         centerOn(longitude, latitude);
726     }
727 
centerOnCurrentPosition()728     void MarbleQuickItem::centerOnCurrentPosition()
729     {
730         GeoDataCoordinates coordinates = d->m_model.positionTracking()->currentLocation();
731         if ( coordinates == GeoDataCoordinates() ) {
732             return;
733         }
734 
735         d->m_presenter.centerOn(coordinates, true);
736         if (d->m_presenter.zoom() < 3000) {
737             d->m_presenter.setZoom(3500);
738         }
739     }
740 
selectPlacemarkAt(int x,int y)741     void MarbleQuickItem::selectPlacemarkAt(int x, int y)
742     {
743         auto features = d->m_map.whichFeatureAt(QPoint(x, y));
744         QVector<GeoDataPlacemark const *> placemarks;
745         for(auto feature: features) {
746             if (const auto placemark = geodata_cast<GeoDataPlacemark>(feature)) {
747                 placemarks << placemark;
748             }
749         }
750 
751         for(auto placemark: placemarks) {
752             if (d->m_placemark && placemark->coordinate() == d->m_placemark->placemark().coordinate()) {
753                 d->m_placemark->deleteLater();
754                 d->m_placemark = nullptr;
755             } else {
756                 if (d->m_placemark) {
757                     d->m_placemark->deleteLater();
758                 }
759                 d->m_placemark = new Placemark(this);
760                 d->m_placemark->setGeoDataPlacemark(*placemark);
761             }
762             delete d->m_placemarkItem;
763             d->m_placemarkItem = nullptr;
764             updatePlacemarks();
765             return;
766         }
767 
768         if (d->m_placemark) {
769             d->m_placemark->deleteLater();
770             d->m_placemark = nullptr;
771             delete d->m_placemarkItem;
772             d->m_placemarkItem = nullptr;
773             updatePlacemarks();
774         }
775     }
776 
goHome()777     void MarbleQuickItem::goHome()
778     {
779         d->m_presenter.goHome();
780     }
781 
zoomIn(FlyToMode mode)782     void MarbleQuickItem::zoomIn(FlyToMode mode)
783     {
784         d->m_presenter.zoomIn(mode);
785     }
786 
zoomOut(FlyToMode mode)787     void MarbleQuickItem::zoomOut(FlyToMode mode)
788     {
789         d->m_presenter.zoomOut(mode);
790     }
791 
handlePinchStarted(const QPointF & point)792     void MarbleQuickItem::handlePinchStarted(const QPointF &point)
793     {
794         pinch(point, 1, Qt::GestureStarted);
795     }
796 
handlePinchFinished(const QPointF & point)797     void MarbleQuickItem::handlePinchFinished(const QPointF &point)
798     {
799         pinch(point, 1, Qt::GestureFinished);
800     }
801 
handlePinchUpdated(const QPointF & point,qreal scale)802     void MarbleQuickItem::handlePinchUpdated(const QPointF &point, qreal scale)
803     {
804         scale = sqrt(sqrt(scale));
805         scale = qBound(static_cast<qreal>(0.5), scale, static_cast<qreal>(2.0));
806         pinch(point, scale, Qt::GestureUpdated);
807     }
808 
setMapWidth(int mapWidth)809     void MarbleQuickItem::setMapWidth(int mapWidth)
810     {
811         if (d->m_map.width() == mapWidth) {
812             return;
813         }
814 
815         d->m_map.setSize(mapWidth, mapHeight());
816         emit mapWidthChanged(mapWidth);
817     }
818 
setMapHeight(int mapHeight)819     void MarbleQuickItem::setMapHeight(int mapHeight)
820     {
821         if (this->mapHeight() == mapHeight) {
822             return;
823         }
824 
825         d->m_map.setSize(mapWidth(), mapHeight);
826         emit mapHeightChanged(mapHeight);
827     }
828 
setShowFrameRate(bool showFrameRate)829     void MarbleQuickItem::setShowFrameRate(bool showFrameRate)
830     {
831         if (this->showFrameRate() == showFrameRate) {
832             return;
833         }
834 
835         d->m_map.setShowFrameRate(showFrameRate);
836         emit showFrameRateChanged(showFrameRate);
837     }
838 
setProjection(Projection projection)839     void MarbleQuickItem::setProjection(Projection projection)
840     {
841         if (this->projection() == projection) {
842             return;
843         }
844 
845         d->m_map.setProjection(Marble::Projection(projection));
846         emit projectionChanged(projection);
847     }
848 
setMapThemeId(const QString & mapThemeId)849     void MarbleQuickItem::setMapThemeId(const QString& mapThemeId)
850     {
851         if (this->mapThemeId() == mapThemeId) {
852             return;
853         }
854 
855         bool const showCompass = d->m_map.showCompass();
856         bool const showOverviewMap = d->m_map.showOverviewMap();
857         bool const showOtherPlaces = d->m_map.showOtherPlaces();
858         bool const showGrid = d->m_map.showGrid();
859 
860         d->m_map.setMapThemeId(mapThemeId);
861 
862         // Map themes are allowed to change properties. Enforce ours.
863         d->m_map.setShowCompass(showCompass);
864         d->m_map.setShowOverviewMap(showOverviewMap);
865         d->m_map.setShowOtherPlaces(showOtherPlaces);
866         d->m_map.setShowGrid(showGrid);
867         d->m_map.setShowScaleBar(d->m_showScaleBar);
868 
869         emit mapThemeIdChanged(mapThemeId);
870     }
871 
setShowAtmosphere(bool showAtmosphere)872     void MarbleQuickItem::setShowAtmosphere(bool showAtmosphere)
873     {
874         if (this->showAtmosphere() == showAtmosphere) {
875             return;
876         }
877 
878         d->m_map.setShowAtmosphere(showAtmosphere);
879         emit showAtmosphereChanged(showAtmosphere);
880     }
881 
setShowCompass(bool showCompass)882     void MarbleQuickItem::setShowCompass(bool showCompass)
883     {
884         if (this->showCompass() == showCompass) {
885             return;
886         }
887 
888         d->m_map.setShowCompass(showCompass);
889         emit showCompassChanged(showCompass);
890     }
891 
setShowClouds(bool showClouds)892     void MarbleQuickItem::setShowClouds(bool showClouds)
893     {
894         if (this->showClouds() == showClouds) {
895             return;
896         }
897 
898         d->m_map.setShowClouds(showClouds);
899         emit showCloudsChanged(showClouds);
900     }
901 
setShowCrosshairs(bool showCrosshairs)902     void MarbleQuickItem::setShowCrosshairs(bool showCrosshairs)
903     {
904         if (this->showCrosshairs() == showCrosshairs) {
905             return;
906         }
907 
908         d->m_map.setShowCrosshairs(showCrosshairs);
909         emit showCrosshairsChanged(showCrosshairs);
910     }
911 
setShowGrid(bool showGrid)912     void MarbleQuickItem::setShowGrid(bool showGrid)
913     {
914         if (this->showGrid() == showGrid) {
915             return;
916         }
917 
918         d->m_map.setShowGrid(showGrid);
919         emit showGridChanged(showGrid);
920     }
921 
setShowOverviewMap(bool showOverviewMap)922     void MarbleQuickItem::setShowOverviewMap(bool showOverviewMap)
923     {
924         if (this->showOverviewMap() == showOverviewMap) {
925             return;
926         }
927 
928         d->m_map.setShowOverviewMap(showOverviewMap);
929         emit showOverviewMapChanged(showOverviewMap);
930     }
931 
setShowOtherPlaces(bool showOtherPlaces)932     void MarbleQuickItem::setShowOtherPlaces(bool showOtherPlaces)
933     {
934         if (this->showOtherPlaces() == showOtherPlaces) {
935             return;
936         }
937 
938         d->m_map.setShowOtherPlaces(showOtherPlaces);
939         emit showOtherPlacesChanged(showOtherPlaces);
940     }
941 
setShowScaleBar(bool showScaleBar)942     void MarbleQuickItem::setShowScaleBar(bool showScaleBar)
943     {
944         if (d->m_showScaleBar == showScaleBar) {
945             return;
946         }
947 
948         d->m_showScaleBar = showScaleBar;
949         d->m_map.setShowScaleBar(d->m_showScaleBar);
950         emit showScaleBarChanged(showScaleBar);
951     }
952 
setShowBackground(bool showBackground)953     void MarbleQuickItem::setShowBackground(bool showBackground)
954     {
955         if (this->showBackground() == showBackground) {
956             return;
957         }
958 
959         d->m_map.setShowBackground(showBackground);
960         emit showBackgroundChanged(showBackground);
961     }
962 
setShowPositionMarker(bool showPositionMarker)963     void MarbleQuickItem::setShowPositionMarker(bool showPositionMarker)
964     {
965         if (this->showPositionMarker() == showPositionMarker) {
966             return;
967         }
968 
969         QList<RenderPlugin *> plugins = d->m_map.renderPlugins();
970         for ( RenderPlugin * plugin: plugins ) {
971             if (plugin->nameId() == QLatin1String("positionMarker")) {
972                 plugin->setVisible(showPositionMarker);
973                 break;
974             }
975         }
976 
977         emit showPositionMarkerChanged(showPositionMarker);
978     }
979 
setShowPublicTransport(bool enabled)980     void MarbleQuickItem::setShowPublicTransport(bool enabled)
981     {
982         if (d->m_showPublicTransport != enabled) {
983             d->m_showPublicTransport = enabled;
984             d->updateVisibleRoutes();
985             emit showPublicTransportChanged(enabled);
986         }
987     }
988 
setShowOutdoorActivities(bool showOutdoorActivities)989     void MarbleQuickItem::setShowOutdoorActivities(bool showOutdoorActivities)
990     {
991         if (d->m_showOutdoorActivities != showOutdoorActivities) {
992             d->m_showOutdoorActivities = showOutdoorActivities;
993             d->updateVisibleRoutes();
994             emit showOutdoorActivitiesChanged(showOutdoorActivities);
995         }
996     }
997 
setPositionProvider(const QString & positionProvider)998     void MarbleQuickItem::setPositionProvider(const QString &positionProvider)
999     {
1000         QString name;
1001         if ( d->m_model.positionTracking()->positionProviderPlugin() ) {
1002             name = d->m_model.positionTracking()->positionProviderPlugin()->nameId();
1003             if ( name == positionProvider ) {
1004                 return;
1005             }
1006         }
1007 
1008         if ( positionProvider.isEmpty() ) {
1009             d->m_model.positionTracking()->setPositionProviderPlugin( nullptr );
1010             return;
1011         }
1012 
1013         QList<const PositionProviderPlugin*> plugins = d->m_model.pluginManager()->positionProviderPlugins();
1014         for (const PositionProviderPlugin* plugin: plugins) {
1015             if ( plugin->nameId() == positionProvider) {
1016                 PositionProviderPlugin * newPlugin = plugin->newInstance();
1017                 d->m_model.positionTracking()->setPositionProviderPlugin(newPlugin);
1018                 connect(newPlugin, SIGNAL(statusChanged(PositionProviderStatus)), this, SLOT(positionDataStatusChanged(PositionProviderStatus)));
1019                 connect(newPlugin, SIGNAL(positionChanged(GeoDataCoordinates,GeoDataAccuracy)), this, SLOT(updateCurrentPosition(GeoDataCoordinates)));
1020                 connect(newPlugin, SIGNAL(positionChanged(GeoDataCoordinates,GeoDataAccuracy)), this, SIGNAL(speedChanged()));
1021                 connect(newPlugin, SIGNAL(positionChanged(GeoDataCoordinates,GeoDataAccuracy)), this, SIGNAL(angleChanged()));
1022                 emit positionProviderChanged(positionProvider);
1023                 break;
1024             }
1025         }
1026     }
1027 
setInertialGlobeRotation(bool inertialGlobeRotation)1028     void MarbleQuickItem::setInertialGlobeRotation(bool inertialGlobeRotation)
1029     {
1030         if (inertialGlobeRotation == d->m_inputHandler.inertialEarthRotationEnabled()) {
1031             return;
1032         }
1033 
1034         d->m_inputHandler.setInertialEarthRotationEnabled(inertialGlobeRotation);
1035         emit inertialGlobeRotationChanged(inertialGlobeRotation);
1036     }
1037 
setAnimationViewContext(bool animationViewContext)1038     void MarbleQuickItem::setAnimationViewContext(bool animationViewContext)
1039     {
1040         d->m_map.setViewContext(animationViewContext ? Animation : Still );
1041 
1042         emit inertialGlobeRotationChanged(animationViewContext);
1043     }
1044 
setAnimationsEnabled(bool animationsEnabled)1045     void MarbleQuickItem::setAnimationsEnabled(bool animationsEnabled)
1046     {
1047         if (d->m_presenter.animationsEnabled() == animationsEnabled)
1048             return;
1049 
1050         d->m_presenter.setAnimationsEnabled(animationsEnabled);
1051         emit animationsEnabledChanged(d->m_presenter.animationsEnabled());
1052     }
1053 
setPluginSetting(const QString & pluginId,const QString & key,const QString & value)1054     void MarbleQuickItem::setPluginSetting(const QString &pluginId, const QString &key, const QString &value)
1055     {
1056         for (RenderPlugin* plugin: d->m_map.renderPlugins()) {
1057             if (plugin->nameId() == pluginId) {
1058                 plugin->setSetting(key, value);
1059             }
1060         }
1061     }
1062 
setPropertyEnabled(const QString & property,bool enabled)1063     void MarbleQuickItem::setPropertyEnabled(const QString &property, bool enabled)
1064     {
1065         d->m_map.setPropertyValue(property, enabled);
1066     }
1067 
isPropertyEnabled(const QString & property) const1068     bool MarbleQuickItem::isPropertyEnabled(const QString &property) const
1069     {
1070         return d->m_map.propertyValue(property);
1071     }
1072 
setShowRuntimeTrace(bool showRuntimeTrace)1073     void MarbleQuickItem::setShowRuntimeTrace(bool showRuntimeTrace)
1074     {
1075         d->m_map.setShowRuntimeTrace(showRuntimeTrace);
1076         update();
1077     }
1078 
setShowDebugPolygons(bool showDebugPolygons)1079     void MarbleQuickItem::setShowDebugPolygons(bool showDebugPolygons)
1080     {
1081         d->m_map.setShowDebugPolygons(showDebugPolygons);
1082         update();
1083     }
1084 
setShowDebugPlacemarks(bool showDebugPlacemarks)1085     void MarbleQuickItem::setShowDebugPlacemarks(bool showDebugPlacemarks)
1086     {
1087         d->m_map.setShowDebugPlacemarks(showDebugPlacemarks);
1088         update();
1089     }
1090 
setShowDebugBatches(bool showDebugBatches)1091     void MarbleQuickItem::setShowDebugBatches(bool showDebugBatches)
1092     {
1093         d->m_map.setShowDebugBatchRender(showDebugBatches);
1094         update();
1095     }
1096 
setPlacemarkDelegate(QQmlComponent * placemarkDelegate)1097     void MarbleQuickItem::setPlacemarkDelegate(QQmlComponent *placemarkDelegate)
1098     {
1099         if (d->m_placemarkDelegate == placemarkDelegate) {
1100             return;
1101         }
1102 
1103         delete d->m_placemarkItem;
1104         d->m_placemarkItem = nullptr;
1105         d->m_placemarkDelegate = placemarkDelegate;
1106         emit placemarkDelegateChanged(placemarkDelegate);
1107     }
1108 
loadSettings()1109     void MarbleQuickItem::loadSettings()
1110     {
1111         QSettings settings;
1112         settings.beginGroup(QStringLiteral("MarbleQuickItem"));
1113         double lon = settings.value(QStringLiteral("centerLon"), QVariant(0.0)).toDouble();
1114         double lat = settings.value(QStringLiteral("centerLat"), QVariant(0.0)).toDouble();
1115         if (lat == 0.0 && lon == 0.0) {
1116             centerOnCurrentPosition();
1117         } else {
1118             centerOn(lon, lat);
1119         }
1120         int const zoom = settings.value(QStringLiteral("zoom"), QVariant(0)).toInt();
1121         if (zoom > 0) {
1122             setZoom(zoom);
1123         }
1124         auto const defaultRelationTypes = QStringList() << "ferry" << "train" << "subway" << "tram" << "bus" << "trolley-bus" << "hiking";
1125         auto const visibleRelationTypes = settings.value(QStringLiteral("visibleRelationTypes"), defaultRelationTypes).toStringList();
1126         d->m_enabledRelationTypes = GeoDataRelation::UnknownType;
1127         for (auto const &route: visibleRelationTypes) {
1128             d->m_enabledRelationTypes |= d->m_relationTypeConverter.value(route, GeoDataRelation::UnknownType);
1129         }
1130         setShowPublicTransport(settings.value(QStringLiteral("showPublicTransport"), false).toBool());
1131         setShowOutdoorActivities(settings.value(QStringLiteral("showOutdoorActivities"), false).toBool());
1132         settings.endGroup();
1133         d->m_model.routingManager()->readSettings();
1134         d->m_model.bookmarkManager()->loadFile(QStringLiteral("bookmarks/bookmarks.kml"));
1135         d->m_model.bookmarkManager()->setShowBookmarks(true);
1136         d->updateVisibleRoutes();
1137     }
1138 
writeSettings()1139     void MarbleQuickItem::writeSettings()
1140     {
1141         QSettings settings;
1142         settings.beginGroup(QStringLiteral("MarbleQuickItem"));
1143         settings.setValue(QStringLiteral("centerLon"), QVariant(d->m_map.centerLongitude()));
1144         settings.setValue(QStringLiteral("centerLat"), QVariant(d->m_map.centerLatitude()));
1145         settings.setValue(QStringLiteral("zoom"), QVariant(zoom()));
1146         QStringList enabledRoutes;
1147         QMap<GeoDataRelation::RelationType, QString> relationConverter;
1148         for (auto iter = d->m_relationTypeConverter.cbegin(), end = d->m_relationTypeConverter.cend(); iter != end; ++iter) {
1149             relationConverter[iter.value()] = iter.key();
1150         }
1151         for (auto iter = relationConverter.cbegin(), end = relationConverter.cend(); iter != end; ++iter) {
1152             if (d->m_enabledRelationTypes & iter.key()) {
1153                 enabledRoutes << iter.value();
1154             }
1155         }
1156         settings.setValue(QStringLiteral("visibleRelationTypes"), enabledRoutes);
1157         settings.setValue(QStringLiteral("showPublicTransport"), d->m_showPublicTransport);
1158         settings.setValue(QStringLiteral("showOutdoorActivities"), d->m_showOutdoorActivities);
1159 
1160         settings.endGroup();
1161         d->m_model.routingManager()->writeSettings();
1162     }
1163 
reloadTiles()1164     void MarbleQuickItem::reloadTiles()
1165     {
1166         d->m_map.reload();
1167     }
1168 
highlightRouteRelation(qint64 osmId,bool enabled)1169     void MarbleQuickItem::highlightRouteRelation(qint64 osmId, bool enabled)
1170     {
1171         d->m_map.highlightRouteRelation(osmId, enabled);
1172     }
1173 
setRelationTypeVisible(const QString & relationType,bool visible)1174     void MarbleQuickItem::setRelationTypeVisible(const QString &relationType, bool visible)
1175     {
1176         auto const relation = d->m_relationTypeConverter.value(relationType, GeoDataRelation::UnknownType);
1177         if (visible) {
1178             d->m_enabledRelationTypes |= relation;
1179         } else {
1180             d->m_enabledRelationTypes &= ~relation;
1181         }
1182         d->updateVisibleRoutes();
1183     }
1184 
isRelationTypeVisible(const QString & relationType) const1185     bool MarbleQuickItem::isRelationTypeVisible(const QString &relationType) const
1186     {
1187         auto const relation = d->m_relationTypeConverter.value(relationType, GeoDataRelation::UnknownType);
1188         return d->m_enabledRelationTypes & relation;
1189     }
1190 
getEventFilter() const1191     QObject *MarbleQuickItem::getEventFilter() const
1192     {   //We would want to install the same event filter for abstract layer QuickItems such as PinchArea
1193         return &d->m_inputHandler;
1194     }
1195 
pinch(const QPointF & center,qreal scale,Qt::GestureState state)1196     void MarbleQuickItem::pinch(const QPointF& center, qreal scale, Qt::GestureState state)
1197     {
1198         d->m_inputHandler.pinch(center, scale, state);
1199     }
1200 
inputHandler()1201     MarbleInputHandler *MarbleQuickItem::inputHandler()
1202     {
1203         return &d->m_inputHandler;
1204     }
1205 
radius() const1206     int MarbleQuickItem::radius() const
1207     {
1208         return d->m_map.radius();
1209     }
1210 
heading() const1211     qreal MarbleQuickItem::heading() const
1212     {
1213         return d->m_map.heading();
1214     }
1215 
1216 
zoom() const1217     int MarbleQuickItem::zoom() const
1218     {
1219         return d->m_presenter.logzoom();
1220     }
1221 
minimumZoom() const1222     int MarbleQuickItem::minimumZoom() const
1223     {
1224         return d->m_presenter.minimumZoom();
1225     }
1226 
maximumZoom() const1227     int MarbleQuickItem::maximumZoom() const
1228     {
1229         return d->m_presenter.maximumZoom();
1230     }
1231 
layersEventFilter(QObject *,QEvent *)1232     bool MarbleQuickItem::layersEventFilter(QObject *, QEvent *)
1233     {   //Does nothing, but can be reimplemented in a subclass
1234         return false;
1235     }
1236 
QuickItemSelectionRubber()1237     QuickItemSelectionRubber::QuickItemSelectionRubber() :
1238         m_visible(false)
1239     {
1240         // nothing to do
1241     }
1242 
updateVisibleRoutes()1243     void MarbleQuickItemPrivate::updateVisibleRoutes()
1244     {
1245         GeoDataRelation::RelationTypes relationTypes = m_enabledRelationTypes;
1246         if (!m_showPublicTransport) {
1247             relationTypes &= ~GeoDataRelation::RouteTrain;
1248             relationTypes &= ~GeoDataRelation::RouteSubway;
1249             relationTypes &= ~GeoDataRelation::RouteTram;
1250             relationTypes &= ~GeoDataRelation::RouteBus;
1251             relationTypes &= ~GeoDataRelation::RouteTrolleyBus;
1252         }
1253         if (!m_showOutdoorActivities) {
1254             relationTypes &= ~GeoDataRelation::RouteBicycle;
1255             relationTypes &= ~GeoDataRelation::RouteMountainbike;
1256             relationTypes &= ~GeoDataRelation::RouteFoot;
1257             relationTypes &= ~GeoDataRelation::RouteHiking;
1258             relationTypes &= ~GeoDataRelation::RouteHorse;
1259             relationTypes &= ~GeoDataRelation::RouteInlineSkates;
1260             relationTypes &= ~GeoDataRelation::RouteSkiDownhill;
1261             relationTypes &= ~GeoDataRelation::RouteSkiNordic;
1262             relationTypes &= ~GeoDataRelation::RouteSkitour;
1263             relationTypes &= ~GeoDataRelation::RouteSled;
1264         }
1265         m_map.setVisibleRelationTypes(relationTypes);
1266     }
1267 
1268 }
1269