Cosmetics
[GPXSee.git] / src / GUI / mapview.cpp
blobff17b7270e73a3225aa582d9fab75a11ba11c827
1 #include <QGraphicsView>
2 #include <QGraphicsScene>
3 #include <QWheelEvent>
4 #include <QApplication>
5 #include <QPixmapCache>
6 #include <QScrollBar>
7 #include "data/poi.h"
8 #include "data/data.h"
9 #include "map/map.h"
10 #include "map/pcs.h"
11 #include "opengl.h"
12 #include "trackitem.h"
13 #include "routeitem.h"
14 #include "waypointitem.h"
15 #include "areaitem.h"
16 #include "scaleitem.h"
17 #include "coordinatesitem.h"
18 #include "keys.h"
19 #include "mapview.h"
22 #define MAX_DIGITAL_ZOOM 2
23 #define MIN_DIGITAL_ZOOM -3
24 #define MARGIN 10
25 #define SCALE_OFFSET 7
26 #define COORDINATES_OFFSET SCALE_OFFSET
29 MapView::MapView(Map *map, POI *poi, QWidget *parent)
30 : QGraphicsView(parent)
32 Q_ASSERT(map != 0);
33 Q_ASSERT(poi != 0);
35 _scene = new QGraphicsScene(this);
36 setScene(_scene);
37 setDragMode(QGraphicsView::ScrollHandDrag);
38 setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
39 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
40 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
41 setRenderHint(QPainter::Antialiasing, true);
42 setResizeAnchor(QGraphicsView::AnchorViewCenter);
43 setAcceptDrops(false);
45 _mapScale = new ScaleItem();
46 _mapScale->setZValue(2.0);
47 _scene->addItem(_mapScale);
48 _coordinates = new CoordinatesItem();
49 _coordinates->setZValue(2.0);
50 _coordinates->setVisible(false);
51 _scene->addItem(_coordinates);
53 _projection = PCS::pcs(3857);
54 _map = map;
55 _map->load();
56 _map->setProjection(_projection);
57 connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
59 _poi = poi;
60 connect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
62 _units = Metric;
63 _coordinatesFormat = DecimalDegrees;
64 _mapOpacity = 1.0;
65 _backgroundColor = Qt::white;
66 _markerColor = Qt::red;
68 _showMap = true;
69 _showTracks = true;
70 _showRoutes = true;
71 _showAreas = true;
72 _showWaypoints = true;
73 _showWaypointLabels = true;
74 _showPOI = true;
75 _showPOILabels = true;
76 _overlapPOIs = true;
77 _showRouteWaypoints = true;
78 _showMarkers = true;
79 _showPathTicks = false;
80 _trackWidth = 3;
81 _routeWidth = 3;
82 _trackStyle = Qt::SolidLine;
83 _routeStyle = Qt::DashLine;
84 _waypointSize = 8;
85 _waypointColor = Qt::black;
86 _poiSize = 8;
87 _poiColor = Qt::black;
89 #ifdef ENABLE_HIDPI
90 _deviceRatio = 1.0;
91 _mapRatio = 1.0;
92 #endif // ENABLE_HIDPI
93 _opengl = false;
94 _plot = false;
95 _digitalZoom = 0;
97 _res = _map->resolution(_map->bounds());
98 _scene->setSceneRect(_map->bounds());
100 centerOn(_scene->sceneRect().center());
103 void MapView::centerOn(const QPointF &pos)
105 QGraphicsView::centerOn(pos);
106 QRectF vr(mapToScene(viewport()->rect()).boundingRect());
107 _res = _map->resolution(vr);
108 _mapScale->setResolution(_res);
109 _coordinates->setCoordinates(Coordinates());
112 PathItem *MapView::addTrack(const Track &track)
114 if (!track.isValid()) {
115 skipColor();
116 return 0;
119 TrackItem *ti = new TrackItem(track, _map);
120 _tracks.append(ti);
121 _tr |= ti->path().boundingRect();
122 ti->setColor(_palette.nextColor());
123 ti->setWidth(_trackWidth);
124 ti->setStyle(_trackStyle);
125 ti->setUnits(_units);
126 ti->setVisible(_showTracks);
127 ti->setDigitalZoom(_digitalZoom);
128 ti->setMarkerColor(_markerColor);
129 ti->showMarker(_showMarkers);
130 ti->showTicks(_showPathTicks);
131 _scene->addItem(ti);
133 if (_showTracks)
134 addPOI(_poi->points(ti->path()));
136 return ti;
139 PathItem *MapView::addRoute(const Route &route)
141 if (!route.isValid()) {
142 skipColor();
143 return 0;
146 RouteItem *ri = new RouteItem(route, _map);
147 _routes.append(ri);
148 _rr |= ri->path().boundingRect();
149 ri->setColor(_palette.nextColor());
150 ri->setWidth(_routeWidth);
151 ri->setStyle(_routeStyle);
152 ri->setUnits(_units);
153 ri->setCoordinatesFormat(_coordinatesFormat);
154 ri->setVisible(_showRoutes);
155 ri->showWaypoints(_showRouteWaypoints);
156 ri->showWaypointLabels(_showWaypointLabels);
157 ri->setDigitalZoom(_digitalZoom);
158 ri->setMarkerColor(_markerColor);
159 ri->showMarker(_showMarkers);
160 ri->showTicks(_showPathTicks);
161 _scene->addItem(ri);
163 if (_showRoutes)
164 addPOI(_poi->points(ri->path()));
166 return ri;
169 void MapView::addArea(const Area &area)
171 if (!area.isValid()) {
172 skipColor();
173 return;
176 AreaItem *ai = new AreaItem(area, _map);
177 _areas.append(ai);
178 _ar |= ai->area().boundingRect();
179 ai->setColor(_palette.nextColor());
180 ai->setWidth(_areaWidth);
181 ai->setStyle(_areaStyle);
182 ai->setOpacity(_areaOpacity);
183 ai->setDigitalZoom(_digitalZoom);
184 ai->setVisible(_showAreas);
185 _scene->addItem(ai);
187 if (_showAreas)
188 addPOI(_poi->points(ai->area()));
191 void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
193 for (int i = 0; i < waypoints.count(); i++) {
194 const Waypoint &w = waypoints.at(i);
196 WaypointItem *wi = new WaypointItem(w, _map);
197 _waypoints.append(wi);
198 _wr = _wr.united(wi->waypoint().coordinates());
199 wi->setZValue(1);
200 wi->setSize(_waypointSize);
201 wi->setColor(_waypointColor);
202 wi->showLabel(_showWaypointLabels);
203 wi->setToolTipFormat(_units, _coordinatesFormat);
204 wi->setVisible(_showWaypoints);
205 wi->setDigitalZoom(_digitalZoom);
206 _scene->addItem(wi);
208 if (_showWaypoints)
209 addPOI(_poi->points(w));
213 QList<PathItem *> MapView::loadData(const Data &data)
215 QList<PathItem *> paths;
216 int zoom = _map->zoom();
218 for (int i = 0; i < data.tracks().count(); i++)
219 paths.append(addTrack(data.tracks().at(i)));
220 for (int i = 0; i < data.routes().count(); i++)
221 paths.append(addRoute(data.routes().at(i)));
222 for (int i = 0; i < data.areas().count(); i++)
223 addArea(data.areas().at(i));
224 addWaypoints(data.waypoints());
226 if (_tracks.empty() && _routes.empty() && _waypoints.empty()
227 && _areas.empty())
228 return paths;
230 if (fitMapZoom() != zoom)
231 rescale();
232 else
233 updatePOIVisibility();
235 centerOn(contentCenter());
237 return paths;
240 int MapView::fitMapZoom() const
242 RectC br = _tr | _rr | _wr | _ar;
244 return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN),
245 br.isNull() ? RectC(_map->xy2ll(_map->bounds().topLeft()),
246 _map->xy2ll(_map->bounds().bottomRight())) : br);
249 QPointF MapView::contentCenter() const
251 RectC br = _tr | _rr | _wr | _ar;
253 return br.isNull() ? sceneRect().center() : _map->ll2xy(br.center());
256 void MapView::updatePOIVisibility()
258 if (!_showPOI)
259 return;
261 for (POIHash::const_iterator it = _pois.constBegin();
262 it != _pois.constEnd(); it++)
263 it.value()->show();
265 if (!_overlapPOIs) {
266 for (POIHash::const_iterator it = _pois.constBegin();
267 it != _pois.constEnd(); it++) {
268 for (POIHash::const_iterator jt = _pois.constBegin();
269 jt != _pois.constEnd(); jt++) {
270 if (it.value()->isVisible() && jt.value()->isVisible()
271 && it != jt && it.value()->collidesWithItem(jt.value()))
272 jt.value()->hide();
278 void MapView::rescale()
280 _scene->setSceneRect(_map->bounds());
281 reloadMap();
283 for (int i = 0; i < _tracks.size(); i++)
284 _tracks.at(i)->setMap(_map);
285 for (int i = 0; i < _routes.size(); i++)
286 _routes.at(i)->setMap(_map);
287 for (int i = 0; i < _areas.size(); i++)
288 _areas.at(i)->setMap(_map);
289 for (int i = 0; i < _waypoints.size(); i++)
290 _waypoints.at(i)->setMap(_map);
292 for (POIHash::const_iterator it = _pois.constBegin();
293 it != _pois.constEnd(); it++)
294 it.value()->setMap(_map);
296 updatePOIVisibility();
299 void MapView::setPalette(const Palette &palette)
301 _palette = palette;
302 _palette.reset();
304 for (int i = 0; i < _tracks.count(); i++)
305 _tracks.at(i)->setColor(_palette.nextColor());
306 for (int i = 0; i < _routes.count(); i++)
307 _routes.at(i)->setColor(_palette.nextColor());
308 for (int i = 0; i < _areas.count(); i++)
309 _areas.at(i)->setColor(_palette.nextColor());
312 void MapView::setMap(Map *map)
314 QRectF vr(mapToScene(viewport()->rect()).boundingRect()
315 .intersected(_map->bounds()));
316 RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
318 _map->unload();
319 disconnect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
321 _map = map;
322 _map->load();
323 _map->setProjection(_projection);
324 #ifdef ENABLE_HIDPI
325 _map->setDevicePixelRatio(_deviceRatio, _mapRatio);
326 #endif // ENABLE_HIDPI
327 connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
329 digitalZoom(0);
331 _map->zoomFit(viewport()->rect().size(), cr);
332 _scene->setSceneRect(_map->bounds());
334 for (int i = 0; i < _tracks.size(); i++)
335 _tracks.at(i)->setMap(map);
336 for (int i = 0; i < _routes.size(); i++)
337 _routes.at(i)->setMap(map);
338 for (int i = 0; i < _areas.size(); i++)
339 _areas.at(i)->setMap(map);
340 for (int i = 0; i < _waypoints.size(); i++)
341 _waypoints.at(i)->setMap(map);
343 for (POIHash::const_iterator it = _pois.constBegin();
344 it != _pois.constEnd(); it++)
345 it.value()->setMap(_map);
346 updatePOIVisibility();
348 QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
349 _map->ll2xy(cr.bottomRight())).center();
350 centerOn(nc);
352 reloadMap();
353 QPixmapCache::clear();
356 void MapView::setPOI(POI *poi)
358 disconnect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
359 connect(poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
361 _poi = poi;
363 updatePOI();
366 void MapView::updatePOI()
368 for (POIHash::const_iterator it = _pois.constBegin();
369 it != _pois.constEnd(); it++)
370 _scene->removeItem(it.value());
371 qDeleteAll(_pois);
372 _pois.clear();
374 if (_showTracks)
375 for (int i = 0; i < _tracks.size(); i++)
376 addPOI(_poi->points(_tracks.at(i)->path()));
377 if (_showRoutes)
378 for (int i = 0; i < _routes.size(); i++)
379 addPOI(_poi->points(_routes.at(i)->path()));
380 if (_showAreas)
381 for (int i = 0; i < _areas.size(); i++)
382 addPOI(_poi->points(_areas.at(i)->area()));
383 if (_showWaypoints)
384 for (int i = 0; i< _waypoints.size(); i++)
385 addPOI(_poi->points(_waypoints.at(i)->waypoint()));
387 updatePOIVisibility();
390 void MapView::addPOI(const QList<Waypoint> &waypoints)
392 for (int i = 0; i < waypoints.size(); i++) {
393 const Waypoint &w = waypoints.at(i);
395 if (_pois.contains(SearchPointer<Waypoint>(&w)))
396 continue;
398 WaypointItem *pi = new WaypointItem(w, _map);
399 pi->setZValue(1);
400 pi->setSize(_poiSize);
401 pi->setColor(_poiColor);
402 pi->showLabel(_showPOILabels);
403 pi->setVisible(_showPOI);
404 pi->setDigitalZoom(_digitalZoom);
405 pi->setToolTipFormat(_units, _coordinatesFormat);
406 _scene->addItem(pi);
408 _pois.insert(SearchPointer<Waypoint>(&(pi->waypoint())), pi);
412 void MapView::setUnits(Units units)
414 if (_units == units)
415 return;
417 _units = units;
419 _mapScale->setUnits(_units);
421 for (int i = 0; i < _tracks.count(); i++)
422 _tracks[i]->setUnits(_units);
423 for (int i = 0; i < _routes.count(); i++)
424 _routes[i]->setUnits(_units);
425 for (int i = 0; i < _waypoints.size(); i++)
426 _waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
428 for (POIHash::const_iterator it = _pois.constBegin();
429 it != _pois.constEnd(); it++)
430 it.value()->setToolTipFormat(_units, _coordinatesFormat);
433 void MapView::setCoordinatesFormat(CoordinatesFormat format)
435 if (_coordinatesFormat == format)
436 return;
438 _coordinatesFormat = format;
440 _coordinates->setFormat(_coordinatesFormat);
442 for (int i = 0; i < _waypoints.count(); i++)
443 _waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
444 for (int i = 0; i < _routes.count(); i++)
445 _routes[i]->setCoordinatesFormat(_coordinatesFormat);
447 for (POIHash::const_iterator it = _pois.constBegin();
448 it != _pois.constEnd(); it++)
449 it.value()->setToolTipFormat(_units, _coordinatesFormat);
452 void MapView::clearMapCache()
454 _map->clearCache();
456 fitMapZoom();
457 rescale();
458 centerOn(contentCenter());
461 void MapView::digitalZoom(int zoom)
463 if (zoom) {
464 _digitalZoom += zoom;
465 scale(pow(2, zoom), pow(2, zoom));
466 } else {
467 _digitalZoom = 0;
468 resetTransform();
471 for (int i = 0; i < _tracks.size(); i++)
472 _tracks.at(i)->setDigitalZoom(_digitalZoom);
473 for (int i = 0; i < _routes.size(); i++)
474 _routes.at(i)->setDigitalZoom(_digitalZoom);
475 for (int i = 0; i < _areas.size(); i++)
476 _areas.at(i)->setDigitalZoom(_digitalZoom);
477 for (int i = 0; i < _waypoints.size(); i++)
478 _waypoints.at(i)->setDigitalZoom(_digitalZoom);
479 for (POIHash::const_iterator it = _pois.constBegin();
480 it != _pois.constEnd(); it++)
481 it.value()->setDigitalZoom(_digitalZoom);
483 _mapScale->setDigitalZoom(_digitalZoom);
484 _coordinates->setDigitalZoom(_digitalZoom);
487 void MapView::zoom(int zoom, const QPoint &pos)
489 bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
491 if (_digitalZoom) {
492 if (((_digitalZoom > 0 && zoom > 0) && (!shift || _digitalZoom
493 >= MAX_DIGITAL_ZOOM)) || ((_digitalZoom < 0 && zoom < 0) && (!shift
494 || _digitalZoom <= MIN_DIGITAL_ZOOM)))
495 return;
497 digitalZoom(zoom);
498 } else {
499 Coordinates c = _map->xy2ll(mapToScene(pos));
500 int oz = _map->zoom();
501 int nz = (zoom > 0) ? _map->zoomIn() : _map->zoomOut();
503 if (nz != oz) {
504 rescale();
505 centerOn(_map->ll2xy(c) - (pos - viewport()->rect().center()));
506 } else {
507 if (shift)
508 digitalZoom(zoom);
513 void MapView::wheelEvent(QWheelEvent *event)
515 static int deg = 0;
517 deg += event->delta() / 8;
518 if (qAbs(deg) < 15)
519 return;
520 deg = 0;
522 zoom((event->delta() > 0) ? 1 : -1, event->pos());
525 void MapView::mouseDoubleClickEvent(QMouseEvent *event)
527 if (event->button() != Qt::LeftButton && event->button() != Qt::RightButton)
528 return;
530 zoom((event->button() == Qt::LeftButton) ? 1 : -1, event->pos());
533 void MapView::keyPressEvent(QKeyEvent *event)
535 int z;
537 QPoint pos = viewport()->rect().center();
539 if (event->key() == ZOOM_IN)
540 z = 1;
541 else if (event->key() == ZOOM_OUT)
542 z = -1;
543 else if (_digitalZoom && event->key() == Qt::Key_Escape) {
544 digitalZoom(0);
545 return;
546 } else {
547 QGraphicsView::keyPressEvent(event);
548 return;
551 zoom(z, pos);
554 void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
555 bool hires)
557 QRect orig, adj;
558 qreal ratio, diff, q;
559 QPointF origScene, origPos;
560 int zoom;
563 // Enter plot mode
564 setUpdatesEnabled(false);
565 _plot = true;
566 #ifdef ENABLE_HIDPI
567 _map->setDevicePixelRatio(_deviceRatio, 1.0);
568 #endif // ENABLE_HIDPI
570 // Compute sizes & ratios
571 orig = viewport()->rect();
572 origPos = _mapScale->pos();
574 if (orig.height() * (target.width() / target.height()) - orig.width() < 0) {
575 ratio = target.height() / target.width();
576 diff = (orig.width() * ratio) - orig.height();
577 adj = orig.adjusted(0, -diff/2, 0, diff/2);
578 } else {
579 ratio = target.width() / target.height();
580 diff = (orig.height() * ratio) - orig.width();
581 adj = orig.adjusted(-diff/2, 0, diff/2, 0);
583 q = (target.width() / scale) / adj.width();
585 // Adjust the view for printing
586 if (hires) {
587 zoom = _map->zoom();
588 QRectF vr(mapToScene(orig).boundingRect());
589 origScene = vr.center();
591 QPointF s(painter->device()->logicalDpiX()
592 / (qreal)metric(QPaintDevice::PdmDpiX),
593 painter->device()->logicalDpiY()
594 / (qreal)metric(QPaintDevice::PdmDpiY));
595 adj = QRect(0, 0, adj.width() * s.x(), adj.height() * s.y());
596 _map->zoomFit(adj.size(), _tr | _rr | _wr | _ar);
597 rescale();
599 QPointF center = contentCenter();
600 centerOn(center);
601 adj.moveCenter(mapFromScene(center));
603 _mapScale->setDigitalZoom(_digitalZoom - log2(s.x() / q));
604 _mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
605 -(SCALE_OFFSET + _mapScale->boundingRect().width()) * (s.x() / q),
606 -(SCALE_OFFSET + _mapScale->boundingRect().height()) * (s.x() / q)))));
607 } else {
608 _mapScale->setDigitalZoom(_digitalZoom - log2(1.0 / q));
609 _mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
610 -(SCALE_OFFSET + _mapScale->boundingRect().width()) / q ,
611 -(SCALE_OFFSET + _mapScale->boundingRect().height()) / q))));
614 // Print the view
615 render(painter, target, adj);
617 // Revert view changes to display mode
618 if (hires) {
619 _map->setZoom(zoom);
620 rescale();
621 centerOn(origScene);
623 _mapScale->setDigitalZoom(_digitalZoom);
624 _mapScale->setPos(origPos);
626 // Exit plot mode
627 #ifdef ENABLE_HIDPI
628 _map->setDevicePixelRatio(_deviceRatio, _mapRatio);
629 #endif // ENABLE_HIDPI
630 _plot = false;
631 setUpdatesEnabled(true);
634 void MapView::clear()
636 _pois.clear();
637 _tracks.clear();
638 _routes.clear();
639 _areas.clear();
640 _waypoints.clear();
642 _scene->removeItem(_mapScale);
643 _scene->removeItem(_coordinates);
644 _scene->clear();
645 _scene->addItem(_mapScale);
646 _scene->addItem(_coordinates);
648 _palette.reset();
650 _tr = RectC();
651 _rr = RectC();
652 _wr = RectC();
653 _ar = RectC();
655 digitalZoom(0);
657 // If not reset, causes huge redraw areas (and system memory exhaustion)
658 resetCachedContent();
661 void MapView::showTracks(bool show)
663 _showTracks = show;
665 for (int i = 0; i < _tracks.count(); i++)
666 _tracks.at(i)->setVisible(show);
668 updatePOI();
671 void MapView::showRoutes(bool show)
673 _showRoutes = show;
675 for (int i = 0; i < _routes.count(); i++)
676 _routes.at(i)->setVisible(show);
678 updatePOI();
681 void MapView::showWaypoints(bool show)
683 _showWaypoints = show;
685 for (int i = 0; i < _waypoints.count(); i++)
686 _waypoints.at(i)->setVisible(show);
688 updatePOI();
691 void MapView::showAreas(bool show)
693 _showAreas = show;
695 for (int i = 0; i < _areas.count(); i++)
696 _areas.at(i)->setVisible(show);
698 updatePOI();
701 void MapView::showWaypointLabels(bool show)
703 _showWaypointLabels = show;
705 for (int i = 0; i < _waypoints.size(); i++)
706 _waypoints.at(i)->showLabel(show);
707 for (int i = 0; i < _routes.size(); i++)
708 _routes.at(i)->showWaypointLabels(show);
711 void MapView::showRouteWaypoints(bool show)
713 _showRouteWaypoints = show;
715 for (int i = 0; i < _routes.size(); i++)
716 _routes.at(i)->showWaypoints(show);
719 void MapView::showMarkers(bool show)
721 _showMarkers = show;
723 for (int i = 0; i < _tracks.size(); i++)
724 _tracks.at(i)->showMarker(show);
725 for (int i = 0; i < _routes.size(); i++)
726 _routes.at(i)->showMarker(show);
729 void MapView::showTicks(bool show)
731 _showPathTicks = show;
732 for (int i = 0; i < _tracks.size(); i++)
733 _tracks.at(i)->showTicks(show);
734 for (int i = 0; i < _routes.size(); i++)
735 _routes.at(i)->showTicks(show);
738 void MapView::showMap(bool show)
740 _showMap = show;
741 reloadMap();
744 void MapView::showPOI(bool show)
746 _showPOI = show;
748 for (POIHash::const_iterator it = _pois.constBegin();
749 it != _pois.constEnd(); it++)
750 it.value()->setVisible(show);
752 updatePOIVisibility();
755 void MapView::showPOILabels(bool show)
757 _showPOILabels = show;
759 for (POIHash::const_iterator it = _pois.constBegin();
760 it != _pois.constEnd(); it++)
761 it.value()->showLabel(show);
763 updatePOIVisibility();
766 void MapView::showCoordinates(bool show)
768 _coordinates->setVisible(show);
769 setMouseTracking(show);
772 void MapView::setPOIOverlap(bool overlap)
774 _overlapPOIs = overlap;
776 updatePOIVisibility();
779 void MapView::setTrackWidth(int width)
781 _trackWidth = width;
783 for (int i = 0; i < _tracks.count(); i++)
784 _tracks.at(i)->setWidth(width);
787 void MapView::setRouteWidth(int width)
789 _routeWidth = width;
791 for (int i = 0; i < _routes.count(); i++)
792 _routes.at(i)->setWidth(width);
795 void MapView::setAreaWidth(int width)
797 _areaWidth = width;
799 for (int i = 0; i < _areas.count(); i++)
800 _areas.at(i)->setWidth(width);
803 void MapView::setTrackStyle(Qt::PenStyle style)
805 _trackStyle = style;
807 for (int i = 0; i < _tracks.count(); i++)
808 _tracks.at(i)->setStyle(style);
811 void MapView::setRouteStyle(Qt::PenStyle style)
813 _routeStyle = style;
815 for (int i = 0; i < _routes.count(); i++)
816 _routes.at(i)->setStyle(style);
819 void MapView::setAreaStyle(Qt::PenStyle style)
821 _areaStyle = style;
823 for (int i = 0; i < _areas.count(); i++)
824 _areas.at(i)->setStyle(style);
827 void MapView::setAreaOpacity(int opacity)
829 _areaOpacity = opacity / 100.0;
831 for (int i = 0; i < _areas.count(); i++)
832 _areas.at(i)->setOpacity(_areaOpacity);
835 void MapView::setWaypointSize(int size)
837 _waypointSize = size;
839 for (int i = 0; i < _waypoints.size(); i++)
840 _waypoints.at(i)->setSize(size);
843 void MapView::setWaypointColor(const QColor &color)
845 _waypointColor = color;
847 for (int i = 0; i < _waypoints.size(); i++)
848 _waypoints.at(i)->setColor(color);
851 void MapView::setPOISize(int size)
853 _poiSize = size;
855 for (POIHash::const_iterator it = _pois.constBegin();
856 it != _pois.constEnd(); it++)
857 it.value()->setSize(size);
860 void MapView::setPOIColor(const QColor &color)
862 _poiColor = color;
864 for (POIHash::const_iterator it = _pois.constBegin();
865 it != _pois.constEnd(); it++)
866 it.value()->setColor(color);
869 void MapView::setMapOpacity(int opacity)
871 _mapOpacity = opacity / 100.0;
872 reloadMap();
875 void MapView::setBackgroundColor(const QColor &color)
877 _backgroundColor = color;
878 reloadMap();
881 void MapView::drawBackground(QPainter *painter, const QRectF &rect)
883 painter->fillRect(rect, _backgroundColor);
885 if (_showMap) {
886 QRectF ir = rect.intersected(_map->bounds());
887 Map::Flags flags = Map::NoFlags;
889 if (_mapOpacity < 1.0)
890 painter->setOpacity(_mapOpacity);
892 if (_plot)
893 flags = Map::Block;
894 else if (_opengl)
895 flags = Map::OpenGL;
897 _map->draw(painter, ir, flags);
901 void MapView::paintEvent(QPaintEvent *event)
903 QPointF scaleScenePos = mapToScene(rect().bottomRight() + QPoint(
904 -(SCALE_OFFSET + _mapScale->boundingRect().width()),
905 -(SCALE_OFFSET + _mapScale->boundingRect().height())));
906 if (_mapScale->pos() != scaleScenePos && !_plot)
907 _mapScale->setPos(scaleScenePos);
909 if (_coordinates->isVisible()) {
910 QPointF coordinatesScenePos = mapToScene(rect().bottomLeft()
911 + QPoint(COORDINATES_OFFSET, -COORDINATES_OFFSET));
912 if (_coordinates->pos() != coordinatesScenePos && !_plot)
913 _coordinates->setPos(coordinatesScenePos);
916 QGraphicsView::paintEvent(event);
919 void MapView::scrollContentsBy(int dx, int dy)
921 QGraphicsView::scrollContentsBy(dx, dy);
923 QRectF sr(mapToScene(viewport()->rect()).boundingRect());
924 qreal res = _map->resolution(sr);
926 if (qMax(res, _res) / qMin(res, _res) > 1.1) {
927 _mapScale->setResolution(res);
928 _res = res;
932 void MapView::mouseMoveEvent(QMouseEvent *event)
934 if (_coordinates->isVisible())
935 _coordinates->setCoordinates(_map->xy2ll(mapToScene(event->pos())));
937 QGraphicsView::mouseMoveEvent(event);
940 void MapView::leaveEvent(QEvent *event)
942 _coordinates->setCoordinates(Coordinates());
943 QGraphicsView::leaveEvent(event);
946 void MapView::useOpenGL(bool use)
948 _opengl = use;
950 if (use)
951 setViewport(new OPENGL_WIDGET);
952 else
953 setViewport(new QWidget);
956 void MapView::useAntiAliasing(bool use)
958 setRenderHint(QPainter::Antialiasing, use);
961 void MapView::setMarkerColor(const QColor &color)
963 _markerColor = color;
965 for (int i = 0; i < _tracks.size(); i++)
966 _tracks.at(i)->setMarkerColor(color);
967 for (int i = 0; i < _routes.size(); i++)
968 _routes.at(i)->setMarkerColor(color);
971 void MapView::reloadMap()
973 _scene->invalidate();
976 void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
978 #ifdef ENABLE_HIDPI
979 if (_deviceRatio == deviceRatio && _mapRatio == mapRatio)
980 return;
982 _deviceRatio = deviceRatio;
983 _mapRatio = mapRatio;
984 QPixmapCache::clear();
986 QRectF vr(mapToScene(viewport()->rect()).boundingRect()
987 .intersected(_map->bounds()));
988 RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
990 _map->setDevicePixelRatio(_deviceRatio, _mapRatio);
991 _scene->setSceneRect(_map->bounds());
993 for (int i = 0; i < _tracks.size(); i++)
994 _tracks.at(i)->setMap(_map);
995 for (int i = 0; i < _routes.size(); i++)
996 _routes.at(i)->setMap(_map);
997 for (int i = 0; i < _areas.size(); i++)
998 _areas.at(i)->setMap(_map);
999 for (int i = 0; i < _waypoints.size(); i++)
1000 _waypoints.at(i)->setMap(_map);
1002 for (POIHash::const_iterator it = _pois.constBegin();
1003 it != _pois.constEnd(); it++)
1004 it.value()->setMap(_map);
1005 updatePOIVisibility();
1007 QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
1008 _map->ll2xy(cr.bottomRight())).center();
1009 centerOn(nc);
1011 reloadMap();
1012 #else // ENABLE_HIDPI
1013 Q_UNUSED(deviceRatio);
1014 Q_UNUSED(mapRatio);
1015 #endif // ENABLE_HIDPI
1018 void MapView::setProjection(int id)
1020 const PCS *pcs;
1021 const GCS *gcs;
1022 Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
1024 if ((pcs = PCS::pcs(id)))
1025 _projection = Projection(pcs);
1026 else if ((gcs = GCS::gcs(id)))
1027 _projection = Projection(gcs);
1028 else
1029 qWarning("%d: Unknown PCS/GCS id", id);
1031 _map->setProjection(_projection);
1032 rescale();
1033 centerOn(_map->ll2xy(center));
1036 void MapView::fitContentToSize()
1038 int zoom = _map->zoom();
1039 if (fitMapZoom() != zoom)
1040 rescale();
1042 centerOn(contentCenter());