diff --git a/gpxsee.qrc b/gpxsee.qrc index 90a57df4..a96a5601 100644 --- a/gpxsee.qrc +++ b/gpxsee.qrc @@ -1,24 +1,44 @@ - - icons/dialog-close.png - icons/document-open.png - icons/document-print.png - icons/document-export.png - icons/flag.png - icons/gpxsee.png - icons/application-exit.png - icons/applications-internet.png - icons/view-refresh.png - icons/arrow-left.png - icons/arrow-right.png - icons/arrow-left-double.png - icons/arrow-right-double.png - icons/view-fullscreen.png - icons/office-chart-line.png - icons/preferences-desktop-display.png - icons/flag_48.png - icons/system-run.png - icons/document-print-preview.png - icons/view-filter.png - + + icons/dialog-close.png + icons/dialog-close@2x.png + icons/document-open.png + icons/document-open@2x.png + icons/document-print.png + icons/document-print@2x.png + icons/document-export.png + icons/document-export@2x.png + icons/flag.png + icons/flag@2x.png + icons/gpxsee.png + icons/gpxsee@2x.png + icons/application-exit.png + icons/application-exit@2x.png + icons/applications-internet.png + icons/applications-internet@2x.png + icons/view-refresh.png + icons/view-refresh@2x.png + icons/arrow-left.png + icons/arrow-left@2x.png + icons/arrow-right.png + icons/arrow-right@2x.png + icons/arrow-left-double.png + icons/arrow-left-double@2x.png + icons/arrow-right-double.png + icons/arrow-right-double@2x.png + icons/view-fullscreen.png + icons/view-fullscreen@2x.png + icons/office-chart-line.png + icons/office-chart-line@2x.png + icons/format-stroke-color.png + icons/format-stroke-color@2x.png + icons/flag_32.png + icons/flag_32@2x.png + icons/preferences-system.png + icons/preferences-system@2x.png + icons/document-print_32.png + icons/document-print_32@2x.png + icons/view-filter.png + icons/view-filter@2x.png + diff --git a/icons/application-exit@2x.png b/icons/application-exit@2x.png new file mode 100644 index 00000000..294f8fd5 Binary files /dev/null and b/icons/application-exit@2x.png differ diff --git a/icons/applications-internet@2x.png b/icons/applications-internet@2x.png new file mode 100644 index 00000000..e47b65a4 Binary files /dev/null and b/icons/applications-internet@2x.png differ diff --git a/icons/arrow-left-double@2x.png b/icons/arrow-left-double@2x.png new file mode 100644 index 00000000..95324cdb Binary files /dev/null and b/icons/arrow-left-double@2x.png differ diff --git a/icons/arrow-left@2x.png b/icons/arrow-left@2x.png new file mode 100644 index 00000000..a8f1ff49 Binary files /dev/null and b/icons/arrow-left@2x.png differ diff --git a/icons/arrow-right-double@2x.png b/icons/arrow-right-double@2x.png new file mode 100644 index 00000000..1729db7d Binary files /dev/null and b/icons/arrow-right-double@2x.png differ diff --git a/icons/arrow-right@2x.png b/icons/arrow-right@2x.png new file mode 100644 index 00000000..4c77710c Binary files /dev/null and b/icons/arrow-right@2x.png differ diff --git a/icons/dialog-close@2x.png b/icons/dialog-close@2x.png new file mode 100644 index 00000000..acc22a5c Binary files /dev/null and b/icons/dialog-close@2x.png differ diff --git a/icons/document-export@2x.png b/icons/document-export@2x.png new file mode 100644 index 00000000..13814cf8 Binary files /dev/null and b/icons/document-export@2x.png differ diff --git a/icons/document-open.png b/icons/document-open.png index bc8cface..317a3577 100644 Binary files a/icons/document-open.png and b/icons/document-open.png differ diff --git a/icons/document-open@2x.png b/icons/document-open@2x.png new file mode 100644 index 00000000..0300ab3d Binary files /dev/null and b/icons/document-open@2x.png differ diff --git a/icons/document-print-preview.png b/icons/document-print-preview.png deleted file mode 100644 index 614ffc46..00000000 Binary files a/icons/document-print-preview.png and /dev/null differ diff --git a/icons/document-print@2x.png b/icons/document-print@2x.png new file mode 100644 index 00000000..ada04cd4 Binary files /dev/null and b/icons/document-print@2x.png differ diff --git a/icons/document-print_32.png b/icons/document-print_32.png new file mode 100644 index 00000000..d6555042 Binary files /dev/null and b/icons/document-print_32.png differ diff --git a/icons/document-print_32@2x.png b/icons/document-print_32@2x.png new file mode 100644 index 00000000..8dc77a8d Binary files /dev/null and b/icons/document-print_32@2x.png differ diff --git a/icons/flag@2x.png b/icons/flag@2x.png new file mode 100644 index 00000000..5ee8f729 Binary files /dev/null and b/icons/flag@2x.png differ diff --git a/icons/flag_32.png b/icons/flag_32.png new file mode 100644 index 00000000..51e1c8f8 Binary files /dev/null and b/icons/flag_32.png differ diff --git a/icons/flag_32@2x.png b/icons/flag_32@2x.png new file mode 100644 index 00000000..fa889df2 Binary files /dev/null and b/icons/flag_32@2x.png differ diff --git a/icons/flag_48.png b/icons/flag_48.png deleted file mode 100644 index 8d450bf2..00000000 Binary files a/icons/flag_48.png and /dev/null differ diff --git a/icons/format-stroke-color.png b/icons/format-stroke-color.png new file mode 100644 index 00000000..05c34b9a Binary files /dev/null and b/icons/format-stroke-color.png differ diff --git a/icons/format-stroke-color@2x.png b/icons/format-stroke-color@2x.png new file mode 100644 index 00000000..7274212d Binary files /dev/null and b/icons/format-stroke-color@2x.png differ diff --git a/icons/gpxsee@2x.png b/icons/gpxsee@2x.png new file mode 100644 index 00000000..6a4bf228 Binary files /dev/null and b/icons/gpxsee@2x.png differ diff --git a/icons/office-chart-line@2x.png b/icons/office-chart-line@2x.png new file mode 100644 index 00000000..0cbf5994 Binary files /dev/null and b/icons/office-chart-line@2x.png differ diff --git a/icons/preferences-desktop-display.png b/icons/preferences-desktop-display.png deleted file mode 100644 index 3334a429..00000000 Binary files a/icons/preferences-desktop-display.png and /dev/null differ diff --git a/icons/preferences-system.png b/icons/preferences-system.png new file mode 100644 index 00000000..2afbd23c Binary files /dev/null and b/icons/preferences-system.png differ diff --git a/icons/preferences-system@2x.png b/icons/preferences-system@2x.png new file mode 100644 index 00000000..9ea5cec4 Binary files /dev/null and b/icons/preferences-system@2x.png differ diff --git a/icons/system-run.png b/icons/system-run.png deleted file mode 100644 index e3f93dd4..00000000 Binary files a/icons/system-run.png and /dev/null differ diff --git a/icons/view-filter.png b/icons/view-filter.png index abcb39de..d20f31d8 100644 Binary files a/icons/view-filter.png and b/icons/view-filter.png differ diff --git a/icons/view-filter@2x.png b/icons/view-filter@2x.png new file mode 100644 index 00000000..c10ccc05 Binary files /dev/null and b/icons/view-filter@2x.png differ diff --git a/icons/view-fullscreen@2x.png b/icons/view-fullscreen@2x.png new file mode 100644 index 00000000..b6d16076 Binary files /dev/null and b/icons/view-fullscreen@2x.png differ diff --git a/icons/view-refresh@2x.png b/icons/view-refresh@2x.png new file mode 100644 index 00000000..1db3e742 Binary files /dev/null and b/icons/view-refresh@2x.png differ diff --git a/src/GUI/axisitem.cpp b/src/GUI/axisitem.cpp index a2c487f4..9eedfe87 100644 --- a/src/GUI/axisitem.cpp +++ b/src/GUI/axisitem.cpp @@ -43,10 +43,6 @@ AxisItem::AxisItem(Type type, QGraphicsItem *parent) : QGraphicsItem(parent) _font.setPixelSize(FONT_SIZE); _font.setFamily(FONT_FAMILY); - -#ifndef Q_OS_MAC - setCacheMode(QGraphicsItem::DeviceCoordinateCache); -#endif // Q_OS_MAC } void AxisItem::setRange(const RangeF &range) diff --git a/src/GUI/gui.cpp b/src/GUI/gui.cpp index dd4072e8..94476564 100644 --- a/src/GUI/gui.cpp +++ b/src/GUI/gui.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include #include #include @@ -22,12 +23,16 @@ #include #include #include +#ifdef ENABLE_HIDPI +#include +#include +#endif // ENABLE_HIDPI +#include #include "data/data.h" #include "data/poi.h" #include "map/maplist.h" #include "map/emptymap.h" #include "map/downloader.h" -#include "config.h" #include "icons.h" #include "keys.h" #include "settings.h" @@ -48,6 +53,8 @@ #include "gui.h" +#define TOOLBAR_ICON_SIZE 22 + GUI::GUI() { loadMaps(); @@ -72,7 +79,7 @@ GUI::GUI() _splitter->setStretchFactor(1, 1); setCentralWidget(_splitter); - setWindowIcon(QIcon(QPixmap(APP_ICON))); + setWindowIcon(QIcon(APP_ICON)); setWindowTitle(APP_NAME); setUnifiedTitleAndToolBarOnMac(true); setAcceptDrops(true); @@ -195,7 +202,7 @@ void GUI::createActions() _navigationActionGroup->setEnabled(false); // General actions - _exitAction = new QAction(QIcon(QPixmap(QUIT_ICON)), tr("Quit"), this); + _exitAction = new QAction(QIcon(QUIT_ICON), tr("Quit"), this); _exitAction->setShortcut(QUIT_SHORTCUT); _exitAction->setMenuRole(QAction::QuitRole); connect(_exitAction, SIGNAL(triggered()), this, SLOT(close())); @@ -208,40 +215,37 @@ void GUI::createActions() _keysAction = new QAction(tr("Keyboard controls"), this); _keysAction->setMenuRole(QAction::NoRole); connect(_keysAction, SIGNAL(triggered()), this, SLOT(keys())); - _aboutAction = new QAction(QIcon(QPixmap(APP_ICON)), - tr("About GPXSee"), this); + _aboutAction = new QAction(QIcon(APP_ICON), tr("About GPXSee"), this); _aboutAction->setMenuRole(QAction::AboutRole); connect(_aboutAction, SIGNAL(triggered()), this, SLOT(about())); // File actions - _openFileAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)), - tr("Open..."), this); + _openFileAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Open..."), this); _openFileAction->setMenuRole(QAction::NoRole); _openFileAction->setShortcut(OPEN_SHORTCUT); connect(_openFileAction, SIGNAL(triggered()), this, SLOT(openFile())); addAction(_openFileAction); - _printFileAction = new QAction(QIcon(QPixmap(PRINT_FILE_ICON)), - tr("Print..."), this); + _printFileAction = new QAction(QIcon(PRINT_FILE_ICON), tr("Print..."), + this); _printFileAction->setMenuRole(QAction::NoRole); _printFileAction->setActionGroup(_fileActionGroup); connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile())); addAction(_printFileAction); - _exportFileAction = new QAction(QIcon(QPixmap(EXPORT_FILE_ICON)), + _exportFileAction = new QAction(QIcon(EXPORT_FILE_ICON), tr("Export to PDF..."), this); _exportFileAction->setMenuRole(QAction::NoRole); _exportFileAction->setShortcut(EXPORT_SHORTCUT); _exportFileAction->setActionGroup(_fileActionGroup); connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile())); addAction(_exportFileAction); - _closeFileAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)), - tr("Close"), this); + _closeFileAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close"), this); _closeFileAction->setMenuRole(QAction::NoRole); _closeFileAction->setShortcut(CLOSE_SHORTCUT); _closeFileAction->setActionGroup(_fileActionGroup); connect(_closeFileAction, SIGNAL(triggered()), this, SLOT(closeAll())); addAction(_closeFileAction); - _reloadFileAction = new QAction(QIcon(QPixmap(RELOAD_FILE_ICON)), - tr("Reload"), this); + _reloadFileAction = new QAction(QIcon(RELOAD_FILE_ICON), tr("Reload"), + this); _reloadFileAction->setMenuRole(QAction::NoRole); _reloadFileAction->setShortcut(RELOAD_SHORTCUT); _reloadFileAction->setActionGroup(_fileActionGroup); @@ -255,12 +259,12 @@ void GUI::createActions() addAction(_statisticsAction); // POI actions - _openPOIAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)), - tr("Load POI file..."), this); + _openPOIAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Load POI file..."), + this); _openPOIAction->setMenuRole(QAction::NoRole); connect(_openPOIAction, SIGNAL(triggered()), this, SLOT(openPOIFile())); - _closePOIAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)), - tr("Close POI files"), this); + _closePOIAction = new QAction(QIcon(CLOSE_FILE_ICON), tr("Close POI files"), + this); _closePOIAction->setMenuRole(QAction::NoRole); connect(_closePOIAction, SIGNAL(triggered()), this, SLOT(closePOIFiles())); _overlapPOIAction = new QAction(tr("Overlap POIs"), this); @@ -273,8 +277,7 @@ void GUI::createActions() _showPOILabelsAction->setCheckable(true); connect(_showPOILabelsAction, SIGNAL(triggered(bool)), _mapView, SLOT(showPOILabels(bool))); - _showPOIAction = new QAction(QIcon(QPixmap(SHOW_POI_ICON)), - tr("Show POIs"), this); + _showPOIAction = new QAction(QIcon(SHOW_POI_ICON), tr("Show POIs"), this); _showPOIAction->setMenuRole(QAction::NoRole); _showPOIAction->setCheckable(true); _showPOIAction->setShortcut(SHOW_POI_SHORTCUT); @@ -284,7 +287,7 @@ void GUI::createActions() createPOIFilesActions(); // Map actions - _showMapAction = new QAction(QIcon(QPixmap(SHOW_MAP_ICON)), tr("Show map"), + _showMapAction = new QAction(QIcon(SHOW_MAP_ICON), tr("Show map"), this); _showMapAction->setMenuRole(QAction::NoRole); _showMapAction->setCheckable(true); @@ -292,8 +295,8 @@ void GUI::createActions() connect(_showMapAction, SIGNAL(triggered(bool)), _mapView, SLOT(showMap(bool))); addAction(_showMapAction); - _loadMapAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)), - tr("Load map..."), this); + _loadMapAction = new QAction(QIcon(OPEN_FILE_ICON), tr("Load map..."), + this); _loadMapAction->setMenuRole(QAction::NoRole); connect(_loadMapAction, SIGNAL(triggered()), this, SLOT(loadMap())); _clearMapCacheAction = new QAction(tr("Clear tile cache"), this); @@ -344,8 +347,8 @@ void GUI::createActions() SLOT(showRouteWaypoints(bool))); // Graph actions - _showGraphsAction = new QAction(QIcon(QPixmap(SHOW_GRAPHS_ICON)), - tr("Show graphs"), this); + _showGraphsAction = new QAction(QIcon(SHOW_GRAPHS_ICON), tr("Show graphs"), + this); _showGraphsAction->setMenuRole(QAction::NoRole); _showGraphsAction->setCheckable(true); _showGraphsAction->setShortcut(SHOW_GRAPHS_SHORTCUT); @@ -439,7 +442,7 @@ void GUI::createActions() _DMSAction->setCheckable(true); _DMSAction->setActionGroup(ag); connect(_DMSAction, SIGNAL(triggered()), this, SLOT(setDMS())); - _fullscreenAction = new QAction(QIcon(QPixmap(FULLSCREEN_ICON)), + _fullscreenAction = new QAction(QIcon(FULLSCREEN_ICON), tr("Fullscreen mode"), this); _fullscreenAction->setMenuRole(QAction::NoRole); _fullscreenAction->setCheckable(true); @@ -453,21 +456,19 @@ void GUI::createActions() SLOT(openOptions())); // Navigation actions - _nextAction = new QAction(QIcon(QPixmap(NEXT_FILE_ICON)), tr("Next"), this); + _nextAction = new QAction(QIcon(NEXT_FILE_ICON), tr("Next"), this); _nextAction->setActionGroup(_navigationActionGroup); _nextAction->setMenuRole(QAction::NoRole); connect(_nextAction, SIGNAL(triggered()), this, SLOT(next())); - _prevAction = new QAction(QIcon(QPixmap(PREV_FILE_ICON)), tr("Previous"), - this); + _prevAction = new QAction(QIcon(PREV_FILE_ICON), tr("Previous"), this); _prevAction->setMenuRole(QAction::NoRole); _prevAction->setActionGroup(_navigationActionGroup); connect(_prevAction, SIGNAL(triggered()), this, SLOT(prev())); - _lastAction = new QAction(QIcon(QPixmap(LAST_FILE_ICON)), tr("Last"), this); + _lastAction = new QAction(QIcon(LAST_FILE_ICON), tr("Last"), this); _lastAction->setMenuRole(QAction::NoRole); _lastAction->setActionGroup(_navigationActionGroup); connect(_lastAction, SIGNAL(triggered()), this, SLOT(last())); - _firstAction = new QAction(QIcon(QPixmap(FIRST_FILE_ICON)), tr("First"), - this); + _firstAction = new QAction(QIcon(FIRST_FILE_ICON), tr("First"), this); _firstAction->setMenuRole(QAction::NoRole); _firstAction->setActionGroup(_navigationActionGroup); connect(_firstAction, SIGNAL(triggered()), this, SLOT(first())); @@ -555,22 +556,28 @@ void GUI::createMenus() void GUI::createToolBars() { + int is = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + QSize iconSize(qMin(is, TOOLBAR_ICON_SIZE), qMin(is, TOOLBAR_ICON_SIZE)); + #ifdef Q_OS_MAC setToolButtonStyle(Qt::ToolButtonTextUnderIcon); #endif // Q_OS_MAC _fileToolBar = addToolBar(tr("File")); + _fileToolBar->setIconSize(iconSize); _fileToolBar->addAction(_openFileAction); _fileToolBar->addAction(_reloadFileAction); _fileToolBar->addAction(_closeFileAction); _fileToolBar->addAction(_printFileAction); _showToolBar = addToolBar(tr("Show")); + _showToolBar->setIconSize(iconSize); _showToolBar->addAction(_showPOIAction); _showToolBar->addAction(_showMapAction); _showToolBar->addAction(_showGraphsAction); _navigationToolBar = addToolBar(tr("Navigation")); + _navigationToolBar->setIconSize(iconSize); _navigationToolBar->addAction(_firstAction); _navigationToolBar->addAction(_prevAction); _navigationToolBar->addAction(_nextAction); @@ -2107,3 +2114,39 @@ qreal GUI::movingTime() const { return (_showTracksAction->isChecked()) ? _movingTime : 0; } + +void GUI::show() +{ + QMainWindow::show(); + +#ifdef ENABLE_HIDPI + QWindow *w = windowHandle(); + connect(w->screen(), SIGNAL(logicalDotsPerInchChanged(qreal)), this, + SLOT(logicalDotsPerInchChanged(qreal))); + connect(w, SIGNAL(screenChanged(QScreen*)), this, + SLOT(screenChanged(QScreen*))); +#endif // ENABLE_HIDPI +} + +void GUI::screenChanged(QScreen *screen) +{ +#ifdef ENABLE_HIDPI + _mapView->updateDevicePixelRatio(); + + disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this, + SLOT(logicalDotsPerInchChanged(qreal))); + connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)), this, + SLOT(logicalDotsPerInchChanged(qreal))); +#else // ENABLE_HIDPI + Q_UNUSED(screen); +#endif // ENABLE_HIDPI +} + +void GUI::logicalDotsPerInchChanged(qreal dpi) +{ + Q_UNUSED(dpi) + +#ifdef ENABLE_HIDPI + _mapView->updateDevicePixelRatio(); +#endif // ENBLE_HIDPI +} diff --git a/src/GUI/gui.h b/src/GUI/gui.h index 92a4f77d..acebc03e 100644 --- a/src/GUI/gui.h +++ b/src/GUI/gui.h @@ -28,6 +28,7 @@ class MapView; class Map; class MapList; class POI; +class QScreen; class GUI : public QMainWindow { @@ -37,6 +38,7 @@ public: GUI(); bool openFile(const QString &fileName); + void show(); private slots: void about(); @@ -83,6 +85,8 @@ private slots: void setDMS() {setCoordinatesFormat(DMS);} void sliderPositionChanged(qreal pos); + void screenChanged(QScreen *screen); + void logicalDotsPerInchChanged(qreal dpi); private: typedef QPair DateRange; diff --git a/src/GUI/icons.h b/src/GUI/icons.h index e1b408f2..8e3086f0 100644 --- a/src/GUI/icons.h +++ b/src/GUI/icons.h @@ -20,10 +20,10 @@ #define FULLSCREEN_ICON ":/icons/view-fullscreen.png" // Options dialog icons -#define APPEARANCE_ICON ":/icons/preferences-desktop-display.png" -#define POI_ICON ":/icons/flag_48.png" -#define SYSTEM_ICON ":/icons/system-run.png" -#define PRINT_EXPORT_ICON ":/icons/document-print-preview.png" +#define APPEARANCE_ICON ":/icons/format-stroke-color.png" +#define POI_ICON ":/icons/flag_32.png" +#define SYSTEM_ICON ":/icons/preferences-system.png" +#define PRINT_EXPORT_ICON ":/icons/document-print_32.png" #define DATA_ICON ":/icons/view-filter.png" #endif /* ICONS_H */ diff --git a/src/GUI/infoitem.cpp b/src/GUI/infoitem.cpp index 9de666bd..ed8e3547 100644 --- a/src/GUI/infoitem.cpp +++ b/src/GUI/infoitem.cpp @@ -9,10 +9,6 @@ InfoItem::InfoItem(QGraphicsItem *parent) : QGraphicsItem(parent) { _font.setPixelSize(FONT_SIZE); _font.setFamily(FONT_FAMILY); - -#ifndef Q_OS_MAC - setCacheMode(QGraphicsItem::DeviceCoordinateCache); -#endif // Q_OS_MAC } void InfoItem::updateBoundingRect() diff --git a/src/GUI/mapview.cpp b/src/GUI/mapview.cpp index 3fca1b1a..dc705580 100644 --- a/src/GUI/mapview.cpp +++ b/src/GUI/mapview.cpp @@ -29,7 +29,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) _scene = new QGraphicsScene(this); setScene(_scene); - setCacheMode(QGraphicsView::CacheBackground); setDragMode(QGraphicsView::ScrollHandDrag); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -42,6 +41,10 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) _scene->addItem(_mapScale); _map = map; +#ifdef ENABLE_HIDPI + _ratio = devicePixelRatioF(); + _map->setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI _map->load(); connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap())); @@ -228,7 +231,7 @@ void MapView::updatePOIVisibility() void MapView::rescale() { _scene->setSceneRect(_map->bounds()); - resetCachedContent(); + reloadMap(); for (int i = 0; i < _tracks.size(); i++) _tracks.at(i)->setMap(_map); @@ -265,6 +268,9 @@ void MapView::setMap(Map *map) disconnect(_map, SIGNAL(loaded()), this, SLOT(reloadMap())); _map = map; +#ifdef ENABLE_HIDPI + _map->setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI _map->load(); connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap())); @@ -289,7 +295,7 @@ void MapView::setMap(Map *map) _map->ll2xy(cr.bottomRight())).center(); centerOn(nc); - resetCachedContent(); + reloadMap(); QPixmapCache::clear(); } @@ -498,6 +504,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, // Enter plot mode setUpdatesEnabled(false); _plot = true; +#ifdef ENABLE_HIDPI + _map->setDevicePixelRatio(1.0); +#endif // ENABLE_HIDPI // Compute sizes & ratios orig = viewport()->rect(); @@ -556,6 +565,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, _mapScale->setPos(origPos); // Exit plot mode +#ifdef ENABLE_HIDPI + _map->setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI _plot = false; setUpdatesEnabled(true); } @@ -635,7 +647,7 @@ void MapView::showRouteWaypoints(bool show) void MapView::showMap(bool show) { _showMap = show; - resetCachedContent(); + reloadMap(); } void MapView::showPOI(bool show) @@ -738,13 +750,13 @@ void MapView::setPOIColor(const QColor &color) void MapView::setMapOpacity(int opacity) { _opacity = opacity / 100.0; - resetCachedContent(); + reloadMap(); } void MapView::setBackgroundColor(const QColor &color) { _backgroundColor = color; - resetCachedContent(); + reloadMap(); } void MapView::drawBackground(QPainter *painter, const QRectF &rect) @@ -819,5 +831,44 @@ void MapView::setMarkerColor(const QColor &color) void MapView::reloadMap() { - resetCachedContent(); + _scene->invalidate(); +} + +void MapView::updateDevicePixelRatio() +{ +#ifdef ENABLE_HIDPI + if (_ratio == devicePixelRatioF()) + return; + + _ratio = devicePixelRatioF(); + + QRectF vr(mapToScene(viewport()->rect()).boundingRect() + .intersected(_map->bounds())); + RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight())); + + _map->setDevicePixelRatio(_ratio); + + digitalZoom(0); + + _map->zoomFit(viewport()->rect().size(), cr); + _scene->setSceneRect(_map->bounds()); + + for (int i = 0; i < _tracks.size(); i++) + _tracks.at(i)->setMap(_map); + for (int i = 0; i < _routes.size(); i++) + _routes.at(i)->setMap(_map); + for (int i = 0; i < _waypoints.size(); i++) + _waypoints.at(i)->setMap(_map); + + QHash, WaypointItem*>::const_iterator it; + for (it = _pois.constBegin(); it != _pois.constEnd(); it++) + it.value()->setMap(_map); + updatePOIVisibility(); + + QPointF nc = QRectF(_map->ll2xy(cr.topLeft()), + _map->ll2xy(cr.bottomRight())).center(); + centerOn(nc); + + reloadMap(); +#endif // ENABLE_HIDPI } diff --git a/src/GUI/mapview.h b/src/GUI/mapview.h index a59c4f61..d8d9581a 100644 --- a/src/GUI/mapview.h +++ b/src/GUI/mapview.h @@ -11,6 +11,7 @@ #include "units.h" #include "format.h" #include "palette.h" +#include "config.h" class Data; class POI; @@ -68,6 +69,7 @@ public slots: void showRouteWaypoints(bool show); void clearMapCache(); void setCoordinatesFormat(CoordinatesFormat format); + void updateDevicePixelRatio(); private slots: void updatePOI(); @@ -136,6 +138,10 @@ private: int _digitalZoom; bool _plot; + +#ifdef ENABLE_HIDPI + qreal _ratio; +#endif // ENABLE_HIDPI }; #endif // MAPVIEW_H diff --git a/src/GUI/optionsdialog.cpp b/src/GUI/optionsdialog.cpp index ad67c5b1..aa98b9d8 100644 --- a/src/GUI/optionsdialog.cpp +++ b/src/GUI/optionsdialog.cpp @@ -492,14 +492,14 @@ OptionsDialog::OptionsDialog(Options *options, QWidget *parent) QListWidget *menu = new QListWidget(); menu->setIconSize(QSize(MENU_ICON_SIZE, MENU_ICON_SIZE)); - new QListWidgetItem(QIcon(QPixmap(APP_ICON)), tr("General"), menu); - new QListWidgetItem(QIcon(QPixmap(APPEARANCE_ICON)), tr("Appearance"), + new QListWidgetItem(QIcon(APP_ICON), tr("General"), menu); + new QListWidgetItem(QIcon(APPEARANCE_ICON), tr("Appearance"), menu); - new QListWidgetItem(QIcon(QPixmap(DATA_ICON)), tr("Data"), menu); - new QListWidgetItem(QIcon(QPixmap(POI_ICON)), tr("POI"), menu); - new QListWidgetItem(QIcon(QPixmap(PRINT_EXPORT_ICON)), tr("Print & Export"), + new QListWidgetItem(QIcon(DATA_ICON), tr("Data"), menu); + new QListWidgetItem(QIcon(POI_ICON), tr("POI"), menu); + new QListWidgetItem(QIcon(PRINT_EXPORT_ICON), tr("Print & Export"), menu); - new QListWidgetItem(QIcon(QPixmap(SYSTEM_ICON)), tr("System"), menu); + new QListWidgetItem(QIcon(SYSTEM_ICON), tr("System"), menu); QHBoxLayout *contentLayout = new QHBoxLayout(); contentLayout->addWidget(menu); diff --git a/src/GUI/scaleitem.cpp b/src/GUI/scaleitem.cpp index 94f0188c..573c95fc 100644 --- a/src/GUI/scaleitem.cpp +++ b/src/GUI/scaleitem.cpp @@ -20,10 +20,6 @@ ScaleItem::ScaleItem(QGraphicsItem *parent) : QGraphicsItem(parent) _font.setPixelSize(FONT_SIZE); _font.setFamily(FONT_FAMILY); - -#ifndef Q_OS_MAC - setCacheMode(QGraphicsItem::DeviceCoordinateCache); -#endif // Q_OS_MAC } void ScaleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, diff --git a/src/config.h b/src/config.h index 8b009d83..3f078f44 100644 --- a/src/config.h +++ b/src/config.h @@ -46,8 +46,13 @@ #define TILES_DIR USER_DIR + QString("/tiles") #define TRANSLATIONS_DIR GLOBAL_DIR + QString("/translations") -#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 1)) + +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 1) #define ENABLE_HTTP2 #endif // QT >= 5.10.1 +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) +#define ENABLE_HIDPI +#endif // QT >= 5.6 + #endif /* CONFIG_H */ diff --git a/src/main.cpp b/src/main.cpp index 7854d2c5..45cd957f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,13 @@ #include "GUI/app.h" +#include "config.h" int main(int argc, char *argv[]) { +#ifdef ENABLE_HIDPI + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); +#endif // ENABLE_HIDPI + App app(argc, argv); app.run(); diff --git a/src/map/atlas.cpp b/src/map/atlas.cpp index 076b87b6..db0b914d 100644 --- a/src/map/atlas.cpp +++ b/src/map/atlas.cpp @@ -49,10 +49,7 @@ void Atlas::computeZooms() void Atlas::computeBounds() { - QList offsets; - - for (int i = 0; i < _maps.count(); i++) - offsets.append(QPointF()); + QVector offsets(_maps.count()); for (int z = 0; z < _zooms.count(); z++) { QList m; @@ -62,21 +59,22 @@ void Atlas::computeBounds() qSort(m.begin(), m.end(), xCmp); offsets[_maps.indexOf(m.first())].setX(0); for (int i = 1; i < m.size(); i++) { - qreal w = round(m.first()->pp2xy(TL(m.at(i))).x()); + qreal w = m.first()->pp2xy(TL(m.at(i))).x(); offsets[_maps.indexOf(m.at(i))].setX(w); } qSort(m.begin(), m.end(), yCmp); offsets[_maps.indexOf(m.first())].setY(0); for (int i = 1; i < m.size(); i++) { - qreal h = round(m.first()->pp2xy(TL(m.at(i))).y()); + qreal h = m.first()->pp2xy(TL(m.at(i))).y(); offsets[_maps.indexOf(m.at(i))].setY(h); } } + _bounds = QVector(_maps.count()); for (int i = 0; i < _maps.count(); i++) - _bounds.append(Bounds(RectD(TL(_maps.at(i)), BR(_maps.at(i))), - QRectF(offsets.at(i), _maps.at(i)->bounds().size()))); + _bounds[i] = Bounds(RectD(TL(_maps.at(i)), BR(_maps.at(i))), + QRectF(offsets.at(i), _maps.at(i)->bounds().size())); } Atlas::Atlas(const QString &fileName, QObject *parent) @@ -147,6 +145,14 @@ Atlas::Atlas(const QString &fileName, QObject *parent) _valid = true; } +void Atlas::setDevicePixelRatio(qreal ratio) +{ + for (int i = 0; i < _maps.size(); i++) + _maps[i]->setDevicePixelRatio(ratio); + + computeBounds(); +} + QRectF Atlas::bounds() { QSizeF s(0, 0); diff --git a/src/map/atlas.h b/src/map/atlas.h index fda52370..3008340d 100644 --- a/src/map/atlas.h +++ b/src/map/atlas.h @@ -28,6 +28,7 @@ public: void draw(QPainter *painter, const QRectF &rect, bool block); + void setDevicePixelRatio(qreal ratio); void unload(); bool isValid() const {return _valid;} diff --git a/src/map/jnxmap.cpp b/src/map/jnxmap.cpp index 4c323509..35dbafa7 100644 --- a/src/map/jnxmap.cpp +++ b/src/map/jnxmap.cpp @@ -5,6 +5,7 @@ #include "rectd.h" #include "gcs.h" #include "pcs.h" +#include "config.h" #include "jnxmap.h" @@ -19,8 +20,10 @@ struct Level { struct Ctx { QPainter *painter; QFile *file; + qreal ratio; - Ctx(QPainter *painter, QFile *file) : painter(painter), file(file) {} + Ctx(QPainter *painter, QFile *file, qreal ratio) + : painter(painter), file(file), ratio(ratio) {} }; @@ -139,7 +142,7 @@ bool JNXMap::readTiles() } JNXMap::JNXMap(const QString &fileName, QObject *parent) - : Map(parent), _file(fileName), _zoom(0), _valid(false) + : Map(parent), _file(fileName), _zoom(0), _ratio(1.0), _valid(false) { _name = QFileInfo(fileName).fileName(); @@ -159,13 +162,13 @@ JNXMap::JNXMap(const QString &fileName, QObject *parent) QPointF JNXMap::ll2xy(const Coordinates &c) { const Zoom &z = _zooms.at(_zoom); - return z.transform.proj2img(_projection.ll2xy(c)); + return z.transform.proj2img(_projection.ll2xy(c)) / _ratio; } Coordinates JNXMap::xy2ll(const QPointF &p) { const Zoom &z = _zooms.at(_zoom); - return _projection.xy2ll(z.transform.img2proj(p)); + return _projection.xy2ll(z.transform.img2proj(p * _ratio)); } QRectF JNXMap::bounds() @@ -233,7 +236,11 @@ QPixmap JNXMap::pixmap(const Tile *tile, QFile *file) bool JNXMap::cb(Tile *tile, void *context) { Ctx *ctx = static_cast(context); - ctx->painter->drawPixmap(tile->pos, pixmap(tile, ctx->file)); + QPixmap pm(pixmap(tile, ctx->file)); +#ifdef ENABLE_HIDPI + pm.setDevicePixelRatio(ctx->ratio); +#endif // ENABLE_HIDPI + ctx->painter->drawPixmap(tile->pos / ctx->ratio, pm); return true; } @@ -242,12 +249,13 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, bool block) { Q_UNUSED(block); const RTree &tree = _zooms.at(_zoom).tree; - Ctx ctx(painter, &_file); + Ctx ctx(painter, &_file, _ratio); + QRectF rr(rect.topLeft() * _ratio, rect.size() * _ratio); qreal min[2], max[2]; - min[0] = rect.left(); - min[1] = rect.top(); - max[0] = rect.right(); - max[1] = rect.bottom(); + min[0] = rr.left(); + min[1] = rr.top(); + max[0] = rr.right(); + max[1] = rr.bottom(); tree.Search(min, max, cb, &ctx); } diff --git a/src/map/jnxmap.h b/src/map/jnxmap.h index f616c5cb..c2bd16a3 100644 --- a/src/map/jnxmap.h +++ b/src/map/jnxmap.h @@ -32,6 +32,8 @@ public: void draw(QPainter *painter, const QRectF &rect, bool block); + void setDevicePixelRatio(qreal ratio) {_ratio = ratio;} + bool isValid() const {return _valid;} QString errorString() const {return _errorString;} @@ -61,6 +63,7 @@ private: int _zoom; RectC _bounds; Projection _projection; + qreal _ratio; bool _valid; QString _errorString; diff --git a/src/map/map.h b/src/map/map.h index 7c2bc476..3fe809e4 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -36,6 +36,7 @@ public: virtual void clearCache() {} virtual void load() {} virtual void unload() {} + virtual void setDevicePixelRatio(qreal ratio) {Q_UNUSED(ratio);} virtual bool isValid() const {return true;} virtual QString errorString() const {return QString();} diff --git a/src/map/mapsource.cpp b/src/map/mapsource.cpp index 66b19da2..ac2796f4 100644 --- a/src/map/mapsource.cpp +++ b/src/map/mapsource.cpp @@ -15,7 +15,7 @@ MapSource::Config::Config() : type(OSM), zooms(ZOOM_MIN, ZOOM_MAX), bounds(Coordinates(BOUNDS_LEFT, BOUNDS_TOP), Coordinates(BOUNDS_RIGHT, - BOUNDS_BOTTOM)), format("image/png"), rest(false) {} + BOUNDS_BOTTOM)), format("image/png"), rest(false), tileRatio(1.0) {} static CoordinateSystem coordinateSystem(QXmlStreamReader &reader) @@ -159,6 +159,13 @@ void MapSource::map(QXmlStreamReader &reader, Config &config) attr.value("username").toString(), attr.value("password").toString()); reader.skipCurrentElement(); + } else if (reader.name() == "tilePixelRatio") { + bool res; + qreal val = reader.readElementText().toDouble(&res); + if (!res) + reader.raiseError("Invalid tilePixelRatio"); + else + config.tileRatio = val; } else reader.skipCurrentElement(); } @@ -222,12 +229,13 @@ Map *MapSource::loadMap(const QString &path, QString &errorString) if (config.type == WMTS) return new WMTSMap(config.name, WMTS::Setup(config.url, config.layer, config.set, config.style, config.format, config.rest, - config.coordinateSystem, config.dimensions, config.authorization)); + config.coordinateSystem, config.dimensions, config.authorization), + config.tileRatio); else if (config.type == WMS) return new WMSMap(config.name, WMS::Setup(config.url, config.layer, config.style, config.format, config.crs, config.coordinateSystem, config.dimensions, config.authorization)); else return new OnlineMap(config.name, config.url, config.zooms, - config.bounds, config.authorization); + config.bounds, config.tileRatio, config.authorization); } diff --git a/src/map/mapsource.h b/src/map/mapsource.h index ee38e0bf..f01f7cbb 100644 --- a/src/map/mapsource.h +++ b/src/map/mapsource.h @@ -37,6 +37,7 @@ private: bool rest; QList > dimensions; Authorization authorization; + qreal tileRatio; Config(); }; diff --git a/src/map/offlinemap.cpp b/src/map/offlinemap.cpp index a1f2f8e9..871a88f5 100644 --- a/src/map/offlinemap.cpp +++ b/src/map/offlinemap.cpp @@ -12,6 +12,7 @@ #include "ozf.h" #include "mapfile.h" #include "geotiff.h" +#include "config.h" #include "offlinemap.h" @@ -94,7 +95,7 @@ bool OfflineMap::setTileInfo(const QStringList &tiles, const QString &path) } OfflineMap::OfflineMap(const QString &fileName, QObject *parent) - : Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _valid(false) + : Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _ratio(1.0), _valid(false) { QFileInfo fi(fileName); QString suffix = fi.suffix().toLower(); @@ -172,7 +173,7 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent) } OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent) - : Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _valid(false) + : Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _ratio(1.0), _valid(false) { QFileInfo fi(fileName); QFileInfo map(fi.absolutePath()); @@ -224,8 +225,13 @@ void OfflineMap::load() if (!_ozf && !_img && _map.isValid()) { _img = new QImage(_map.path); - if (_img->isNull()) + if (!_img || _img->isNull()) { qWarning("%s: error loading map image", qPrintable(_map.path)); + return; + } +#ifdef ENABLE_HIDPI + _img->setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI } } @@ -237,15 +243,15 @@ void OfflineMap::unload() void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) const { - QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tile.size.width()) - * _tile.size.width(), (int)floor(rect.top() / _tile.size.height()) - * _tile.size.height()); + QSizeF ts(_tile.size.width() / _ratio, _tile.size.height() / _ratio); + QPointF tl(floor(rect.left() / ts.width()) * ts.width(), + floor(rect.top() / ts.height()) * ts.height()); QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y()); - for (int i = 0; i < ceil(s.width() / _tile.size.width()); i++) { - for (int j = 0; j < ceil(s.height() / _tile.size.height()); j++) { - int x = tl.x() + i * _tile.size.width(); - int y = tl.y() + j * _tile.size.height(); + for (int i = 0; i < ceil(s.width() / ts.width()); i++) { + for (int j = 0; j < ceil(s.height() / ts.height()); j++) { + int x = round(tl.x() * _ratio + i * _tile.size.width()); + int y = round(tl.y() * _ratio + j * _tile.size.height()); QString tileName(_tile.path.arg(QString::number(x), QString::number(y))); @@ -265,23 +271,29 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) const if (pixmap.isNull()) qWarning("%s: error loading tile image", qPrintable( _tile.path.arg(QString::number(x), QString::number(y)))); - else - painter->drawPixmap(QPoint(x, y), pixmap); + else { +#ifdef ENABLE_HIDPI + pixmap.setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI + QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height()); + painter->drawPixmap(tp, pixmap); + } } } } void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) const { - QPoint tl = QPoint((int)floor(rect.left() / _ozf->tileSize().width()) - * _ozf->tileSize().width(), (int)floor(rect.top() - / _ozf->tileSize().height()) * _ozf->tileSize().height()); + QSizeF ts(_ozf->tileSize().width() / _ratio, _ozf->tileSize().height() + / _ratio); + QPointF tl(floor(rect.left() / ts.width()) * ts.width(), + floor(rect.top() / ts.height()) * ts.height()); QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y()); - for (int i = 0; i < ceil(s.width() / _ozf->tileSize().width()); i++) { - for (int j = 0; j < ceil(s.height() / _ozf->tileSize().height()); j++) { - int x = tl.x() + i * _ozf->tileSize().width(); - int y = tl.y() + j * _ozf->tileSize().height(); + for (int i = 0; i < ceil(s.width() / ts.width()); i++) { + for (int j = 0; j < ceil(s.height() / ts.height()); j++) { + int x = round(tl.x() * _ratio + i * _ozf->tileSize().width()); + int y = round(tl.y() * _ratio + j * _ozf->tileSize().height()); QPixmap pixmap; QString key = _ozf->fileName() + "/" + QString::number(_zoom) + "_" @@ -294,17 +306,21 @@ void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) const if (pixmap.isNull()) qWarning("%s: error loading tile image", qPrintable(key)); - else - painter->drawPixmap(QPoint(x, y), pixmap); + else { +#ifdef ENABLE_HIDPI + pixmap.setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI + QPointF tp(tl.x() + i * ts.width(), tl.y() + j * ts.height()); + painter->drawPixmap(tp, pixmap); + } } } } void OfflineMap::drawImage(QPainter *painter, const QRectF &rect) const { - QRect r(rect.toRect()); - painter->drawImage(r.left(), r.top(), *_img, r.left(), r.top(), - r.width(), r.height()); + painter->drawImage(rect.topLeft(), *_img, QRectF(rect.topLeft() * _ratio, + rect.size() * _ratio)); } void OfflineMap::draw(QPainter *painter, const QRectF &rect, bool block) @@ -322,22 +338,24 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect, bool block) QPointF OfflineMap::ll2xy(const Coordinates &c) { QPointF p(_transform.proj2img(_projection.ll2xy(c))); - return _ozf ? QPointF(p.x() * _scale.x(), p.y() * _scale.y()) : p; + return _ozf + ? QPointF(p.x() * _scale.x(), p.y() * _scale.y()) / _ratio + : p / _ratio; } Coordinates OfflineMap::xy2ll(const QPointF &p) { return _ozf ? _projection.xy2ll(_transform.img2proj(QPointF(p.x() / _scale.x(), - p.y() / _scale.y()))) - : _projection.xy2ll(_transform.img2proj(p)); + p.y() / _scale.y()) * _ratio)) + : _projection.xy2ll(_transform.img2proj(p * _ratio)); } QRectF OfflineMap::bounds() { return _ozf - ? QRectF(QPointF(0, 0), _ozf->size(_zoom)) - : QRectF(QPointF(0, 0), _map.size); + ? QRectF(QPointF(0, 0), _ozf->size(_zoom) / _ratio) + : QRectF(QPointF(0, 0), _map.size / _ratio); } int OfflineMap::zoomFit(const QSize &size, const RectC &rect) diff --git a/src/map/offlinemap.h b/src/map/offlinemap.h index 4b7abefd..604bfb62 100644 --- a/src/map/offlinemap.h +++ b/src/map/offlinemap.h @@ -33,6 +33,7 @@ public: void draw(QPainter *painter, const QRectF &rect, bool block); + void setDevicePixelRatio(qreal ratio) {_ratio = ratio;} void load(); void unload(); @@ -42,9 +43,9 @@ public: PointD ll2pp(const Coordinates &c) const {return _projection.ll2xy(c);} PointD xy2pp(const QPointF &p) const - {return _transform.img2proj(p);} + {return _transform.img2proj(p * _ratio);} QPointF pp2xy(const PointD &p) const - {return _transform.proj2img(p);} + {return _transform.proj2img(p) / _ratio;} private: struct ImageInfo { @@ -72,6 +73,7 @@ private: ImageInfo _map, _tile; int _zoom; QPointF _scale; + qreal _ratio; bool _valid; QString _errorString; diff --git a/src/map/onlinemap.cpp b/src/map/onlinemap.cpp index bf8cc31a..52be8800 100644 --- a/src/map/onlinemap.cpp +++ b/src/map/onlinemap.cpp @@ -42,14 +42,13 @@ static int scale2zoom(qreal scale) OnlineMap::OnlineMap(const QString &name, const QString &url, - const Range &zooms, const RectC &bounds, const Authorization &authorization, - QObject *parent) : Map(parent), _name(name), _zooms(zooms), _bounds(bounds), - _valid(false) + const Range &zooms, const RectC &bounds, qreal tileRatio, + const Authorization &authorization, QObject *parent) + : Map(parent), _name(name), _zooms(zooms), _bounds(bounds), + _zoom(_zooms.max()), _deviceRatio(1.0), _tileRatio(tileRatio), _valid(false) { QString dir(TILES_DIR + "/" + _name); - _zoom = _zooms.max(); - _tileLoader = new TileLoader(this); _tileLoader->setUrl(url); _tileLoader->setDir(dir); @@ -86,7 +85,7 @@ int OnlineMap::zoomFit(const QSize &size, const RectC &rect) else { QRectF tbr(ll2m(rect.topLeft()), ll2m(rect.bottomRight())); QPointF sc(tbr.width() / size.width(), tbr.height() / size.height()); - _zoom = limitZoom(scale2zoom(qMax(sc.x(), -sc.y()))); + _zoom = limitZoom(scale2zoom(qMax(sc.x(), -sc.y()) / coordinatesRatio())); } return _zoom; @@ -112,19 +111,34 @@ int OnlineMap::zoomOut() return _zoom; } +qreal OnlineMap::coordinatesRatio() const +{ + return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0; +} + +qreal OnlineMap::imageRatio() const +{ + return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio; +} + +qreal OnlineMap::tileSize() const +{ + return (TILE_SIZE / coordinatesRatio()); +} + void OnlineMap::draw(QPainter *painter, const QRectF &rect, bool block) { qreal scale = zoom2scale(_zoom); QPoint tile = mercator2tile(QPointF(rect.topLeft().x() * scale, - -rect.topLeft().y() * scale), _zoom); - QPoint tl = QPoint((int)floor(rect.left() / (qreal)TILE_SIZE) - * TILE_SIZE, (int)floor(rect.top() / TILE_SIZE) * TILE_SIZE); + -rect.topLeft().y() * scale) * coordinatesRatio(), _zoom); + QPointF tl(floor(rect.left() / tileSize()) + * tileSize(), floor(rect.top() / tileSize()) * tileSize()); QList tiles; QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y()); - for (int i = 0; i < ceil(s.width() / TILE_SIZE); i++) - for (int j = 0; j < ceil(s.height() / TILE_SIZE); j++) + for (int i = 0; i < ceil(s.width() / tileSize()); i++) + for (int j = 0; j < ceil(s.height() / tileSize()); j++) tiles.append(Tile(QPoint(tile.x() + i, tile.y() + j), _zoom)); if (block) @@ -134,10 +148,14 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, bool block) for (int i = 0; i < tiles.count(); i++) { Tile &t = tiles[i]; - QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE, - tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE); - if (!t.pixmap().isNull()) + QPointF tp(tl.x() + (t.xy().x() - tile.x()) * tileSize(), + tl.y() + (t.xy().y() - tile.y()) * tileSize()); + if (!t.pixmap().isNull()) { +#ifdef ENABLE_HIDPI + t.pixmap().setDevicePixelRatio(imageRatio()); +#endif // ENABLE_HIDPI painter->drawPixmap(tp, t.pixmap()); + } } } @@ -145,11 +163,11 @@ QPointF OnlineMap::ll2xy(const Coordinates &c) { qreal scale = zoom2scale(_zoom); QPointF m = ll2m(c); - return QPointF(m.x() / scale, m.y() / -scale); + return QPointF(m.x() / scale, m.y() / -scale) / coordinatesRatio(); } Coordinates OnlineMap::xy2ll(const QPointF &p) { qreal scale = zoom2scale(_zoom); - return m2ll(QPointF(p.x() * scale, -p.y() * scale)); + return m2ll(QPointF(p.x() * scale, -p.y() * scale) * coordinatesRatio()); } diff --git a/src/map/onlinemap.h b/src/map/onlinemap.h index f87e5143..4620e5fb 100644 --- a/src/map/onlinemap.h +++ b/src/map/onlinemap.h @@ -12,7 +12,7 @@ class OnlineMap : public Map public: OnlineMap(const QString &name, const QString &url, const Range &zooms, - const RectC &bounds, const Authorization &authorization, + const RectC &bounds, qreal tileRatio, const Authorization &authorization, QObject *parent = 0); QString name() const {return _name;} @@ -31,6 +31,7 @@ public: void draw(QPainter *painter, const QRectF &rect, bool block); + void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;} void clearCache() {_tileLoader->clearCache();} bool isValid() const {return _valid;} @@ -38,12 +39,16 @@ public: private: int limitZoom(int zoom) const; + qreal tileSize() const; + qreal coordinatesRatio() const; + qreal imageRatio() const; TileLoader *_tileLoader; QString _name; Range _zooms; RectC _bounds; int _zoom; + qreal _deviceRatio, _tileRatio; bool _valid; QString _errorString; diff --git a/src/map/wmsmap.cpp b/src/map/wmsmap.cpp index 37ca585e..a92c1a20 100644 --- a/src/map/wmsmap.cpp +++ b/src/map/wmsmap.cpp @@ -103,7 +103,7 @@ bool WMSMap::loadWMS() WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, QObject *parent) : Map(parent), _name(name), _setup(setup), _tileLoader(0), _zoom(0), - _valid(false) + _ratio(1.0), _valid(false) { if (!QDir().mkpath(tilesDir())) { _errorString = "Error creating tiles dir"; @@ -129,8 +129,8 @@ void WMSMap::clearCache() QRectF WMSMap::bounds() { - return QRectF(_transform.proj2img(_bbox.topLeft()), - _transform.proj2img(_bbox.bottomRight())); + return QRectF(_transform.proj2img(_bbox.topLeft()) / _ratio, + _transform.proj2img(_bbox.bottomRight()) / _ratio); } int WMSMap::zoomFit(const QSize &size, const RectC &rect) @@ -146,7 +146,7 @@ int WMSMap::zoomFit(const QSize &size, const RectC &rect) _zoom = 0; for (int i = 0; i < _zooms.size(); i++) { - if (sd2res(_zooms.at(i)) < resolution) + if (sd2res(_zooms.at(i)) < resolution / _ratio) break; _zoom = i; } @@ -179,20 +179,25 @@ int WMSMap::zoomOut() QPointF WMSMap::ll2xy(const Coordinates &c) { - return _transform.proj2img(_projection.ll2xy(c)); + return _transform.proj2img(_projection.ll2xy(c)) / _ratio; } Coordinates WMSMap::xy2ll(const QPointF &p) { - return _projection.xy2ll(_transform.img2proj(p)); + return _projection.xy2ll(_transform.img2proj(p * _ratio)); +} + +qreal WMSMap::tileSize() const +{ + return (TILE_SIZE / _ratio); } void WMSMap::draw(QPainter *painter, const QRectF &rect, bool block) { - QPoint tl = QPoint((int)floor(rect.left() / (qreal)TILE_SIZE), - (int)floor(rect.top() / (qreal)TILE_SIZE)); - QPoint br = QPoint((int)ceil(rect.right() / (qreal)TILE_SIZE), - (int)ceil(rect.bottom() / (qreal)TILE_SIZE)); + QPoint tl = QPoint((int)floor(rect.left() / tileSize()), + (int)floor(rect.top() / tileSize())); + QPoint br = QPoint((int)ceil(rect.right() / tileSize()), + (int)ceil(rect.bottom() / tileSize())); QList tiles; for (int i = tl.x(); i < br.x(); i++) { @@ -216,8 +221,12 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, bool block) for (int i = 0; i < tiles.count(); i++) { Tile &t = tiles[i]; - QPoint tp(t.xy().x() * TILE_SIZE, t.xy().y() * TILE_SIZE); - if (!t.pixmap().isNull()) + QPointF tp(t.xy().x() * tileSize(), t.xy().y() * tileSize()); + if (!t.pixmap().isNull()) { +#ifdef ENABLE_HIDPI + t.pixmap().setDevicePixelRatio(_ratio); +#endif // ENABLE_HIDPI painter->drawPixmap(tp, t.pixmap()); + } } } diff --git a/src/map/wmsmap.h b/src/map/wmsmap.h index 9e70b50a..d2d5e061 100644 --- a/src/map/wmsmap.h +++ b/src/map/wmsmap.h @@ -31,6 +31,7 @@ public: void draw(QPainter *painter, const QRectF &rect, bool block); + void setDevicePixelRatio(qreal ratio) {_ratio = ratio;} void clearCache(); bool isValid() const {return _valid;} @@ -43,6 +44,7 @@ private: void computeZooms(const RangeF &scaleDenominator); void updateTransform(); bool loadWMS(); + qreal tileSize() const; QString _name; @@ -54,6 +56,7 @@ private: QVector _zooms; RectD _bbox; int _zoom; + qreal _ratio; bool _valid; QString _errorString; diff --git a/src/map/wmtsmap.cpp b/src/map/wmtsmap.cpp index 611f7850..342509e5 100644 --- a/src/map/wmtsmap.cpp +++ b/src/map/wmtsmap.cpp @@ -35,9 +35,9 @@ bool WMTSMap::loadWMTS() return true; } -WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, QObject *parent) - : Map(parent), _name(name), _setup(setup), _tileLoader(0), _zoom(0), - _valid(false) +WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, qreal tileRatio, + QObject *parent) : Map(parent), _name(name), _setup(setup), _tileLoader(0), + _zoom(0), _deviceRatio(1.0), _tileRatio(tileRatio), _valid(false) { if (!QDir().mkpath(tilesDir())) { _errorString = "Error creating tiles dir"; @@ -105,7 +105,6 @@ QRectF WMTSMap::bounds() bounds = _bounds.isValid() ? QRectF(ll2xy(_bounds.topLeft()), ll2xy(_bounds.bottomRight())) : QRectF(); - return _bounds.isValid() ? tileBounds.intersected(bounds) : tileBounds; } @@ -122,7 +121,8 @@ int WMTSMap::zoomFit(const QSize &size, const RectC &rect) _zoom = 0; for (int i = 0; i < _zooms.size(); i++) { - if (sd2res(_zooms.at(i).scaleDenominator()) < resolution) + if (sd2res(_zooms.at(i).scaleDenominator()) < resolution + / coordinatesRatio()) break; _zoom = i; } @@ -153,13 +153,31 @@ int WMTSMap::zoomOut() return _zoom; } +qreal WMTSMap::coordinatesRatio() const +{ + return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0; +} + +qreal WMTSMap::imageRatio() const +{ + return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio; +} + +QSizeF WMTSMap::tileSize(const WMTS::Zoom &zoom) const +{ + return QSizeF(zoom.tile().width() / coordinatesRatio(), + zoom.tile().height() / coordinatesRatio()); +} + void WMTSMap::draw(QPainter *painter, const QRectF &rect, bool block) { const WMTS::Zoom &z = _zooms.at(_zoom); - QPoint tl = QPoint((int)floor(rect.left() / (qreal)z.tile().width()), - (int)floor(rect.top() / (qreal)z.tile().height())); - QPoint br = QPoint((int)ceil(rect.right() / (qreal)z.tile().width()), - (int)ceil(rect.bottom() / (qreal)z.tile().height())); + QSizeF ts(tileSize(z)); + + QPoint tl = QPoint((int)floor(rect.left() / ts.width()), + (int)floor(rect.top() / ts.height())); + QPoint br = QPoint((int)ceil(rect.right() / ts.width()), + (int)ceil(rect.bottom() / ts.height())); QList tiles; for (int i = tl.x(); i < br.x(); i++) @@ -173,18 +191,22 @@ void WMTSMap::draw(QPainter *painter, const QRectF &rect, bool block) for (int i = 0; i < tiles.count(); i++) { Tile &t = tiles[i]; - QPoint tp(t.xy().x() * z.tile().width(), t.xy().y() * z.tile().height()); - if (!t.pixmap().isNull()) + QPointF tp(t.xy().x() * ts.width(), t.xy().y() * ts.height()); + if (!t.pixmap().isNull()) { +#ifdef ENABLE_HIDPI + t.pixmap().setDevicePixelRatio(imageRatio()); +#endif // ENABLE_HIDPI painter->drawPixmap(tp, t.pixmap()); + } } } QPointF WMTSMap::ll2xy(const Coordinates &c) { - return _transform.proj2img(_projection.ll2xy(c)); + return _transform.proj2img(_projection.ll2xy(c)) / coordinatesRatio(); } Coordinates WMTSMap::xy2ll(const QPointF &p) { - return _projection.xy2ll(_transform.img2proj(p)); + return _projection.xy2ll(_transform.img2proj(p * coordinatesRatio())); } diff --git a/src/map/wmtsmap.h b/src/map/wmtsmap.h index 8fd22a0b..b1db5ce3 100644 --- a/src/map/wmtsmap.h +++ b/src/map/wmtsmap.h @@ -13,7 +13,8 @@ class WMTSMap : public Map Q_OBJECT public: - WMTSMap(const QString &name, const WMTS::Setup &setup, QObject *parent = 0); + WMTSMap(const QString &name, const WMTS::Setup &setup, qreal tileRatio, + QObject *parent = 0); QString name() const {return _name;} @@ -30,6 +31,7 @@ public: void draw(QPainter *painter, const QRectF &rect, bool block); + void setDevicePixelRatio(qreal ratio) {_deviceRatio = ratio;} void clearCache(); bool isValid() const {return _valid;} @@ -40,6 +42,9 @@ private: double sd2res(double scaleDenominator) const; QString tilesDir() const; void updateTransform(); + QSizeF tileSize(const WMTS::Zoom &zoom) const; + qreal coordinatesRatio() const; + qreal imageRatio() const; QString _name; WMTS::Setup _setup; @@ -50,6 +55,7 @@ private: Transform _transform; CoordinateSystem _cs; int _zoom; + qreal _deviceRatio, _tileRatio; bool _valid; QString _errorString;