地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

406 lines
13 KiB

/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Gus Grubba <mavlink@grubba.com>
#include "QGCMapEngineManager.h"
#include "QGCApplication.h"
#include <QSettings>
#include "QGCMapTileSet.h"
#include "QGCMapUrlEngine.h"
#include <QStorageInfo>
QGC_LOGGING_CATEGORY(QGCMapEngineManagerLog, "QGCMapEngineManagerLog")
static const char* kQmlOfflineMapKeyName = "QGCOfflineMap";
//-----------------------------------------------------------------------------
QGCMapEngineManager::QGCMapEngineManager(QGCApplication* app)
: QGCTool(app)
, _topleftLat(0.0)
, _topleftLon(0.0)
, _bottomRightLat(0.0)
, _bottomRightLon(0.0)
, _minZoom(0)
, _maxZoom(0)
, _setID(UINT64_MAX)
, _freeDiskSpace(0)
, _diskSpace(0)
{
}
//-----------------------------------------------------------------------------
QGCMapEngineManager::~QGCMapEngineManager()
{
_tileSets.clear();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::setToolbox(QGCToolbox *toolbox)
{
QGCTool::setToolbox(toolbox);
QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
qmlRegisterUncreatableType<QGCMapEngineManager>("QGroundControl.QGCMapEngineManager", 1, 0, "QGCMapEngineManager", "Reference only");
connect(getQGCMapEngine(), &QGCMapEngine::updateTotals, this, &QGCMapEngineManager::_updateTotals);
_updateDiskFreeSpace();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::updateForCurrentView(double lon0, double lat0, double lon1, double lat1, int minZoom, int maxZoom, const QString& mapName)
{
UrlFactory::MapType mapType = QGCMapEngine::getTypeFromName(mapName);
_topleftLat = lat0;
_topleftLon = lon0;
_bottomRightLat = lat1;
_bottomRightLon = lon1;
_minZoom = minZoom;
_maxZoom = maxZoom;
_totalSet.clear();
for(int z = minZoom; z <= maxZoom; z++) {
QGCTileSet set = QGCMapEngine::getTileCount(z, lon0, lat0, lon1, lat1, mapType);
_totalSet += set;
}
//-- Beyond 100,000,000 tiles is just nuts
if(_totalSet.tileCount > 100 * 1000 * 1000) {
_crazySize = true;
emit crazySizeChanged();
} else {
_crazySize = false;
emit crazySizeChanged();
emit tileX0Changed();
emit tileX1Changed();
emit tileY0Changed();
emit tileY1Changed();
emit tileCountChanged();
emit tileSizeChanged();
}
}
//-----------------------------------------------------------------------------
QString
QGCMapEngineManager::tileCountStr()
{
return QGCMapEngine::numberToString(_totalSet.tileCount);
}
//-----------------------------------------------------------------------------
QString
QGCMapEngineManager::tileSizeStr()
{
return QGCMapEngine::bigSizeToString(_totalSet.tileSize);
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::loadTileSets()
{
if(_tileSets.count()) {
_tileSets.clear();
emit tileSetsChanged();
}
QGCFetchTileSetTask* task = new QGCFetchTileSetTask();
connect(task, &QGCFetchTileSetTask::tileSetFetched, this, &QGCMapEngineManager::_tileSetFetched);
connect(task, &QGCMapTask::error, this, &QGCMapEngineManager::taskError);
getQGCMapEngine()->addTask(task);
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::_tileSetFetched(QGCCachedTileSet* tileSet)
{
//-- A blank (default) type means it uses various types and not just one
if(tileSet->type() == UrlFactory::Invalid) {
tileSet->setMapTypeStr("Various");
}
_tileSets.append(tileSet);
tileSet->setManager(this);
emit tileSetsChanged();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::startDownload(const QString& name, const QString& description, const QString& mapType, const QImage& image)
{
if(_totalSet.tileSize) {
QGCCachedTileSet* set = new QGCCachedTileSet(name, description);
set->setMapTypeStr(mapType);
set->setTopleftLat(_topleftLat);
set->setTopleftLon(_topleftLon);
set->setBottomRightLat(_bottomRightLat);
set->setBottomRightLon(_bottomRightLon);
set->setMinZoom(_minZoom);
set->setMaxZoom(_maxZoom);
set->setTilesSize(_totalSet.tileSize);
set->setNumTiles(_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);
connect(task, &QGCMapTask::error, this, &QGCMapEngineManager::taskError);
getQGCMapEngine()->addTask(task);
} else {
qWarning() << "QGCMapEngineManager::startDownload() No Tiles to save";
}
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::_tileSetSaved(QGCCachedTileSet *set)
{
qCDebug(QGCMapEngineManagerLog) << "New tile set saved (" << set->name() << "). Starting download...";
_tileSets.append(set);
emit tileSetsChanged();
//-- Start downloading tiles
set->createDownloadTask();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::saveSetting (const QString& key, const QString& value)
{
QSettings settings;
settings.beginGroup(kQmlOfflineMapKeyName);
settings.setValue(key, value);
}
//-----------------------------------------------------------------------------
QString
QGCMapEngineManager::loadSetting (const QString& key, const QString& defaultValue)
{
QSettings settings;
settings.beginGroup(kQmlOfflineMapKeyName);
return settings.value(key, defaultValue).toString();
}
//-----------------------------------------------------------------------------
QStringList
QGCMapEngineManager::mapList()
{
return getQGCMapEngine()->getMapNameList();
}
//-----------------------------------------------------------------------------
QString
QGCMapEngineManager::mapboxToken()
{
return getQGCMapEngine()->getMapBoxToken();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::setMapboxToken(QString token)
{
getQGCMapEngine()->setMapBoxToken(token);
}
//-----------------------------------------------------------------------------
quint32
QGCMapEngineManager::maxMemCache()
{
return getQGCMapEngine()->getMaxMemCache();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::setMaxMemCache(quint32 size)
{
getQGCMapEngine()->setMaxMemCache(size);
}
//-----------------------------------------------------------------------------
quint32
QGCMapEngineManager::maxDiskCache()
{
return getQGCMapEngine()->getMaxDiskCache();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::setMaxDiskCache(quint32 size)
{
getQGCMapEngine()->setMaxDiskCache(size);
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::deleteTileSet(QGCCachedTileSet* tileSet)
{
qCDebug(QGCMapEngineManagerLog) << "Deleting tile set " << tileSet->name();
//-- If deleting default set, delete it all
if(tileSet->defaultSet()) {
for(int i = 0; i < _tileSets.count(); i++ ) {
QGCCachedTileSet* set = qobject_cast<QGCCachedTileSet*>(_tileSets.get(i));
Q_ASSERT(set);
set->setDeleting(true);
}
QGCResetTask* task = new QGCResetTask();
connect(task, &QGCResetTask::resetCompleted, this, &QGCMapEngineManager::_resetCompleted);
connect(task, &QGCMapTask::error, this, &QGCMapEngineManager::taskError);
getQGCMapEngine()->addTask(task);
} else {
tileSet->setDeleting(true);
QGCDeleteTileSetTask* task = new QGCDeleteTileSetTask(tileSet->setID());
connect(task, &QGCDeleteTileSetTask::tileSetDeleted, this, &QGCMapEngineManager::_tileSetDeleted);
connect(task, &QGCMapTask::error, this, &QGCMapEngineManager::taskError);
getQGCMapEngine()->addTask(task);
}
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::_resetCompleted()
{
//-- Reload sets
loadTileSets();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::_tileSetDeleted(quint64 setID)
{
//-- Tile Set successfully deleted
QGCCachedTileSet* setToDelete = NULL;
int i = 0;
for(i = 0; i < _tileSets.count(); i++ ) {
QGCCachedTileSet* set = qobject_cast<QGCCachedTileSet*>(_tileSets.get(i));
Q_ASSERT(set);
if (set->setID() == setID) {
setToDelete = set;
break;
}
}
if(setToDelete) {
_tileSets.removeAt(i);
delete setToDelete;
}
emit tileSetsChanged();
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::taskError(QGCMapTask::TaskType type, QString error)
{
QString task;
switch(type) {
case QGCMapTask::taskFetchTileSets:
task = "Fetch Tile Set";
break;
case QGCMapTask::taskCreateTileSet:
task = "Create Tile Set";
break;
case QGCMapTask::taskGetTileDownloadList:
task = "Get Tile Download List";
break;
case QGCMapTask::taskUpdateTileDownloadState:
task = "Update Tile Download Status";
break;
case QGCMapTask::taskDeleteTileSet:
task = "Delete Tile Set";
break;
case QGCMapTask::taskReset:
task = "Reset Tile Sets";
break;
default:
task = "Database Error";
break;
}
QString serror = "Error in task: " + task;
serror += "\nError description:\n";
serror += error;
qWarning() << "QGCMapEngineManager::_taskError()";
setErrorMessage(serror);
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::_updateTotals(quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize)
{
for(int i = 0; i < _tileSets.count(); i++ ) {
QGCCachedTileSet* set = qobject_cast<QGCCachedTileSet*>(_tileSets.get(i));
Q_ASSERT(set);
if (set->defaultSet()) {
set->setSavedSize(totalsize);
set->setSavedTiles(totaltiles);
set->setNumTiles(defaulttiles);
set->setTilesSize(defaultsize);
return;
}
}
_updateDiskFreeSpace();
}
//-----------------------------------------------------------------------------
bool
QGCMapEngineManager::findName(const QString& name)
{
for(int i = 0; i < _tileSets.count(); i++ ) {
QGCCachedTileSet* set = qobject_cast<QGCCachedTileSet*>(_tileSets.get(i));
Q_ASSERT(set);
if (set->name() == name) {
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
QString
QGCMapEngineManager::getUniqueName()
{
QString test = "Tile Set ";
QString name;
int count = 1;
while (true) {
char numb[16];
snprintf(numb, sizeof(numb), "%03d", count++);
name = test;
name += numb;
if(!findName(name))
return name;
}
}
//-----------------------------------------------------------------------------
void
QGCMapEngineManager::_updateDiskFreeSpace()
{
QString path = getQGCMapEngine()->getCachePath();
if(!path.isEmpty()) {
QStorageInfo info(path);
quint32 total = (quint32)(info.bytesTotal() / 1024);
quint32 free = (quint32)(info.bytesFree() / 1024);
qCDebug(QGCMapEngineManagerLog) << info.rootPath() << "has" << free << "Mbytes available.";
if(_freeDiskSpace != free) {
_freeDiskSpace = free;
_diskSpace = total;
emit freeDiskSpaceChanged();
}
}
}