Marble

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

KDE's Doxygen guidelines are available online.