Skip to content

Commit 3386543

Browse files
committed
Initial Qt basemap plugin commit
0 parents  commit 3386543

16 files changed

+1096
-0
lines changed

CMakeLists.txt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
project(QtBasemapPlugin VERSION 1.0.0 LANGUAGES CXX)
3+
4+
set(LIB_NAME qtgeoservices_basemap_pix4d)
5+
set(PACKAGE_NAME QtBasemapPlugin)
6+
7+
if (NOT ${BUILD_SHARED_LIBS})
8+
message(STATUS " ***** Build plugin as static library *****")
9+
set(DEFINES "-DQT_STATICPLUGIN -DQT_PLUGIN")
10+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DEFINES}")
11+
set(CXXFLAGS "${CXXFLAGS} ${DEFINES}")
12+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEFINES}")
13+
endif()
14+
15+
find_package(Qt5 COMPONENTS
16+
Core
17+
Gui
18+
OpenGL
19+
Quick
20+
Xml
21+
Positioning
22+
Location
23+
Network
24+
REQUIRED QUIET)
25+
26+
set(SOURCES
27+
src/GeoServiceProviderPlugin.cpp
28+
src/GeoTiledMappingManagerEngine.cpp
29+
src/GeoTileFetcher.cpp
30+
src/GeoMapReply.cpp
31+
src/GeoFileTileCache.cpp
32+
33+
src/GeoServiceProviderPlugin.h
34+
src/GeoTiledMappingManagerEngine.h
35+
src/GeoTileFetcher.h
36+
src/GeoMapReply.h
37+
src/GeoFileTileCache.h
38+
)
39+
40+
add_library(${LIB_NAME} ${SOURCES} )
41+
set_target_properties(${LIB_NAME} PROPERTIES AUTORCC ON AUTOMOC ON)
42+
43+
target_link_libraries(${LIB_NAME} PRIVATE
44+
Qt5::Core
45+
Qt5::Gui
46+
Qt5::Quick
47+
Qt5::Positioning
48+
Qt5::Xml
49+
Qt5::Location
50+
Qt5::LocationPrivate
51+
Qt5::Network
52+
Qt5::OpenGL
53+
)
54+
55+
target_include_directories(${LIB_NAME} INTERFACE
56+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
57+
PRIVATE src
58+
${Qt5Location_PRIVATE_INCLUDE_DIRS}
59+
)
60+
61+
target_compile_features(${LIB_NAME} PRIVATE cxx_std_14)
62+
63+
install(TARGETS ${LIB_NAME} EXPORT ${PACKAGE_NAME}Config
64+
LIBRARY DESTINATION plugins/geoservices
65+
RUNTIME DESTINATION plugins/geoservices
66+
ARCHIVE DESTINATION lib
67+
)
68+
69+
install(EXPORT ${PACKAGE_NAME}Config DESTINATION share/${PACKAGE_NAME}/cmake)

conanfile.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from conans import CMake, ConanFile, tools
2+
import os
3+
4+
5+
class QtBasemapPluginConan(ConanFile):
6+
name = 'QtBasemapPlugin'
7+
version = '1.0.1-2'
8+
license = 'LGPL3'
9+
url = 'http://code.qt.io/cgit/qt/qtlocation.git/tree/src/plugins/geoservices/mapbox?h=5.10'
10+
description = 'Qt GeoServices plugin for basemaps including MapBox'
11+
options = {'shared': [True, False]}
12+
default_options = 'shared=True'
13+
settings = 'os', 'compiler', 'build_type', 'arch'
14+
generators = 'cmake'
15+
exports_sources = ['CMakeLists.txt', 'src/*']
16+
17+
def build(self):
18+
cmake = CMake(self, parallel=True)
19+
cmake_args = {
20+
'-DBUILD_SHARED_LIBS=': 'ON' if self.options.shared else 'OFF'
21+
}
22+
23+
if(tools.cross_building(self.settings) and
24+
str(self.settings.os).lower() == 'android'):
25+
# this is a workaround for the lack of proper Android support from Conan
26+
# see https://github.com/conan-io/conan/issues/2856#issuecomment-421036768
27+
cmake.definitions["CONAN_LIBCXX"] = ""
28+
29+
cmake.configure(source_dir='..', build_dir='build', defs=cmake_args)
30+
cmake.build(target='install')
31+
32+
def configure(self):
33+
del self.settings.compiler.libcxx
34+
35+
def package_info(self):
36+
self.cpp_info.libs = ["qtgeoservices_basemap_pix4d"]
37+
self.cpp_info.includedirs = ['include']
38+
self.cpp_info.libdirs += ['plugins/geoservices/']
39+
self.cpp_info.builddirs += ['share/QtMapboxPlugin/cmake']

src/GeoFileTileCache.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#include "GeoFileTileCache.h"
2+
3+
#include <QDir>
4+
#include <QtLocation/private/qgeotilespec_p.h>
5+
6+
GeoFileTileCache::GeoFileTileCache(const QList<QGeoMapType>& mapTypes,
7+
int scaleFactor,
8+
const QString& directory,
9+
QObject* parent)
10+
: QGeoFileTileCache(directory, parent)
11+
, m_hasCacheDirectory(!directory.isEmpty())
12+
, m_mapTypes(mapTypes)
13+
{
14+
m_scaleFactor = qBound(1, scaleFactor, 2);
15+
for (int i = 0; i < mapTypes.size(); i++)
16+
{
17+
m_mapNameToId.insert(mapTypes[i].name(), i + 1);
18+
}
19+
}
20+
21+
QString GeoFileTileCache::tileSpecToFilename(const QGeoTileSpec& spec,
22+
const QString& format,
23+
const QString& directory) const
24+
{
25+
if (!m_hasCacheDirectory)
26+
{
27+
return QString();
28+
}
29+
30+
QString filename = spec.plugin();
31+
32+
filename += QLatin1String("-");
33+
filename += m_mapTypes[spec.mapId() - 1].name();
34+
filename += QLatin1String("-");
35+
filename += QString::number(spec.zoom());
36+
filename += QLatin1String("-");
37+
filename += QString::number(spec.x());
38+
filename += QLatin1String("-");
39+
filename += QString::number(spec.y());
40+
41+
if (spec.version() != -1)
42+
{
43+
filename += QLatin1String("-");
44+
filename += QString::number(spec.version());
45+
}
46+
47+
filename += QLatin1String("-@");
48+
filename += QString::number(m_scaleFactor);
49+
filename += QLatin1Char('x');
50+
filename += QLatin1String(".");
51+
filename += format;
52+
53+
return QDir(directory).filePath(filename);
54+
}
55+
56+
QGeoTileSpec GeoFileTileCache::filenameToTileSpec(const QString& filename) const
57+
{
58+
// @See QGeoFileTileCacheMapBox for more information for this function
59+
// General scheme is: plugin_name - map_type - zoom - x - y - @scale.png
60+
// For now the cached tiles names look like this:
61+
62+
63+
// basemap_pix4d_100 = plugin name
64+
// mapbox.streets-satellite / mapbox.satellite = map type
65+
// 13 = zoom
66+
// 4401-2685 = x, y
67+
68+
if (!m_hasCacheDirectory)
69+
{
70+
return QGeoTileSpec();
71+
}
72+
73+
const QStringList parts = filename.split('.');
74+
if (parts.length() != 3) // 3 because the map name has always a dot in it.
75+
{
76+
return QGeoTileSpec();
77+
}
78+
79+
// name = mapbox_pix4d_100-mapbox.streets-satellite-13-4401-2685-@2x (no extension)
80+
const QString name = parts.at(0) + "." + parts.at(1);
81+
const QStringList fields = name.split('-');
82+
83+
// must be at least 6 different fields
84+
if (fields.length() < 6)
85+
{
86+
return QGeoTileSpec();
87+
}
88+
89+
const int length = fields.length();
90+
const int scaleIdx = fields.last().indexOf("@");
91+
if (scaleIdx < 0 || fields.last().size() <= (scaleIdx + 2))
92+
{
93+
return QGeoTileSpec();
94+
}
95+
96+
int scaleFactor = fields.last()[scaleIdx + 1].digitValue();
97+
if (scaleFactor != m_scaleFactor)
98+
{
99+
return QGeoTileSpec();
100+
}
101+
102+
QList<int> numbers;
103+
int startIndex = 2;
104+
105+
// try to combine the fields from [1] and [2]. In case the map type
106+
// contains a '-' in it (e.g. mapbox.streets-satellite vs mapbox.satellite)
107+
QString pluginName = fields.at(1);
108+
if (m_mapNameToId.find(pluginName + "-" + fields.at(2)) != m_mapNameToId.end())
109+
{
110+
pluginName += "-" + fields.at(2);
111+
startIndex = 3;
112+
}
113+
114+
for (int i = startIndex; i < length - 1; ++i) // skipping -@_X
115+
{
116+
bool ok = false;
117+
const int value = fields.at(i).toInt(&ok);
118+
if (!ok)
119+
{
120+
return QGeoTileSpec();
121+
}
122+
numbers.append(value);
123+
}
124+
125+
if (numbers.length() < 3)
126+
{
127+
return QGeoTileSpec();
128+
}
129+
130+
// File name without version, append default
131+
if (numbers.length() < 4)
132+
{
133+
numbers.append(-1);
134+
}
135+
136+
return QGeoTileSpec(
137+
fields.at(0), m_mapNameToId[pluginName], numbers.at(0), numbers.at(1), numbers.at(2), numbers.at(3));
138+
}

src/GeoFileTileCache.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#include <QtLocation/private/qgeofiletilecache_p.h>
4+
#include <QMap>
5+
6+
class GeoFileTileCache : public QGeoFileTileCache
7+
{
8+
Q_OBJECT
9+
10+
public:
11+
GeoFileTileCache(const QList<QGeoMapType>& mapTypes, int scaleFactor, const QString& directory = QString(), QObject* parent = nullptr);
12+
13+
protected:
14+
QString tileSpecToFilename(const QGeoTileSpec& spec, const QString& format, const QString& directory) const override;
15+
QGeoTileSpec filenameToTileSpec(const QString& filename) const override;
16+
17+
bool m_hasCacheDirectory{false};
18+
QList<QGeoMapType> m_mapTypes;
19+
QMap<QString, int> m_mapNameToId;
20+
int m_scaleFactor{0};
21+
};

src/GeoMapReply.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include "GeoMapReply.h"
2+
3+
#include <QtLocation/private/qgeotilespec_p.h>
4+
5+
GeoMapReply::GeoMapReply(QNetworkReply* reply,
6+
const QGeoTileSpec& spec,
7+
const QString& format,
8+
bool enableLogging,
9+
QObject* parent)
10+
: QGeoTiledMapReply(spec, parent)
11+
, m_format(format)
12+
, m_enableLogging(enableLogging)
13+
{
14+
if (!reply)
15+
{
16+
setError(UnknownError, QStringLiteral("Null reply"));
17+
if (m_enableLogging)
18+
{
19+
qWarning() << "GeoMapReply: " << errorString();
20+
}
21+
}
22+
else
23+
{
24+
// Cannot use qOverload for Windows: https://bugreports.qt.io/browse/QTBUG-61667
25+
void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = &QNetworkReply::error;
26+
27+
connect(reply, &QNetworkReply::finished, this, &GeoMapReply::networkReplyFinished);
28+
connect(reply, errorSignal, this, &GeoMapReply::networkReplyError);
29+
connect(this, &QGeoTiledMapReply::aborted, reply, &QNetworkReply::abort);
30+
connect(this, &QObject::destroyed, reply, &QObject::deleteLater);
31+
}
32+
}
33+
34+
void GeoMapReply::networkReplyFinished()
35+
{
36+
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
37+
reply->deleteLater();
38+
39+
if (reply->error() != QNetworkReply::NoError)
40+
{
41+
if (m_enableLogging)
42+
{
43+
qWarning() << "GeoMapReply: " << reply->errorString();
44+
}
45+
}
46+
else
47+
{
48+
setMapImageData(reply->readAll());
49+
setMapImageFormat(m_format);
50+
setFinished(true);
51+
}
52+
}
53+
54+
void GeoMapReply::networkReplyError(QNetworkReply::NetworkError error)
55+
{
56+
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
57+
reply->deleteLater();
58+
59+
if (error == QNetworkReply::OperationCanceledError)
60+
{
61+
setFinished(true);
62+
}
63+
else
64+
{
65+
if (m_enableLogging)
66+
{
67+
qWarning() << "GeoMapReply: " << reply->errorString();
68+
}
69+
setError(QGeoTiledMapReply::CommunicationError, reply->errorString());
70+
}
71+
}

src/GeoMapReply.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <QtLocation/private/qgeotiledmapreply_p.h>
4+
#include <QtNetwork/QNetworkReply>
5+
6+
class GeoMapReply : public QGeoTiledMapReply
7+
{
8+
Q_OBJECT
9+
10+
public:
11+
GeoMapReply(QNetworkReply* reply,
12+
const QGeoTileSpec& spec,
13+
const QString& format,
14+
bool enableLogging,
15+
QObject* parent = nullptr);
16+
17+
private slots:
18+
void networkReplyFinished();
19+
void networkReplyError(QNetworkReply::NetworkError error);
20+
21+
private:
22+
QString m_format;
23+
bool m_enableLogging{false};
24+
};

0 commit comments

Comments
 (0)