4#include <QtCore/QCoreApplication>
5#include <QtCore/QSettings>
13#ifdef QGC_UNITTEST_BUILD
19#ifdef QGC_UNITTEST_BUILD
20std::function<
QGCCacheTile*(
const QString&)> QGCCacheWorker::_unitTestTileGenerator;
22void QGCCacheWorker::setUnitTestTileGenerator(std::function<
QGCCacheTile*(
const QString &hash)> generator)
24 _unitTestTileGenerator = std::move(generator);
31 qCDebug(QGCTileCacheWorkerLog) <<
this;
38 qCDebug(QGCTileCacheWorkerLog) <<
this;
43 _stopRequested =
true;
44 QMutexLocker lock(&_taskQueueMutex);
45 qDeleteAll(_taskQueue);
57 task->
setError(tr(
"Database Not Initialized"));
62 QMutexLocker lock(&_taskQueueMutex);
63 _taskQueue.enqueue(task);
69 start(QThread::NormalPriority);
77 _stopRequested =
false;
78 _database = std::make_unique<QGCTileCacheDatabase>(_databasePath);
80 if (!_database->init()) {
81 qCWarning(QGCTileCacheWorkerLog) <<
"Failed To Init Database";
84 QMutexLocker lock(&_taskQueueMutex);
86 orphan->setError(tr(
"Database Init Failed"));
87 orphan->deleteLater();
93 if (_database->isValid()) {
94 if (_database->connectDB()) {
95 _database->deleteBingNoTileTiles();
99 _dbValid = _database->isValid();
101 _updateTimer.start();
103 QMutexLocker lock(&_taskQueueMutex);
104 while (!_stopRequested) {
105 if (!_taskQueue.isEmpty()) {
106 QGCMapTask*
const task = _taskQueue.dequeue();
112 const qsizetype count = _taskQueue.count();
114 _updateTimeout = kLongTimeoutMs;
115 }
else if (count < 25) {
116 _updateTimeout = kShortTimeoutMs;
119 if ((count == 0) || _updateTimer.hasExpired(_updateTimeout)) {
120 if (_database && _database->isValid()) {
127 (void) _waitc.wait(lock.mutex(), 5000);
132 orphan->setError(tr(
"Worker shutting down"));
133 orphan->deleteLater();
140 _database->disconnectDB();
145void QGCCacheWorker::_runTask(
QGCMapTask *task)
147 switch (task->
type()) {
160 _createTileSet(task);
163 _getTileDownloadList(task);
166 _updateTileDownloadState(task);
169 _deleteTileSet(task);
172 _renameTileSet(task);
178 _resetCacheDatabase(task);
187 qCWarning(QGCTileCacheWorkerLog) <<
"given unhandled task type" << task->
type();
192bool QGCCacheWorker::_testTask(
QGCMapTask *mtask)
194 if (!_database || !_database->isValid()) {
195 mtask->
setError(
"No Cache Database");
202void QGCCacheWorker::_emitTotals()
206 _updateTimer.restart();
209void QGCCacheWorker::_saveTile(
QGCMapTask *mtask)
211 if (!_testTask(mtask)) {
218 mtask->
setError(
"Error saving tile to cache");
222void QGCCacheWorker::_getTile(
QGCMapTask *mtask)
224 if (!_testTask(mtask)) {
229 auto tile = _database->getTile(task->
hash());
238#ifdef QGC_UNITTEST_BUILD
248 task->
setError(
"Tile not in cache database");
251void QGCCacheWorker::_getTileSets(
QGCMapTask *mtask)
253 if (!_testTask(mtask)) {
258 const QList<TileSetRecord> records = _database->getTileSets();
260 for (
const auto &rec : records) {
262 set->blockSignals(
true);
264 set->
setId(rec.setID);
277 const SetTotalsResult totals = _database->computeSetTotals(rec.setID, rec.defaultSet, rec.numTiles, set->
type());
284 set->blockSignals(
false);
285 (void) set->moveToThread(QCoreApplication::instance()->thread());
290void QGCCacheWorker::_createTileSet(
QGCMapTask *mtask)
292 if (!_testTask(mtask)) {
297 const auto setID = _database->createTileSet(
304 if (!setID.has_value()) {
305 mtask->
setError(
"Error saving tile set");
309 task->
tileSet()->blockSignals(
true);
320 task->
tileSet()->blockSignals(
false);
325void QGCCacheWorker::_getTileDownloadList(
QGCMapTask *mtask)
327 if (!_testTask(mtask)) {
332 const QList<QGCTile> tileValues = _database->getTileDownloadList(task->
setID(), task->
count());
333 QQueue<QGCTile*> tiles;
334 for (
const auto &t : tileValues) {
340void QGCCacheWorker::_updateTileDownloadState(
QGCMapTask *mtask)
342 if (!_testTask(mtask)) {
348 if (task->
hash() == QStringLiteral(
"*")) {
349 ok = _database->updateAllTileDownloadStates(task->
setID(),
static_cast<int>(task->
state()));
351 ok = _database->updateTileDownloadState(task->
setID(),
static_cast<int>(task->
state()), task->
hash());
354 mtask->
setError(
"Error updating tile download state");
358void QGCCacheWorker::_pruneCache(
QGCMapTask *mtask)
360 if (!_testTask(mtask)) {
365 if (!_database->pruneCache(task->
amount())) {
366 mtask->
setError(
"Error pruning cache");
372void QGCCacheWorker::_deleteTileSet(
QGCMapTask *mtask)
374 if (!_testTask(mtask)) {
379 if (!_database->deleteTileSet(task->
setID())) {
380 mtask->
setError(
"Error deleting tile set");
387void QGCCacheWorker::_renameTileSet(
QGCMapTask *mtask)
389 if (!_testTask(mtask)) {
394 if (!_database->renameTileSet(task->
setID(), task->
newName())) {
395 task->
setError(
"Error renaming tile set");
399void QGCCacheWorker::_resetCacheDatabase(
QGCMapTask *mtask)
401 if (!_testTask(mtask)) {
406 if (!_database->resetDatabase()) {
407 mtask->
setError(
"Error resetting cache database");
410 _dbValid = _database->isValid();
414void QGCCacheWorker::_importSets(
QGCMapTask *mtask)
416 if (!_testTask(mtask)) {
421 auto progress = [task](
int pct) { task->
setProgress(pct); };
425 result = _database->importSetsReplace(task->
path(), progress);
427 result = _database->importSetsMerge(task->
path(), progress);
430 _dbValid = _database->isValid();
437 if (task->
replace() && _database->isValid()) {
440 _database->deleteBingNoTileTiles();
446void QGCCacheWorker::_exportSets(
QGCMapTask *mtask)
448 if (!_testTask(mtask)) {
454 auto progress = [task](
int pct) { task->
setProgress(pct); };
#define QGC_LOGGING_CATEGORY(name, categoryStr)
bool enqueueTask(QGCMapTask *task)
void updateTotals(quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize)
QGCCacheWorker(QObject *parent=nullptr)
void setTotalTileCount(quint32 num)
double bottomRightLon() const
double topleftLat() const
void setUniqueTileCount(quint32 num)
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 setDefaultSet(bool def)
quint32 totalTileCount() const
const QString & name() const
void setBottomRightLon(double lon)
void setType(const QString &type)
const QString & mapTypeStr() const
void setBottomRightLat(double lat)
void setCreationDate(const QDateTime &date)
void setMapTypeStr(const QString &typeStr)
double bottomRightLat() const
void setUniqueTileSize(quint64 size)
void setTopleftLon(double lon)
QGCCachedTileSet * tileSet()
void setProgress(int percentage)
void setExportCompleted()
const QList< TileSetRecord > & sets() const
void setTileSetFetched(QGCCachedTileSet *tileSet)
void setTileFetched(QGCCacheTile *tile)
void setTileListFetched(const QQueue< QGCTile * > &tiles)
void setImportCompleted()
void setProgress(int percentage)
void setError(const QString &errorString=QString())
@ taskUpdateTileDownloadState
@ taskGetTileDownloadList
const QGCCacheTile * tile() const
static constexpr const char * kBingNoTileDoneKey
QGCTile::TileState state() const
static QString getProviderTypeFromQtMapId(int qtMapId)