3#include <QtCore/QApplicationStatic>
5#include <QtCore/QDirIterator>
6#include <QtCore/QRegularExpression>
7#include <QtCore/QSettings>
8#include <QtCore/QStorageInfo>
9#include <QtCore/QTemporaryDir>
10#include <QtQml/QQmlEngine>
26using namespace Qt::StringLiterals;
34 return _mapEngineManager();
41 qCDebug(QGCMapEngineManagerLog) <<
this;
43 (void) qmlRegisterUncreatableType<QGCMapEngineManager>(
"QGroundControl.QGCMapEngineManager", 1, 0,
"QGCMapEngineManager",
"Reference only");
52 qCDebug(QGCMapEngineManagerLog) <<
this;
59 _bottomRightLat = lat1;
60 _bottomRightLon = lon1;
65 _elevationSet.
clear();
67 for (
int z = minZoom; z <= maxZoom; z++) {
72 if (_fetchElevation) {
81 qCDebug(QGCMapEngineManagerLog) << lat0 << lon0 << lat1 << lon1 << minZoom << maxZoom;
96 if (_tileSets->
count() > 0) {
111 if (tileSet->
type() == QStringLiteral(
"Invalid")) {
116 _tileSets->
append(tileSet);
142 qCWarning(QGCMapEngineManagerLog) <<
"No Tiles to save";
158 set->
setType(elevationProviderName);
167 qCWarning(QGCMapEngineManagerLog) <<
"No Tiles to save";
173 qCDebug(QGCMapEngineManagerLog) <<
"New tile set saved (" << set->
name() <<
"). Starting download...";
183 settings.beginGroup(kQmlOfflineMapKeyName);
184 settings.setValue(key, value);
190 settings.beginGroup(kQmlOfflineMapKeyName);
191 return settings.value(key, defaultValue).toString();
196 QStringList mapStringList =
mapList();
197 mapStringList = mapStringList.filter(QRegularExpression(provider));
199 static const QRegularExpression providerType = QRegularExpression(uR
"(^([^\ ]*) (.*)$)"_s);
200 (void) mapStringList.replaceInStrings(providerType, "\\2");
201 (void) mapStringList.removeDuplicates();
203 return mapStringList;
208 qCDebug(QGCMapEngineManagerLog) <<
"Deleting tile set" << tileSet->
name();
211 for (qsizetype i = 0; i < _tileSets->
count(); i++ ) {
239 QString name = newName;
241 name = QString(
"%1 (%2)").arg(newName).arg(idx++);
244 qCDebug(QGCMapEngineManagerLog) <<
"Renaming tile set" << tileSet->
name() <<
"to" << name;
255void QGCMapEngineManager::_tileSetDeleted(quint64 setID)
257 for (qsizetype i = 0; i < _tileSets->
count(); i++ ) {
259 if (set && (set->
id() == setID)) {
273 task = QStringLiteral(
"Fetch Tile Set");
276 task = QStringLiteral(
"Create Tile Set");
279 task = QStringLiteral(
"Get Tile Download List");
282 task = QStringLiteral(
"Update Tile Download Status");
285 task = QStringLiteral(
"Delete Tile Set");
288 task = QStringLiteral(
"Reset Tile Sets");
291 task = QStringLiteral(
"Export Tile Sets");
294 task = QStringLiteral(
"Database Error");
298 QString serror = QStringLiteral(
"Error in task: ") + task;
299 serror += QStringLiteral(
"\nError description:\n");
304 qCWarning(QGCMapEngineManagerLog) << serror;
307void QGCMapEngineManager::_updateTotals(quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize)
309 for (qsizetype i = 0; i < _tileSets->
count(); i++) {
323 for (qsizetype i = 0; i < _tileSets->
count(); i++) {
324 const QGCCachedTileSet*
const set = qobject_cast<const QGCCachedTileSet*>(_tileSets->
get(i));
325 if (set && (set->
name() == name)) {
335 for (qsizetype i = 0; i < _tileSets->
count(); i++) {
345 for (qsizetype i = 0; i < _tileSets->
count(); i++) {
357 for (qsizetype i = 0; i < _tileSets->
count(); i++) {
358 const QGCCachedTileSet*
const set = qobject_cast<const QGCCachedTileSet*>(_tileSets->
get(i));
371 if (path.isEmpty()) {
393 if (path.isEmpty()) {
397 QList<TileSetRecord> records;
399 for (qsizetype i = 0; i < _tileSets->
count(); i++) {
420 if (records.isEmpty()) {
438void QGCMapEngineManager::_actionCompleted()
452 const QString name = QStringLiteral(
"Tile Set ") + QString::asprintf(
"%03d", count++);
466 QStringList mapStringList =
mapList();
468 for (
const QString &elevationProviderName : elevationStringList) {
469 (void) mapStringList.removeAll(elevationProviderName);
472 static const QRegularExpression providerType = QRegularExpression(uR
"(^([^\ ]*) (.*)$)"_s);
473 (void) mapStringList.replaceInStrings(providerType, "\\1");
474 (void) mapStringList.removeDuplicates();
476 return mapStringList;
486 if (archivePath.isEmpty()) {
491 if (!QFile::exists(archivePath)) {
497 setErrorMessage(tr(
"Not a supported archive format: %1").arg(archivePath));
506 const QString tempPath = QDir::temp().filePath(QStringLiteral(
"qgc_tiles_") + QString::number(QDateTime::currentMSecsSinceEpoch()));
507 if (!QDir().mkpath(tempPath)) {
512 _extractionOutputDir = tempPath;
514 if (_extractionJob ==
nullptr) {
517 this, &QGCMapEngineManager::_handleExtractionProgress);
519 this, &QGCMapEngineManager::_handleExtractionFinished);
529void QGCMapEngineManager::_handleExtractionProgress(qreal progress)
534void QGCMapEngineManager::_handleExtractionFinished(
bool success)
537 const QString
error = _extractionJob !=
nullptr ? _extractionJob->
errorString() : tr(
"Extraction failed");
540 QDir(_extractionOutputDir).removeRecursively();
541 _extractionOutputDir.clear();
546 QDirIterator it(_extractionOutputDir, {QStringLiteral(
"*.db"), QStringLiteral(
"*.sqlite")},
547 QDir::Files, QDirIterator::Subdirectories);
552 if (dbPath.isEmpty()) {
555 QDir(_extractionOutputDir).removeRecursively();
556 _extractionOutputDir.clear();
560 qCDebug(QGCMapEngineManagerLog) <<
"Found tile database:" << dbPath;
565 QDir(_extractionOutputDir).removeRecursively();
566 _extractionOutputDir.clear();
576 QDir(_extractionOutputDir).removeRecursively();
577 _extractionOutputDir.clear();
QObject wrapper for async compression operations using QtConcurrent/QPromise.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Q_APPLICATION_STATIC(QGCMapEngineManager, _mapEngineManager)
QGCMapEngine * getQGCMapEngine()
void setTotalTileCount(quint32 num)
double bottomRightLon() const
void setName(const QString &name)
double topleftLat() const
void setTotalTileSize(quint64 size)
void setSavedTileCount(quint32 num)
void setMinZoom(int zoom)
void setSavedTileSize(quint64 size)
void setMaxZoom(int zoom)
void setTopleftLat(double lat)
const QString & type() const
double topleftLon() const
void setDeleting(bool del)
quint32 totalTileCount() const
Q_INVOKABLE void createDownloadTask()
const QString & name() const
void setBottomRightLon(double lon)
void setType(const QString &type)
const QString & mapTypeStr() const
void setBottomRightLat(double lat)
const QDateTime & creationDate() const
void setSelected(bool sel)
void setManager(QGCMapEngineManager *mgr)
void setMapTypeStr(const QString &typeStr)
double bottomRightLat() const
void setTopleftLon(double lon)
QObject wrapper for compression operations with progress signals.
QString errorString() const
void progressChanged(qreal progress)
Emitted when progress changes (0.0 to 1.0)
void finished(bool success)
void extractArchive(const QString &archivePath, const QString &outputDirectoryPath, qint64 maxBytes=0)
void tileSetSaved(QGCCachedTileSet *tileSet)
void tileSetDeleted(quint64 setID)
void actionProgress(int percentage)
void tileSetFetched(QGCCachedTileSet *tileSet)
void actionProgress(int percentage)
static QStringList mapProviderList()
Q_INVOKABLE bool findName(const QString &name) const
void taskError(QGCMapTask::TaskType type, const QString &error)
static Q_INVOKABLE QString loadSetting(const QString &key, const QString &defaultValue)
Q_INVOKABLE bool importArchive(const QString &archivePath)
Q_INVOKABLE void selectAll()
void setActionProgress(int percentage)
QString tileCountStr() const
static QStringList elevationProviderList()
static Q_INVOKABLE void saveSetting(const QString &key, const QString &value)
static QStringList mapList()
static Q_INVOKABLE QStringList mapTypeList(const QString &provider)
QGCMapEngineManager(QObject *parent=nullptr)
Q_INVOKABLE void startDownload(const QString &name, const QString &mapType)
QString tileSizeStr() const
Q_INVOKABLE void renameTileSet(QGCCachedTileSet *tileSet, const QString &newName)
Q_INVOKABLE void deleteTileSet(QGCCachedTileSet *tileSet)
Q_INVOKABLE void selectNone()
Q_INVOKABLE bool importSets(const QString &path=QString())
Q_INVOKABLE bool exportSets(const QString &path=QString())
int selectedCount() const
Q_INVOKABLE QString getUniqueName() const
Q_INVOKABLE void loadTileSets()
void setImportAction(ImportAction action)
void setErrorMessage(const QString &error)
Q_INVOKABLE void updateForCurrentView(double lon0, double lat0, double lon1, double lat1, int minZoom, int maxZoom, const QString &mapName)
bool addTask(QGCMapTask *task)
void updateTotals(quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize)
@ taskUpdateTileDownloadState
@ taskGetTileDownloadList
void error(QGCMapTask::TaskType type, const QString &errorString)
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
Q_INVOKABLE QObject * get(int index)
QObject * removeAt(int index)
int count() const override final
void clear() override final
FlightMapSettings * flightMapSettings() const
static SettingsManager * instance()
static QStringList getProviderTypes()
static QGCTileSet getTileCount(int zoom, double topleftLon, double topleftLat, double bottomRightLon, double bottomRightLat, QStringView mapType)
static bool isElevation(int qtMapId)
static QStringList getElevationProviderTypes()
static int getQtMapIdFromProviderType(QStringView type)
bool isArchiveFile(const QString &filePath)
Check if file path indicates an archive file (.zip, .tar, .tar.gz, etc.)
QString numberToString(quint64 number)
Decimal integer (e.g. "1,234,567").
QString bigSizeToString(quint64 size)
Byte size with unit: B, KB, MB, GB, TB. 1 fractional digit above 1 KB.