From a681941aeca0d9e37a975aebb9bd43db5b98b75d Mon Sep 17 00:00:00 2001 From: dogmaphobic Date: Tue, 12 Jul 2016 01:14:43 -0400 Subject: [PATCH] Fixes to Offline Map Cache --- src/QmlControls/OfflineMapButton.qml | 4 +- src/QtLocationPlugin/QGCMapEngine.cpp | 28 +- src/QtLocationPlugin/QGCMapEngine.h | 5 +- src/QtLocationPlugin/QGCMapTileSet.cpp | 106 ++-- src/QtLocationPlugin/QGCMapTileSet.h | 117 +++-- src/QtLocationPlugin/QGCTileCacheWorker.cpp | 142 +++--- src/QtLocationPlugin/QGCTileCacheWorker.h | 2 +- .../QMLControl/OfflineMap.qml | 469 ++++++------------ .../QMLControl/QGCMapEngineManager.cc | 18 +- .../QMLControl/QGCMapEngineManager.h | 2 +- 10 files changed, 391 insertions(+), 502 deletions(-) diff --git a/src/QmlControls/OfflineMapButton.qml b/src/QmlControls/OfflineMapButton.qml index e0c781571..6ff13ee76 100644 --- a/src/QmlControls/OfflineMapButton.qml +++ b/src/QmlControls/OfflineMapButton.qml @@ -20,7 +20,8 @@ Rectangle property bool checked: false property bool complete: false property alias text: nameLabel.text - property alias size: sizeLabel.text + property int tiles: 0 + property string size: "" signal clicked() @@ -40,6 +41,7 @@ Rectangle horizontalAlignment: Text.AlignRight anchors.verticalCenter: parent.verticalCenter color: __showHighlight ? __qgcPal.buttonHighlightText : __qgcPal.buttonText + text: __mapButton.size + (tiles > 0 ? " (" + tiles + " tiles)" : "") } Item { width: ScreenTools.defaultFontPixelWidth * 2 diff --git a/src/QtLocationPlugin/QGCMapEngine.cpp b/src/QtLocationPlugin/QGCMapEngine.cpp index e04decdbb..fc02dedd7 100644 --- a/src/QtLocationPlugin/QGCMapEngine.cpp +++ b/src/QtLocationPlugin/QGCMapEngine.cpp @@ -32,7 +32,7 @@ Q_DECLARE_METATYPE(QList) static const char* kDbFileName = "qgcMapCache.db"; static QLocale kLocale; -#define CACHE_PATH_VERSION "100" +#define CACHE_PATH_VERSION "300" struct stQGeoTileCacheQGCMapTypes { const char* name; @@ -144,15 +144,29 @@ QGCMapEngine::~QGCMapEngine() //----------------------------------------------------------------------------- void -QGCMapEngine::init() +QGCMapEngine::_wipeOldCaches() { - //-- Delete old style cache (if present) + QString oldCacheDir; +#ifdef __mobile__ + oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1String("/QGCMapCache55"); +#else + oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1String("/QGCMapCache55"); +#endif + _wipeDirectory(oldCacheDir); #ifdef __mobile__ - QString oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1String("/QGCMapCache55"); + oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1String("/QGCMapCache100"); #else - QString oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1String("/QGCMapCache55"); + oldCacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + QLatin1String("/QGCMapCache100"); #endif _wipeDirectory(oldCacheDir); +} + +//----------------------------------------------------------------------------- +void +QGCMapEngine::init() +{ + //-- Delete old style caches (if present) + _wipeOldCaches(); //-- Figure out cache path #ifdef __mobile__ QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QLatin1String("/QGCMapCache" CACHE_PATH_VERSION); @@ -398,7 +412,7 @@ QGCMapEngine::bigSizeToString(quint64 size) //----------------------------------------------------------------------------- QString -QGCMapEngine::numberToString(quint32 number) +QGCMapEngine::numberToString(quint64 number) { return kLocale.toString(number); } @@ -408,7 +422,7 @@ void QGCMapEngine::_updateTotals(quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize) { emit updateTotals(totaltiles, totalsize, defaulttiles, defaultsize); - quint64 maxSize = getMaxDiskCache() * 1024 * 1024; + quint64 maxSize = (quint64)getMaxDiskCache() * 1024L * 1024L; if(!_prunning && defaultsize > maxSize) { //-- Prune Disk Cache _prunning = true; diff --git a/src/QtLocationPlugin/QGCMapEngine.h b/src/QtLocationPlugin/QGCMapEngine.h index 803dcc26b..97fe8ee7e 100644 --- a/src/QtLocationPlugin/QGCMapEngine.h +++ b/src/QtLocationPlugin/QGCMapEngine.h @@ -96,7 +96,7 @@ public: static QString getTileHash (UrlFactory::MapType type, int x, int y, int z); static UrlFactory::MapType getTypeFromName (const QString &name); static QString bigSizeToString (quint64 size); - static QString numberToString (quint32 number); + static QString numberToString (quint64 number); static int concurrentDownloads (UrlFactory::MapType type); private slots: @@ -107,7 +107,8 @@ signals: void updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize); private: - bool _wipeDirectory(const QString& dirPath); + void _wipeOldCaches (); + bool _wipeDirectory (const QString& dirPath); private: QGCCacheWorker _worker; diff --git a/src/QtLocationPlugin/QGCMapTileSet.cpp b/src/QtLocationPlugin/QGCMapTileSet.cpp index 846d890d3..71f770f3c 100644 --- a/src/QtLocationPlugin/QGCMapTileSet.cpp +++ b/src/QtLocationPlugin/QGCMapTileSet.cpp @@ -28,17 +28,18 @@ QGC_LOGGING_CATEGORY(QGCCachedTileSetLog, "QGCCachedTileSetLog") #define TILE_BATCH_SIZE 256 //----------------------------------------------------------------------------- -QGCCachedTileSet::QGCCachedTileSet(const QString& name, const QString& description) +QGCCachedTileSet::QGCCachedTileSet(const QString& name) : _name(name) - , _description(description) , _topleftLat(0.0) , _topleftLon(0.0) , _bottomRightLat(0.0) , _bottomRightLon(0.0) - , _numTiles(0) - , _tilesSize(0) - , _savedTiles(0) - , _savedSize(0) + , _totalTileCount(0) + , _totalTileSize(0) + , _uniqueTileCount(0) + , _uniqueTileSize(0) + , _savedTileCount(0) + , _savedTileSize(0) , _minZoom(3) , _maxZoom(3) , _defaultSet(false) @@ -72,30 +73,44 @@ QGCCachedTileSet::errorCountStr() //----------------------------------------------------------------------------- QString -QGCCachedTileSet::numTilesStr() +QGCCachedTileSet::totalTileCountStr() { - return QGCMapEngine::numberToString(_numTiles); + return QGCMapEngine::numberToString(_totalTileCount); } //----------------------------------------------------------------------------- QString -QGCCachedTileSet::tilesSizeStr() +QGCCachedTileSet::totalTilesSizeStr() { - return QGCMapEngine::bigSizeToString(_tilesSize); + return QGCMapEngine::bigSizeToString(_totalTileSize); } //----------------------------------------------------------------------------- QString -QGCCachedTileSet::savedTilesStr() +QGCCachedTileSet::uniqueTileSizeStr() { - return QGCMapEngine::numberToString(_savedTiles); + return QGCMapEngine::bigSizeToString(_uniqueTileSize); } //----------------------------------------------------------------------------- QString -QGCCachedTileSet::savedSizeStr() +QGCCachedTileSet::uniqueTileCountStr() { - return QGCMapEngine::bigSizeToString(_savedSize); + return QGCMapEngine::numberToString(_uniqueTileCount); +} + +//----------------------------------------------------------------------------- +QString +QGCCachedTileSet::savedTileCountStr() +{ + return QGCMapEngine::numberToString(_savedTileCount); +} + +//----------------------------------------------------------------------------- +QString +QGCCachedTileSet::savedTileSizeStr() +{ + return QGCMapEngine::bigSizeToString(_savedTileSize); } //----------------------------------------------------------------------------- @@ -103,12 +118,12 @@ QString QGCCachedTileSet::downloadStatus() { if(_defaultSet) { - return tilesSizeStr(); + return totalTilesSizeStr(); } - if(_numTiles == _savedTiles) { - return savedSizeStr(); + if(_totalTileCount <= _savedTileCount) { + return savedTileSizeStr(); } else { - return savedSizeStr() + " / " + tilesSizeStr(); + return savedTileSizeStr() + " / " + totalTilesSizeStr(); } } @@ -128,8 +143,8 @@ QGCCachedTileSet::createDownloadTask() if(_manager) connect(task, &QGCMapTask::error, _manager, &QGCMapEngineManager::taskError); getQGCMapEngine()->addTask(task); - emit numTilesChanged(); - emit tilesSizeChanged(); + emit totalTileCountChanged(); + emit totalTilesSizeChanged(); _batchRequested = true; } @@ -164,6 +179,7 @@ QGCCachedTileSet::_tileListFetched(QList tiles) _noMoreTiles = true; } if(!tiles.size()) { + _doneWithDownload(); return; } //-- If this is the first time, create Network Manager @@ -176,23 +192,33 @@ QGCCachedTileSet::_tileListFetched(QList tiles) _prepareDownload(); } +//----------------------------------------------------------------------------- +void QGCCachedTileSet::_doneWithDownload() +{ + if(!_errorCount) { + _totalTileCount = _savedTileCount; + _totalTileSize = _savedTileSize; + //-- Too expensive to compute the real size now. Estimate it for the time being. + quint32 avg = _savedTileSize / _savedTileCount; + _uniqueTileSize = _uniqueTileCount * avg; + } + emit totalTileCountChanged(); + emit totalTilesSizeChanged(); + emit savedTileSizeChanged(); + emit savedTileCountChanged(); + emit uniqueTileSizeChanged(); + _downloading = false; + emit downloadingChanged(); + emit completeChanged(); +} + //----------------------------------------------------------------------------- void QGCCachedTileSet::_prepareDownload() { if(!_tilesToDownload.count()) { //-- Are we done? if(_noMoreTiles) { - if(!_errorCount) { - _numTiles = _savedTiles; - _tilesSize = _savedSize; - } - emit numTilesChanged(); - emit tilesSizeChanged(); - emit savedSizeChanged(); - emit savedTilesChanged(); - _downloading = false; - emit downloadingChanged(); - emit completeChanged(); + _doneWithDownload(); } else { if(!_batchRequested) createDownloadTask(); @@ -253,15 +279,17 @@ QGCCachedTileSet::_networkReplyFinished() QGCUpdateTileDownloadStateTask* task = new QGCUpdateTileDownloadStateTask(_id, QGCTile::StateComplete, hash); getQGCMapEngine()->addTask(task); //-- Updated cached (downloaded) data - _savedSize += image.size(); - _savedTiles++; - emit savedSizeChanged(); - emit savedTilesChanged(); + _savedTileSize += image.size(); + _savedTileCount++; + emit savedTileSizeChanged(); + emit savedTileCountChanged(); //-- Update estimate - if(_savedTiles % 10 == 0) { - quint32 avg = _savedSize / _savedTiles; - _tilesSize = avg * _numTiles; - emit tilesSizeChanged(); + if(_savedTileCount % 10 == 0) { + quint32 avg = _savedTileSize / _savedTileCount; + _totalTileSize = avg * _totalTileCount; + _uniqueTileSize = avg * _uniqueTileCount; + emit totalTilesSizeChanged(); + emit uniqueTileSizeChanged(); } } //-- Setup a new download diff --git a/src/QtLocationPlugin/QGCMapTileSet.h b/src/QtLocationPlugin/QGCMapTileSet.h index c13967b35..dc8217e61 100644 --- a/src/QtLocationPlugin/QGCMapTileSet.h +++ b/src/QtLocationPlugin/QGCMapTileSet.h @@ -39,36 +39,38 @@ class QGCCachedTileSet : public QObject { Q_OBJECT public: - QGCCachedTileSet (const QString& name, const QString& description); + QGCCachedTileSet (const QString& name); ~QGCCachedTileSet (); - Q_PROPERTY(QString name READ name CONSTANT) - Q_PROPERTY(QString description READ description CONSTANT) - Q_PROPERTY(QString mapTypeStr READ mapTypeStr CONSTANT) - Q_PROPERTY(double topleftLon READ topleftLon CONSTANT) - Q_PROPERTY(double topleftLat READ topleftLat CONSTANT) - Q_PROPERTY(double bottomRightLon READ bottomRightLon CONSTANT) - Q_PROPERTY(double bottomRightLat READ bottomRightLat CONSTANT) - Q_PROPERTY(int minZoom READ minZoom CONSTANT) - Q_PROPERTY(int maxZoom READ maxZoom CONSTANT) - Q_PROPERTY(quint32 numTiles READ numTiles NOTIFY numTilesChanged) - Q_PROPERTY(QString numTilesStr READ numTilesStr NOTIFY numTilesChanged) - Q_PROPERTY(quint64 tilesSize READ tilesSize NOTIFY tilesSizeChanged) - Q_PROPERTY(QString tilesSizeStr READ tilesSizeStr NOTIFY tilesSizeChanged) - Q_PROPERTY(quint32 savedTiles READ savedTiles NOTIFY savedTilesChanged) - Q_PROPERTY(QString savedTilesStr READ savedTilesStr NOTIFY savedTilesChanged) - Q_PROPERTY(quint64 savedSize READ savedSize NOTIFY savedSizeChanged) - Q_PROPERTY(QString savedSizeStr READ savedSizeStr NOTIFY savedSizeChanged) - Q_PROPERTY(QString downloadStatus READ downloadStatus NOTIFY savedSizeChanged) - Q_PROPERTY(QDateTime creationDate READ creationDate CONSTANT) - Q_PROPERTY(bool complete READ complete NOTIFY completeChanged) - Q_PROPERTY(bool defaultSet READ defaultSet CONSTANT) - Q_PROPERTY(quint64 setID READ setID CONSTANT) - Q_PROPERTY(bool deleting READ deleting NOTIFY deletingChanged) - Q_PROPERTY(bool downloading READ downloading NOTIFY downloadingChanged) - Q_PROPERTY(quint32 errorCount READ errorCount NOTIFY errorCountChanged) - Q_PROPERTY(QString errorCountStr READ errorCountStr NOTIFY errorCountChanged) - Q_PROPERTY(QImage thumbNail READ thumbNail CONSTANT) + Q_PROPERTY(QString name READ name CONSTANT) + Q_PROPERTY(QString mapTypeStr READ mapTypeStr CONSTANT) + Q_PROPERTY(double topleftLon READ topleftLon CONSTANT) + Q_PROPERTY(double topleftLat READ topleftLat CONSTANT) + Q_PROPERTY(double bottomRightLon READ bottomRightLon CONSTANT) + Q_PROPERTY(double bottomRightLat READ bottomRightLat CONSTANT) + Q_PROPERTY(int minZoom READ minZoom CONSTANT) + Q_PROPERTY(int maxZoom READ maxZoom CONSTANT) + Q_PROPERTY(quint32 totalTileCount READ totalTileCount NOTIFY totalTileCountChanged) + Q_PROPERTY(QString totalTileCountStr READ totalTileCountStr NOTIFY totalTileCountChanged) + Q_PROPERTY(quint64 totalTilesSize READ totalTilesSize NOTIFY totalTilesSizeChanged) + Q_PROPERTY(QString totalTilesSizeStr READ totalTilesSizeStr NOTIFY totalTilesSizeChanged) + Q_PROPERTY(quint32 uniqueTileCount READ uniqueTileCount NOTIFY uniqueTileCountChanged) + Q_PROPERTY(QString uniqueTileCountStr READ uniqueTileCountStr NOTIFY uniqueTileCountChanged) + Q_PROPERTY(quint64 uniqueTileSize READ uniqueTileSize NOTIFY uniqueTileSizeChanged) + Q_PROPERTY(QString uniqueTileSizeStr READ uniqueTileSizeStr NOTIFY uniqueTileSizeChanged) + Q_PROPERTY(quint32 savedTileCount READ savedTileCount NOTIFY savedTileCountChanged) + Q_PROPERTY(QString savedTileCountStr READ savedTileCountStr NOTIFY savedTileCountChanged) + Q_PROPERTY(quint64 savedTileSize READ savedTileSize NOTIFY savedTileSizeChanged) + Q_PROPERTY(QString savedTileSizeStr READ savedTileSizeStr NOTIFY savedTileSizeChanged) + Q_PROPERTY(QString downloadStatus READ downloadStatus NOTIFY savedTileSizeChanged) + Q_PROPERTY(QDateTime creationDate READ creationDate CONSTANT) + Q_PROPERTY(bool complete READ complete NOTIFY completeChanged) + Q_PROPERTY(bool defaultSet READ defaultSet CONSTANT) + Q_PROPERTY(quint64 setID READ setID CONSTANT) + Q_PROPERTY(bool deleting READ deleting NOTIFY deletingChanged) + Q_PROPERTY(bool downloading READ downloading NOTIFY downloadingChanged) + Q_PROPERTY(quint32 errorCount READ errorCount NOTIFY errorCountChanged) + Q_PROPERTY(QString errorCountStr READ errorCountStr NOTIFY errorCountChanged) Q_INVOKABLE void createDownloadTask (); Q_INVOKABLE void resumeDownloadTask (); @@ -77,46 +79,49 @@ public: void setManager (QGCMapEngineManager* mgr); QString name () { return _name; } - QString description () { return _description; } QString mapTypeStr () { return _mapTypeStr; } double topleftLat () { return _topleftLat; } double topleftLon () { return _topleftLon; } double bottomRightLat () { return _bottomRightLat; } double bottomRightLon () { return _bottomRightLon; } - quint32 numTiles () { return (quint32)_numTiles; } - QString numTilesStr (); - quint64 tilesSize () { return (quint64)_tilesSize; } - QString tilesSizeStr (); - quint32 savedTiles () { return (quint32)_savedTiles; } - QString savedTilesStr (); - quint64 savedSize () { return (quint64)_savedSize; } - QString savedSizeStr (); + quint32 totalTileCount () { return (quint32)_totalTileCount; } + QString totalTileCountStr (); + quint64 totalTilesSize () { return (quint64)_totalTileSize; } + QString totalTilesSizeStr (); + quint32 uniqueTileCount () { return _uniqueTileCount; } + QString uniqueTileCountStr (); + quint64 uniqueTileSize () { return _uniqueTileSize; } + QString uniqueTileSizeStr (); + quint32 savedTileCount () { return (quint32)_savedTileCount; } + QString savedTileCountStr (); + quint64 savedTileSize () { return (quint64)_savedTileSize; } + QString savedTileSizeStr (); QString downloadStatus (); int minZoom () { return _minZoom; } int maxZoom () { return _maxZoom; } QDateTime creationDate () { return _creationDate; } quint64 id () { return _id; } UrlFactory::MapType type () { return _type; } - bool complete () { return _defaultSet || (_numTiles == _savedTiles); } + bool complete () { return _defaultSet || (_totalTileCount <= _savedTileCount); } bool defaultSet () { return _defaultSet; } quint64 setID () { return _id; } bool deleting () { return _deleting; } bool downloading () { return _downloading; } quint32 errorCount () { return _errorCount; } QString errorCountStr (); - QImage thumbNail () { return _thumbNail; } void setName (QString name) { _name = name; } - void setDescription (QString desc) { _description = desc; } void setMapTypeStr (QString typeStr) { _mapTypeStr = typeStr; } void setTopleftLat (double lat) { _topleftLat = lat; } void setTopleftLon (double lon) { _topleftLon = lon; } void setBottomRightLat (double lat) { _bottomRightLat = lat; } void setBottomRightLon (double lon) { _bottomRightLon = lon; } - void setNumTiles (quint32 num) { _numTiles = num; } - void setTilesSize (quint64 size) { _tilesSize = size; } - void setSavedTiles (quint32 num) { _savedTiles = num; emit savedTilesChanged(); } - void setSavedSize (quint64 size) { _savedSize = size; emit savedSizeChanged(); } + void setTotalTileCount (quint32 num) { _totalTileCount = num; emit totalTileCountChanged(); } + void setUniqueTileCount (quint32 num) { _uniqueTileCount = num; } + void setUniqueTileSize (quint64 size) { _uniqueTileSize = size; } + void setTotalTileSize (quint64 size) { _totalTileSize = size; emit totalTilesSizeChanged(); } + void setSavedTileCount (quint32 num) { _savedTileCount = num; emit savedTileCountChanged(); } + void setSavedTileSize (quint64 size) { _savedTileSize = size; emit savedTileSizeChanged(); } void setMinZoom (int zoom) { _minZoom = zoom; } void setMaxZoom (int zoom) { _maxZoom = zoom; } void setCreationDate (QDateTime date) { _creationDate = date; } @@ -125,15 +130,16 @@ public: void setDefaultSet (bool def) { _defaultSet = def; } void setDeleting (bool del) { _deleting = del; emit deletingChanged(); } void setDownloading (bool down) { _downloading = down; } - void setThumbNail (const QImage& thumb) { _thumbNail = thumb; } signals: void deletingChanged (); void downloadingChanged (); - void numTilesChanged (); - void tilesSizeChanged (); - void savedTilesChanged (); - void savedSizeChanged (); + void totalTileCountChanged (); + void uniqueTileCountChanged (); + void uniqueTileSizeChanged (); + void totalTilesSizeChanged (); + void savedTileCountChanged (); + void savedTileSizeChanged (); void completeChanged (); void errorCountChanged (); @@ -144,19 +150,21 @@ private slots: private: void _prepareDownload (); + void _doneWithDownload (); private: QString _name; - QString _description; QString _mapTypeStr; double _topleftLat; double _topleftLon; double _bottomRightLat; double _bottomRightLon; - quint32 _numTiles; - quint64 _tilesSize; - quint32 _savedTiles; - quint64 _savedSize; + quint32 _totalTileCount; + quint64 _totalTileSize; + quint32 _uniqueTileCount; + quint64 _uniqueTileSize; + quint32 _savedTileCount; + quint64 _savedTileSize; int _minZoom; int _maxZoom; bool _defaultSet; @@ -173,7 +181,6 @@ private: bool _noMoreTiles; bool _batchRequested; QGCMapEngineManager* _manager; - QImage _thumbNail; }; #endif // QGC_MAP_TILE_SET_H diff --git a/src/QtLocationPlugin/QGCTileCacheWorker.cpp b/src/QtLocationPlugin/QGCTileCacheWorker.cpp index cea90f9ed..91ec4d160 100644 --- a/src/QtLocationPlugin/QGCTileCacheWorker.cpp +++ b/src/QtLocationPlugin/QGCTileCacheWorker.cpp @@ -168,7 +168,9 @@ QGCCacheWorker::run() _updateTimeout = SHORT_TIMEOUT; } if(!count || (time(0) - _lastUpdate > _updateTimeout)) { - _updateTotals(); + if(_valid) { + _updateTotals(); + } } } else { //-- Wait a bit before shutting things down @@ -298,14 +300,11 @@ QGCCacheWorker::_getTileSets(QGCMapTask* mtask) QGCFetchTileSetTask* task = static_cast(mtask); QSqlQuery query(*_db); QString s = QString("SELECT * FROM TileSets ORDER BY defaultSet DESC, name ASC"); + qCDebug(QGCTileCacheLog) << "_getTileSets(): " << s; if(query.exec(s)) { while(query.next()) { QString name = query.value("name").toString(); - QString desc = query.value("description").toString(); - //-- Original database had description as NOT NULL - if(desc.isEmpty()) - desc = " "; - QGCCachedTileSet* set = new QGCCachedTileSet(name, desc); + QGCCachedTileSet* set = new QGCCachedTileSet(name); set->setId(query.value("setID").toULongLong()); set->setMapTypeStr(query.value("typeStr").toString()); set->setTopleftLat(query.value("topleftLat").toDouble()); @@ -315,19 +314,9 @@ QGCCacheWorker::_getTileSets(QGCMapTask* mtask) set->setMinZoom(query.value("minZoom").toInt()); set->setMaxZoom(query.value("maxZoom").toInt()); set->setType((UrlFactory::MapType)query.value("type").toInt()); - set->setNumTiles(query.value("numTiles").toUInt()); - set->setTilesSize(query.value("tilesSize").toULongLong()); + set->setTotalTileCount(query.value("numTiles").toUInt()); set->setDefaultSet(query.value("defaultSet").toInt() != 0); set->setCreationDate(QDateTime::fromTime_t(query.value("date").toUInt())); - //-- Load thumbnail (if not default set) - if(!set->defaultSet()) { - int w = query.value("thumbW").toInt(); - int h = query.value("thumbH").toInt(); - if(w && h) { - QByteArray ba = query.value("thumbNail").toByteArray(); - set->setThumbNail(QImage((uchar*)(void*)ba.data(), w, h, QImage::Format_RGB32)); - } - } _updateSetTotals(set); //-- Object created here must be moved to app thread to be used there set->moveToThread(QApplication::instance()->thread()); @@ -344,23 +333,52 @@ QGCCacheWorker::_updateSetTotals(QGCCachedTileSet* set) { if(set->defaultSet()) { _updateTotals(); - set->setSavedTiles(_totalCount); - set->setSavedSize(_totalSize); - set->setNumTiles(_defaultCount); - set->setTilesSize(_defaultSize); + set->setSavedTileCount(_totalCount); + set->setSavedTileSize(_totalSize); + set->setTotalTileCount(_defaultCount); + set->setTotalTileSize(_defaultSize); return; } QSqlQuery subquery(*_db); QString sq = QString("SELECT COUNT(size), SUM(size) FROM Tiles A INNER JOIN SetTiles B on A.tileID = B.tileID WHERE B.setID = %1").arg(set->id()); + qCDebug(QGCTileCacheLog) << "_updateSetTotals(): " << sq; if(subquery.exec(sq)) { if(subquery.next()) { - set->setSavedTiles(subquery.value(0).toUInt()); - set->setSavedSize(subquery.value(1).toULongLong()); - //-- Update estimated size - if(set->savedTiles() > 10 && set->savedSize()) { - quint32 avg = set->savedSize() / set->savedTiles(); - set->setTilesSize(avg * set->numTiles()); + set->setSavedTileCount(subquery.value(0).toUInt()); + set->setSavedTileSize(subquery.value(1).toULongLong()); + qCDebug(QGCTileCacheLog) << "Set" << set->id() << "Totals:" << set->savedTileCount() << " " << set->savedTileSize() << "Expected: " << set->totalTileCount() << " " << set->totalTilesSize(); + //-- Update (estimated) size + quint64 avg = UrlFactory::averageSizeForType(set->type()); + if(set->totalTileCount() <= set->savedTileCount()) { + //-- We're done so the saved size is the total size + set->setTotalTileSize(set->savedTileSize()); + } else { + //-- Otherwise we need to estimate it. + if(set->savedTileCount() > 10 && set->savedTileSize()) { + avg = set->savedTileSize() / set->savedTileCount(); + } + set->setTotalTileSize(avg * set->totalTileCount()); + } + //-- Now figure out the count for tiles unique to this set + quint32 ucount = 0; + quint64 usize = 0; + sq = QString("SELECT COUNT(size), SUM(size) FROM Tiles WHERE tileID IN (SELECT A.tileID FROM SetTiles A join SetTiles B on A.tileID = B.tileID WHERE B.setID = %1 GROUP by A.tileID HAVING COUNT(A.tileID) = 1)").arg(set->id()); + if(subquery.exec(sq)) { + if(subquery.next()) { + //-- This is only accurate when all tiles are downloaded + ucount = subquery.value(0).toUInt(); + usize = subquery.value(1).toULongLong(); + } + } + //-- If we haven't downloaded it all, estimate size of unique tiles + quint32 expectedUcount = set->totalTileCount() - set->savedTileCount(); + if(!ucount) { + usize = expectedUcount * avg; + } else { + expectedUcount = ucount; } + set->setUniqueTileCount(expectedUcount); + set->setUniqueTileSize(usize); } } } @@ -372,13 +390,15 @@ QGCCacheWorker::_updateTotals() QSqlQuery query(*_db); QString s; s = QString("SELECT COUNT(size), SUM(size) FROM Tiles"); + qCDebug(QGCTileCacheLog) << "_updateTotals(): " << s; if(query.exec(s)) { if(query.next()) { _totalCount = query.value(0).toUInt(); _totalSize = query.value(1).toULongLong(); } } - s = QString("SELECT COUNT(size), SUM(size) FROM Tiles A INNER JOIN SetTiles B on A.tileID = B.tileID WHERE B.setID = %1").arg(_getDefaultTileSet()); + s = QString("SELECT COUNT(size), SUM(size) FROM Tiles WHERE tileID IN (SELECT A.tileID FROM SetTiles A join SetTiles B on A.tileID = B.tileID WHERE B.setID = %1 GROUP by A.tileID HAVING COUNT(A.tileID) = 1)").arg(_getDefaultTileSet()); + qCDebug(QGCTileCacheLog) << "_updateTotals(): " << s; if(query.exec(s)) { if(query.next()) { _defaultCount = query.value(0).toUInt(); @@ -390,17 +410,17 @@ QGCCacheWorker::_updateTotals() } //----------------------------------------------------------------------------- -bool -QGCCacheWorker::_findTile(const QString hash) +quint64 QGCCacheWorker::_findTile(const QString hash) { + quint64 tileID = 0; QSqlQuery query(*_db); - QString s = QString("SELECT type FROM Tiles WHERE hash = \"%1\"").arg(hash); + QString s = QString("SELECT tileID FROM Tiles WHERE hash = \"%1\"").arg(hash); if(query.exec(s)) { if(query.next()) { - return true; + tileID = query.value(0).toULongLong(); } } - return false; + return tileID; } //----------------------------------------------------------------------------- @@ -412,15 +432,10 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask) quint32 actual_count = 0; QGCCreateTileSetTask* task = static_cast(mtask); QSqlQuery query(*_db); - QString desc = task->tileSet()->description(); - //-- Original database had description as NOT NULL - if(desc.isEmpty()) - desc = " "; query.prepare("INSERT INTO TileSets(" - "name, description, typeStr, topleftLat, topleftLon, bottomRightLat, bottomRightLon, minZoom, maxZoom, type, numTiles, tilesSize, thumbNail, thumbW, thumbH, date" - ") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + "name, typeStr, topleftLat, topleftLon, bottomRightLat, bottomRightLon, minZoom, maxZoom, type, numTiles, date" + ") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); query.addBindValue(task->tileSet()->name()); - query.addBindValue(desc); query.addBindValue(task->tileSet()->mapTypeStr()); query.addBindValue(task->tileSet()->topleftLat()); query.addBindValue(task->tileSet()->topleftLon()); @@ -429,35 +444,28 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask) query.addBindValue(task->tileSet()->minZoom()); query.addBindValue(task->tileSet()->maxZoom()); query.addBindValue(task->tileSet()->type()); - query.addBindValue(task->tileSet()->numTiles()); - query.addBindValue(task->tileSet()->tilesSize()); - if(task->tileSet()->thumbNail().isNull()) { - query.addBindValue(QByteArray(1,'\0')); - query.addBindValue(0); - query.addBindValue(0); - } else { - query.addBindValue(QByteArray((const char *)(void*)task->tileSet()->thumbNail().convertToFormat(QImage::Format_RGB32).bits(), task->tileSet()->thumbNail().byteCount())); - query.addBindValue(task->tileSet()->thumbNail().width()); - query.addBindValue(task->tileSet()->thumbNail().height()); - } + query.addBindValue(task->tileSet()->totalTileCount()); query.addBindValue(QDateTime::currentDateTime().toTime_t()); if(!query.exec()) { qWarning() << "Map Cache SQL error (add tileSet into TileSets):" << query.lastError().text(); } else { - //-- Get just creted (auto-incremented) setID + //-- Get just created (auto-incremented) setID quint64 setID = query.lastInsertId().toULongLong(); task->tileSet()->setId(setID); //-- Prepare Download List + quint64 tileCount = 0; for(int z = task->tileSet()->minZoom(); z <= task->tileSet()->maxZoom(); z++) { QGCTileSet set = QGCMapEngine::getTileCount(z, task->tileSet()->topleftLon(), task->tileSet()->topleftLat(), task->tileSet()->bottomRightLon(), task->tileSet()->bottomRightLat(), task->tileSet()->type()); + tileCount += set.tileCount; UrlFactory::MapType type = task->tileSet()->type(); for(int x = set.tileX0; x <= set.tileX1; x++) { for(int y = set.tileY0; y <= set.tileY1; y++) { //-- See if tile is already downloaded QString hash = QGCMapEngine::getTileHash(type, x, y, z); - if(!_findTile(hash)) { + quint64 tileID = _findTile(hash); + if(!tileID) { //-- Set to download query.prepare("INSERT OR IGNORE INTO TilesDownload(setID, hash, type, x, y, z, state) VALUES(?, ?, ?, ?, ? ,? ,?)"); query.addBindValue(setID); @@ -473,16 +481,18 @@ QGCCacheWorker::_createTileSet(QGCMapTask *mtask) return; } else actual_count++; + } else { + //-- Tile already in the database. No need to dowload. + QString s = QString("INSERT OR IGNORE INTO SetTiles(tileID, setID) VALUES(%1, %2)").arg(tileID).arg(setID); + query.prepare(s); + if(!query.exec()) { + qWarning() << "Map Cache SQL error (add tile into SetTiles):" << query.lastError().text(); + } + qCDebug(QGCTileCacheLog) << "_createTileSet() Already Cached HASH:" << hash; } } } } - //-- Now update how many tiles we actually have to download - quint64 actual_size = actual_count * UrlFactory::averageSizeForType(task->tileSet()->type()); - QString s = QString("UPDATE TileSets SET numTiles = %1, tilesSize = %2 WHERE setID = %3").arg(actual_count).arg(actual_size).arg(task->tileSet()->setID()); - if(!query.exec(s)) { - qWarning() << "Map Cache SQL error (set TilesDownload state):" << query.lastError().text(); - } //-- Done _updateSetTotals(task->tileSet()); task->setTileSetSaved(); @@ -560,7 +570,8 @@ QGCCacheWorker::_pruneCache(QGCMapTask* mtask) QGCPruneCacheTask* task = static_cast(mtask); QSqlQuery query(*_db); QString s; - s = QString("SELECT tileID, size, hash FROM Tiles WHERE tileID IN (SELECT tileID FROM SetTiles WHERE setID = %1) ORDER BY DATE ASC LIMIT 128").arg(_getDefaultTileSet()); + //-- Select tiles in default set only, sorted by oldest. + s = QString("SELECT tileID, size, hash FROM Tiles WHERE tileID IN (SELECT A.tileID FROM SetTiles A join SetTiles B on A.tileID = B.tileID WHERE B.setID = %1 GROUP by A.tileID HAVING COUNT(A.tileID) = 1) ORDER BY DATE ASC LIMIT 128").arg(_getDefaultTileSet()); qint64 amount = (qint64)task->amount(); QList tlist; if(query.exec(s)) { @@ -590,7 +601,8 @@ QGCCacheWorker::_deleteTileSet(QGCMapTask* mtask) QGCDeleteTileSetTask* task = static_cast(mtask); QSqlQuery query(*_db); QString s; - s = QString("DELETE FROM Tiles WHERE tileID IN (SELECT tileID FROM SetTiles WHERE setID = %1)").arg(task->setID()); + //-- Only delete tiles unique to this set + s = QString("DELETE FROM Tiles WHERE tileID IN (SELECT A.tileID FROM SetTiles A JOIN SetTiles B ON A.tileID = B.tileID WHERE B.setID = %1 GROUP BY A.tileID HAVING COUNT(A.tileID) = 1)").arg(task->setID()); query.exec(s); s = QString("DELETE FROM TilesDownload WHERE setID = %1").arg(task->setID()); query.exec(s); @@ -672,7 +684,6 @@ QGCCacheWorker::_createDB() "CREATE TABLE IF NOT EXISTS TileSets (" "setID INTEGER PRIMARY KEY NOT NULL, " "name TEXT NOT NULL UNIQUE, " - "description TEXT, " "typeStr TEXT, " "topleftLat REAL DEFAULT 0.0, " "topleftLon REAL DEFAULT 0.0, " @@ -682,11 +693,7 @@ QGCCacheWorker::_createDB() "maxZoom INTEGER DEFAULT 3, " "type INTEGER DEFAULT -1, " "numTiles INTEGER DEFAULT 0, " - "tilesSize INTEGER DEFAULT 0, " "defaultSet INTEGER DEFAULT 0, " - "thumbNail BLOB NULL, " - "thumbW INTEGER DEFAULT 0, " - "thumbH INTEGER DEFAULT 0, " "date INTEGER DEFAULT 0)")) { qWarning() << "Map Cache SQL error (create TileSets db):" << query.lastError().text(); @@ -721,9 +728,8 @@ QGCCacheWorker::_createDB() QString s = QString("SELECT name FROM TileSets WHERE name = \"%1\"").arg(kDefaultSet); if(query.exec(s)) { if(!query.next()) { - query.prepare("INSERT INTO TileSets(name, description, defaultSet, date) VALUES(?, ?, ?, ?)"); + query.prepare("INSERT INTO TileSets(name, defaultSet, date) VALUES(?, ?, ?)"); query.addBindValue(kDefaultSet); - query.addBindValue("System wide tile cache"); query.addBindValue(1); query.addBindValue(QDateTime::currentDateTime().toTime_t()); if(!query.exec()) { diff --git a/src/QtLocationPlugin/QGCTileCacheWorker.h b/src/QtLocationPlugin/QGCTileCacheWorker.h index 0ff41584e..da63535fa 100644 --- a/src/QtLocationPlugin/QGCTileCacheWorker.h +++ b/src/QtLocationPlugin/QGCTileCacheWorker.h @@ -60,7 +60,7 @@ private: void _resetCacheDatabase (QGCMapTask* mtask); void _pruneCache (QGCMapTask* mtask); - bool _findTile (const QString hash); + quint64 _findTile (const QString hash); bool _findTileSetID (const QString name, quint64& setID); void _updateSetTotals (QGCCachedTileSet* set); bool _init (); diff --git a/src/QtLocationPlugin/QMLControl/OfflineMap.qml b/src/QtLocationPlugin/QMLControl/OfflineMap.qml index 5d4396d61..a80510eba 100644 --- a/src/QtLocationPlugin/QMLControl/OfflineMap.qml +++ b/src/QtLocationPlugin/QMLControl/OfflineMap.qml @@ -37,16 +37,17 @@ QGCView { property real savedZoom: 3 property string savedMapType: "" property bool _showPreview: true + property bool _defaultSet: offlineMapView && offlineMapView._currentSelection && offlineMapView._currentSelection.defaultSet - property bool _saveRealEstate: ScreenTools.isTinyScreen || ScreenTools.isShortScreen - property real _adjustableFontPointSize: _saveRealEstate ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize + property bool _saveRealEstate: ScreenTools.isTinyScreen || ScreenTools.isShortScreen + property real _adjustableFontPointSize: _saveRealEstate ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize property var _mapAdjustedColor: _map.isSatelliteMap ? "white" : "black" readonly property real minZoomLevel: 3 readonly property real maxZoomLevel: 20 - readonly property int _maxTilesForDownload: 60000 + readonly property int _maxTilesForDownload: 100000 QGCPalette { id: qgcPal } @@ -98,7 +99,6 @@ QGCView { _map.visible = true _tileSetList.visible = false infoView.visible = false - defaultInfoView.visible = false addNewSetView.visible = true } @@ -107,7 +107,6 @@ QGCView { _map.visible = false _tileSetList.visible = true infoView.visible = false - defaultInfoView.visible = false addNewSetView.visible = false } @@ -140,13 +139,12 @@ QGCView { } function enterInfoView() { - var isDefaultSet = offlineMapView._currentSelection.defaultSet _map.visible = true isMapInteractive = false savedCenter = _map.toCoordinate(Qt.point(_map.width / 2, _map.height / 2)) savedZoom = _map.zoomLevel savedMapType = mapType - if(!isDefaultSet) { + if(!offlineMapView._currentSelection.defaultSet) { mapType = offlineMapView._currentSelection.mapTypeStr _map.center = midPoint(offlineMapView._currentSelection.topleftLat, offlineMapView._currentSelection.bottomRightLat, offlineMapView._currentSelection.topleftLon, offlineMapView._currentSelection.bottomRightLon) //-- Delineate Set Region @@ -157,15 +155,14 @@ QGCView { mapBoundary.topLeft = QtPositioning.coordinate(y0, x0) mapBoundary.bottomRight = QtPositioning.coordinate(y1, x1) mapBoundary.visible = true + // Some times, for whatever reason, the bounding box is correct (around ETH for instance), but the rectangle is drawn across the planet. + // When that happens, the "_map.fitViewportToMapItems()" below makes the map to zoom to the entire earth. + //console.log("Map boundary: " + mapBoundary.topLeft + " " + mapBoundary.bottomRight) _map.fitViewportToMapItems() } _tileSetList.visible = false addNewSetView.visible = false - if(isDefaultSet) { - defaultInfoView.visible = true - } else { - infoView.visible = true - } + infoView.visible = true } function leaveInfoView() { @@ -277,30 +274,17 @@ QGCView { Component { id: deleteConfirmationDialogComponent - QGCViewMessage { - id: deleteConfirmationDialog - message: qsTr("Delete %1 and all its tiles.\n\nIs this really what you want?").arg(offlineMapView._currentSelection.name) - - function accept() { - QGroundControl.mapEngineManager.deleteTileSet(offlineMapView._currentSelection) - deleteConfirmationDialog.hideDialog() - leaveInfoView() - showList() + id: deleteConfirmationDialog + message: { + if(offlineMapView._currentSelection.defaultSet) + return qsTr("This will delete all tiles INCLUDING the tile sets you have created yourself.\n\nIs this really what you want?"); + else + return qsTr("Delete %1 and all its tiles.\n\nIs this really what you want?").arg(offlineMapView._currentSelection.name); } - } - } - - Component { - id: deleteSystemSetConfirmationDialogComponent - - QGCViewMessage { - id: deleteSystemSetConfirmationDialog - message: qsTr("This will delete all tiles INCLUDING the tile sets you have created yourself.\n\nIs this really what you want?") - function accept() { QGroundControl.mapEngineManager.deleteTileSet(offlineMapView._currentSelection) - deleteSystemSetConfirmationDialog.hideDialog() + deleteConfirmationDialog.hideDialog() leaveInfoView() showList() } @@ -351,35 +335,26 @@ QGCView { mapControl: _map } + //----------------------------------------------------------------- //-- Show Set Info Rectangle { id: infoView - anchors.margins: ScreenTools.defaultFontPixelWidth - y: Math.max(anchors.margins, (parent.height - (anchors.margins * 2) - height) / 2) + anchors.margins: ScreenTools.defaultFontPixelHeight anchors.right: parent.right - width: Math.max(ScreenTools.defaultFontPixelWidth * 20, controlInfoFlickable.width + (infoView._margins * 2)) - height: Math.min(parent.height - (anchors.margins * 2), controlInfoFlickable.y + controlInfoColumn.height + ScreenTools.defaultFontPixelHeight) - color: qgcPal.window - opacity: 0.85 + anchors.verticalCenter: parent.verticalCenter + width: tileInfoColumn.width + (ScreenTools.defaultFontPixelWidth * 2) + height: tileInfoColumn.height + (ScreenTools.defaultFontPixelHeight * 2) + color: Qt.rgba(qgcPal.window.r, qgcPal.window.g, qgcPal.window.b, 0.85) radius: ScreenTools.defaultFontPixelWidth * 0.5 visible: false - - readonly property real _margins: ScreenTools.defaultFontPixelHeight / 2 - - QGCLabel { - anchors.margins: ScreenTools.defaultFontPixelHeight / 4 - anchors.top: parent.top - anchors.right: parent.right - text: "X" - } - + property bool _extraButton: !_defaultSet && ((!offlineMapView._currentSelection.complete && !offlineMapView._currentSelection.downloading) || (!offlineMapView._currentSelection.complete && offlineMapView._currentSelection.downloading)) + property real _labelWidth: ScreenTools.defaultFontPixelWidth * 10 + property real _valueWidth: ScreenTools.defaultFontPixelWidth * 14 Column { - id: titleColumn - anchors.margins: infoView._margins - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - + id: tileInfoColumn + anchors.margins: ScreenTools.defaultFontPixelHeight * 0.5 + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + anchors.centerIn: parent QGCLabel { anchors.left: parent.left anchors.right: parent.right @@ -388,222 +363,113 @@ QGCView { font.pointSize: _saveRealEstate ? ScreenTools.defaultFontPointSize : ScreenTools.mediumFontPointSize horizontalAlignment: Text.AlignHCenter } - QGCLabel { anchors.left: parent.left anchors.right: parent.right wrapMode: Text.WordWrap - text: offlineMapView._currentSelection ? offlineMapView._currentSelection.description : "" - visible: text !== qsTr("Description") + text: { + if(offlineMapView._currentSelection) { + if(offlineMapView._currentSelection.defaultSet) + return qsTr("System Wide Tile Cache"); + else + return "(" + offlineMapView._currentSelection.mapTypeStr + ")" + } else + return ""; + } horizontalAlignment: Text.AlignHCenter } - - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: offlineMapView._currentSelection ? "(" + offlineMapView._currentSelection.mapTypeStr + ")" : "" - horizontalAlignment: Text.AlignHCenter + //-- Tile Sets + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: !_defaultSet + QGCLabel { text: qsTr("Zoom Levels:"); width: infoView._labelWidth; } + QGCLabel { text: offlineMapView._currentSelection ? (offlineMapView._currentSelection.minZoom + " - " + offlineMapView._currentSelection.maxZoom) : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } } - - } - - MouseArea { - anchors.fill: titleColumn - preventStealing: true - - onClicked: { - leaveInfoView() - showList() + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: !_defaultSet + QGCLabel { text: qsTr("Total:"); width: infoView._labelWidth; } + QGCLabel { text: (offlineMapView._currentSelection ? offlineMapView._currentSelection.totalTileCountStr : "") + " (" + (offlineMapView._currentSelection ? offlineMapView._currentSelection.totalTilesSizeStr : "") + ")"; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: offlineMapView && offlineMapView._currentSelection && !_defaultSet && offlineMapView._currentSelection.uniqueTileCount > 0 + QGCLabel { text: qsTr("Unique:"); width: infoView._labelWidth; } + QGCLabel { text: (offlineMapView._currentSelection ? offlineMapView._currentSelection.uniqueTileCountStr : "") + " (" + (offlineMapView._currentSelection ? offlineMapView._currentSelection.uniqueTileSizeStr : "") + ")"; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } } - } - - QGCFlickable { - id: controlInfoFlickable - anchors.margins: infoView._margins - anchors.top: titleColumn.bottom - anchors.bottom: parent.bottom - anchors.left: parent.left - width: controlInfoColumn.width - clip: true - contentHeight: controlInfoColumn.height - - Column { - id: controlInfoColumn - spacing: ScreenTools.defaultFontPixelHeight - - GridLayout { - columns: 2 - rowSpacing: 0 - - QGCLabel { text: qsTr("Min Zoom:") } - QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.minZoom : "" } - - QGCLabel { text: qsTr("Max Zoom:") } - QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.maxZoom : "" } - - QGCLabel { text: qsTr("Total:") } - QGCLabel { text: (offlineMapView._currentSelection ? offlineMapView._currentSelection.numTilesStr : "") + " (" + (offlineMapView._currentSelection ? offlineMapView._currentSelection.tilesSizeStr : "") + ")" } - - QGCLabel { - text: qsTr("Downloaded:") - visible: offlineMapView._currentSelection && !offlineMapView._currentSelection.complete - } - QGCLabel { - text: (offlineMapView._currentSelection ? offlineMapView._currentSelection.savedTilesStr : "") + " (" + (offlineMapView._currentSelection ? offlineMapView._currentSelection.savedSizeStr : "") + ")" - visible: offlineMapView._currentSelection && !offlineMapView._currentSelection.complete - } - - QGCLabel { - text: qsTr("Error Count:") - visible: offlineMapView._currentSelection && !offlineMapView._currentSelection.complete - } - QGCLabel { - text: offlineMapView._currentSelection ? offlineMapView._currentSelection.errorCountStr : "" - visible: offlineMapView._currentSelection && !offlineMapView._currentSelection.complete - } - } + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: offlineMapView && offlineMapView._currentSelection && !_defaultSet && !offlineMapView._currentSelection.complete + QGCLabel { text: qsTr("Downloaded:"); width: infoView._labelWidth; } + QGCLabel { text: (offlineMapView._currentSelection ? offlineMapView._currentSelection.savedTileCountStr : "") + " (" + (offlineMapView._currentSelection ? offlineMapView._currentSelection.savedTileSizeStr : "") + ")"; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: offlineMapView && offlineMapView._currentSelection && !_defaultSet && !offlineMapView._currentSelection.complete && offlineMapView._currentSelection.errorCount > 0 + QGCLabel { text: qsTr("Error Count:"); width: infoView._labelWidth; } + QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.errorCountStr : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } + } + //-- Default Tile Set + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: _defaultSet + QGCLabel { text: qsTr("Size:"); width: infoView._labelWidth; } + QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.savedTileSizeStr : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + visible: _defaultSet + QGCLabel { text: qsTr("Tile Count:"); width: infoView._labelWidth; } + QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.savedTileCountStr : ""; horizontalAlignment: Text.AlignRight; width: infoView._valueWidth; } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter QGCButton { text: qsTr("Resume Download") - visible: offlineMapView._currentSelection && (!offlineMapView._currentSelection.complete && !offlineMapView._currentSelection.downloading) - + visible: offlineMapView._currentSelection && offlineMapView._currentSelection && !_defaultSet && (!offlineMapView._currentSelection.complete && !offlineMapView._currentSelection.downloading) + width: ScreenTools.defaultFontPixelWidth * 16 onClicked: { if(offlineMapView._currentSelection) offlineMapView._currentSelection.resumeDownloadTask() } } - QGCButton { text: qsTr("Cancel Download") - visible: offlineMapView._currentSelection && (!offlineMapView._currentSelection.complete && offlineMapView._currentSelection.downloading) - + visible: offlineMapView._currentSelection && offlineMapView._currentSelection && !_defaultSet && (!offlineMapView._currentSelection.complete && offlineMapView._currentSelection.downloading) + width: ScreenTools.defaultFontPixelWidth * 16 onClicked: { if(offlineMapView._currentSelection) offlineMapView._currentSelection.cancelDownloadTask() } } - QGCButton { text: qsTr("Delete") + width: ScreenTools.defaultFontPixelWidth * (infoView._extraButton ? 6 : 10) onClicked: showDialog(deleteConfirmationDialogComponent, qsTr("Confirm Delete"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) } - } // Column - } // QGCFlickable - } // Rectangle - infoView - - //-- Show Default Set Info - Rectangle { - id: defaultInfoView - anchors.margins: ScreenTools.defaultFontPixelWidth - y: Math.max(anchors.margins, (parent.height - (anchors.margins * 2) - height) / 2) - anchors.right: parent.right - width: ScreenTools.defaultFontPixelWidth * 20 - height: Math.min(parent.height - (anchors.margins * 2), defaultControlInfoFlickable.y + defaultControlInfoColumn.height + ScreenTools.defaultFontPixelHeight) - color: qgcPal.window - opacity: 0.85 - radius: ScreenTools.defaultFontPixelWidth * 0.5 - visible: false - - QGCLabel { - anchors.margins: ScreenTools.defaultFontPixelHeight / 4 - anchors.top: parent.top - anchors.right: parent.right - text: "X" - } - - Column { - id: defaultTitleColumn - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: offlineMapView._currentSelection ? offlineMapView._currentSelection.name : "" - font.pointSize: _saveRealEstate ? ScreenTools.defaultFontPointSize : ScreenTools.mediumFontPointSize - horizontalAlignment: Text.AlignHCenter - } - - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: qsTr("System Wide Tile Cache") - horizontalAlignment: Text.AlignHCenter - } - } - - MouseArea { - anchors.fill: defaultTitleColumn - preventStealing: true - - onClicked: { - leaveInfoView() - showList() - } - } - - QGCFlickable { - id: defaultControlInfoFlickable - anchors.margins: ScreenTools.defaultFontPixelHeight - anchors.top: defaultTitleColumn.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - clip: true - contentHeight: defaultControlInfoColumn.height - - Column { - id: defaultControlInfoColumn - anchors.left: parent.left - anchors.right: parent.right - spacing: ScreenTools.defaultFontPixelHeight - - GridLayout { - columns: 2 - rowSpacing: 0 - - QGCLabel { - Layout.columnSpan: 2 - text: qsTr("System Cache") - } - - QGCLabel { text: qsTr("Size:") } - QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.tilesSizeStr : "" } - - QGCLabel { text: qsTr("Tile Count:") } - QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.numTilesStr : "" } - - Item { - width: 1 - height: ScreenTools.defaultFontPixelHeight - Layout.columnSpan: 2 - } - - QGCLabel { - Layout.columnSpan: 2 - text: qsTr("All Sets") - } - - QGCLabel { text: qsTr("Size:") } - QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.savedSizeStr : "" } - - QGCLabel { text: qsTr("Tile Count:") } - QGCLabel { text: offlineMapView._currentSelection ? offlineMapView._currentSelection.savedTilesStr : ""} - } - QGCButton { - text: qsTr("Delete All") - onClicked: showDialog(deleteSystemSetConfirmationDialogComponent, qsTr("Confirm Delete All"), qgcView.showDialogDefaultWidth, StandardButton.Yes | StandardButton.No) + text: qsTr("Close") + width: ScreenTools.defaultFontPixelWidth * (infoView._extraButton ? 6 : 10) + onClicked: { + leaveInfoView() + showList() + } } - } // Column - } // QGCFlickable - } // Rectangle - defaultInfoView + } + } + } // Rectangle - infoView + //----------------------------------------------------------------- + //-- Add new set Item { id: addNewSetView anchors.fill: parent @@ -667,13 +533,14 @@ QGCView { border.color: _mapAdjustedColor color: "transparent" visible: _showPreview - QGCLabel { - anchors.fill: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: _mapAdjustedColor - text: qsTr("Min Zoom: %1").arg(sliderMinZoom.value) + anchors.centerIn: parent + color: _mapAdjustedColor + text: qsTr("Min Zoom: %1").arg(sliderMinZoom.value) + } + MouseArea { + anchors.fill: parent + onClicked: _showPreview = false } } @@ -682,26 +549,15 @@ QGCView { border.color: _mapAdjustedColor color: "transparent" visible: _showPreview - QGCLabel { - anchors.fill: parent - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - color: _mapAdjustedColor - text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value) + anchors.centerIn: parent + color: _mapAdjustedColor + text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value) + } + MouseArea { + anchors.fill: parent + onClicked: _showPreview = false } - } - - MouseArea { - anchors.fill: minZoomPreview - visible: _showPreview - onClicked: _showPreview = false - } - - MouseArea { - anchors.fill: maxZoomPreview - visible: _showPreview - onClicked: _showPreview = false } QGCButton { @@ -715,21 +571,13 @@ QGCView { //-- Add new set dialog Rectangle { anchors.margins: ScreenTools.defaultFontPixelWidth - y: Math.max(anchors.margins, (parent.height - (anchors.margins * 2) - height) / 2) + anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right - width: ScreenTools.defaultFontPixelWidth * 20 + width: ScreenTools.defaultFontPixelWidth * 24 height: Math.min(parent.height - (anchors.margins * 2), addNewSetFlickable.y + addNewSetColumn.height + ScreenTools.defaultFontPixelHeight) - color: qgcPal.window - opacity: 0.85 + color: Qt.rgba(qgcPal.window.r, qgcPal.window.g, qgcPal.window.b, 0.85) radius: ScreenTools.defaultFontPixelWidth * 0.5 - QGCLabel { - anchors.margins: ScreenTools.defaultFontPixelHeight / 4 - anchors.top: parent.top - anchors.right: parent.right - text: "X" - } - QGCLabel { id: addNewSetLabel anchors.margins: ScreenTools.defaultFontPixelHeight / 2 @@ -742,12 +590,6 @@ QGCView { horizontalAlignment: Text.AlignHCenter } - MouseArea { - anchors.fill: addNewSetLabel - preventStealing: true - onClicked: showList() - } - QGCFlickable { id: addNewSetFlickable anchors.leftMargin: ScreenTools.defaultFontPixelWidth @@ -770,9 +612,7 @@ QGCView { Column { anchors.left: parent.left anchors.right: parent.right - QGCLabel { text: qsTr("Name:") } - QGCTextField { id: setName anchors.left: parent.left @@ -783,25 +623,21 @@ QGCView { Column { anchors.left: parent.left anchors.right: parent.right - QGCLabel { text: qsTr("Map type:") visible: !_saveRealEstate } - QGCComboBox { id: mapCombo anchors.left: parent.left anchors.right: parent.right model: QGroundControl.mapEngineManager.mapList - onActivated: { mapType = textAt(index) if(_dropButtonsExclusiveGroup.current) _dropButtonsExclusiveGroup.current.checked = false _dropButtonsExclusiveGroup.current = null } - Component.onCompleted: { var index = mapCombo.find(mapType) if (index === -1) { @@ -823,7 +659,7 @@ QGCView { Column { id: zoomColumn - anchors.margins: ScreenTools.defaultFontPixelHeight / 4 + anchors.margins: ScreenTools.defaultFontPixelHeight * 0.25 anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right @@ -842,11 +678,8 @@ QGCView { maximumValue: maxZoomLevel stepSize: 1 updateValueWhileDragging: true - property real _savedZoom - - Component.onCompleted: sliderMinZoom.value = _map.zoomLevel - 2 - + Component.onCompleted: Math.max(sliderMinZoom.value = _map.zoomLevel - 4, 2) onValueChanged: { if(sliderMinZoom.value > sliderMaxZoom.value) { sliderMaxZoom.value = sliderMinZoom.value @@ -856,8 +689,8 @@ QGCView { } // Slider - min zoom QGCLabel { - text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value) - font.pointSize: _adjustableFontPointSize + text: qsTr("Max Zoom: %1").arg(sliderMaxZoom.value) + font.pointSize: _adjustableFontPointSize } Slider { @@ -869,11 +702,8 @@ QGCView { maximumValue: maxZoomLevel stepSize: 1 updateValueWhileDragging: true - property real _savedZoom - - Component.onCompleted: sliderMaxZoom.value = _map.zoomLevel + 2 - + Component.onCompleted: Math.min(sliderMaxZoom.value = _map.zoomLevel + 2, 20) onValueChanged: { if(sliderMaxZoom.value < sliderMinZoom.value) { sliderMinZoom.value = sliderMaxZoom.value @@ -885,18 +715,17 @@ QGCView { GridLayout { columns: 2 rowSpacing: 0 - QGCLabel { - text: qsTr("Tile Count") + text: qsTr("Count:") font.pointSize: _adjustableFontPointSize } QGCLabel { - text: QGroundControl.mapEngineManager.tileCountStr + text: QGroundControl.mapEngineManager.tileCountStr font.pointSize: _adjustableFontPointSize } QGCLabel { - text: qsTr("Set Size (Est)") + text: qsTr("Est Size:") font.pointSize: _adjustableFontPointSize } QGCLabel { @@ -907,27 +736,30 @@ QGCView { } // Column - Zoom info } // Rectangle - Zoom info - QGCButton { - text: _tooManyTiles ? qsTr("Too many tiles") : qsTr("Download") - enabled: !_tooManyTiles && setName.text.length > 0 + Row { + spacing: ScreenTools.defaultFontPixelWidth anchors.horizontalCenter: parent.horizontalCenter - - property bool _tooManyTiles: QGroundControl.mapEngineManager.tileCount > _maxTilesForDownload - - onClicked: { - if(QGroundControl.mapEngineManager.findName(setName.text)) { - duplicateName.visible = true - } else { - /* This does not work if hosted by QQuickWidget. Waiting until we're 100% QtQuick - var mapImage - _map.grabToImage(function(result) { mapImage = result; }) - QGroundControl.mapEngineManager.startDownload(setName.text, "Description", mapType, mapImage); - */ - QGroundControl.mapEngineManager.startDownload(setName.text, "Description" /* Description */, mapType); + QGCButton { + text: _tooManyTiles ? qsTr("Too many tiles") : qsTr("Download") + enabled: !_tooManyTiles && setName.text.length > 0 + property bool _tooManyTiles: QGroundControl.mapEngineManager.tileCount > _maxTilesForDownload + onClicked: { + if(QGroundControl.mapEngineManager.findName(setName.text)) { + duplicateName.visible = true + } else { + QGroundControl.mapEngineManager.startDownload(setName.text, mapType); + showList() + } + } + } + QGCButton { + text: qsTr("Cancel") + onClicked: { showList() } } } + } // Column } // QGCFlickable } // Rectangle - Add new set dialog @@ -965,6 +797,7 @@ QGCView { delegate: OfflineMapButton { text: object.name size: object.downloadStatus + tiles: object.totalTileCount complete: object.complete width: firstButton.width height: ScreenTools.defaultFontPixelHeight * 2 diff --git a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc index cce88da7f..e05dfeb34 100644 --- a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc +++ b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc @@ -127,10 +127,10 @@ QGCMapEngineManager::_tileSetFetched(QGCCachedTileSet* tileSet) //----------------------------------------------------------------------------- void -QGCMapEngineManager::startDownload(const QString& name, const QString& description, const QString& mapType, const QImage& image) +QGCMapEngineManager::startDownload(const QString& name, const QString& mapType) { if(_totalSet.tileSize) { - QGCCachedTileSet* set = new QGCCachedTileSet(name, description); + QGCCachedTileSet* set = new QGCCachedTileSet(name); set->setMapTypeStr(mapType); set->setTopleftLat(_topleftLat); set->setTopleftLon(_topleftLon); @@ -138,11 +138,9 @@ QGCMapEngineManager::startDownload(const QString& name, const QString& descripti set->setBottomRightLon(_bottomRightLon); set->setMinZoom(_minZoom); set->setMaxZoom(_maxZoom); - set->setTilesSize(_totalSet.tileSize); - set->setNumTiles(_totalSet.tileCount); + set->setTotalTileSize(_totalSet.tileSize); + set->setTotalTileCount(_totalSet.tileCount); set->setType(QGCMapEngine::getTypeFromName(mapType)); - if(!image.isNull()) - set->setThumbNail(image); QGCCreateTileSetTask* task = new QGCCreateTileSetTask(set); //-- Create Tile Set (it will also create a list of tiles to download) connect(task, &QGCCreateTileSetTask::tileSetSaved, this, &QGCMapEngineManager::_tileSetSaved); @@ -329,10 +327,10 @@ QGCMapEngineManager::_updateTotals(quint32 totaltiles, quint64 totalsize, quint3 QGCCachedTileSet* set = qobject_cast(_tileSets.get(i)); Q_ASSERT(set); if (set->defaultSet()) { - set->setSavedSize(totalsize); - set->setSavedTiles(totaltiles); - set->setNumTiles(defaulttiles); - set->setTilesSize(defaultsize); + set->setSavedTileSize(totalsize); + set->setSavedTileCount(totaltiles); + set->setTotalTileCount(defaulttiles); + set->setTotalTileSize(defaultsize); return; } } diff --git a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h index ee56cc625..e168c6b7f 100644 --- a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h +++ b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h @@ -49,7 +49,7 @@ public: Q_INVOKABLE void loadTileSets (); Q_INVOKABLE void updateForCurrentView (double lon0, double lat0, double lon1, double lat1, int minZoom, int maxZoom, const QString& mapName); - Q_INVOKABLE void startDownload (const QString& name, const QString& description, const QString& mapType, const QImage& image = QImage()); + Q_INVOKABLE void startDownload (const QString& name, const QString& mapType); Q_INVOKABLE void saveSetting (const QString& key, const QString& value); Q_INVOKABLE QString loadSetting (const QString& key, const QString& defaultValue); Q_INVOKABLE void deleteTileSet (QGCCachedTileSet* tileSet); -- 2.22.0