diff --git a/src/QtLocationPlugin/QGCMapEngineData.h b/src/QtLocationPlugin/QGCMapEngineData.h index 63401f4b75f972398ce9bee344355487db5484da..345d146c041263735b52685bd0bf992ade486ab0 100644 --- a/src/QtLocationPlugin/QGCMapEngineData.h +++ b/src/QtLocationPlugin/QGCMapEngineData.h @@ -389,12 +389,19 @@ public: emit exportCompleted(); } + void setProgress(int percentage) + { + emit exportProgress(percentage); + } + private: QVector _sets; QString _path; signals: - void exportCompleted(); + void exportCompleted (); + void exportProgress (int percentage); + }; diff --git a/src/QtLocationPlugin/QGCTileCacheWorker.cpp b/src/QtLocationPlugin/QGCTileCacheWorker.cpp index 01382a6a1cd40f0547bd9299f1df51b27864ca61..6b81ae456f1c66a354e926fca685c620539f2a7a 100644 --- a/src/QtLocationPlugin/QGCTileCacheWorker.cpp +++ b/src/QtLocationPlugin/QGCTileCacheWorker.cpp @@ -641,27 +641,40 @@ QGCCacheWorker::_exportSets(QGCMapTask* mtask) if(!_testTask(mtask)) { return; } - bool res = false; QGCExportTileTask* task = static_cast(mtask); + //-- Delete target if it exists + QFile file(task->path()); + file.remove(); //-- Create exported database QSqlDatabase *dbExport = new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE", kExportSession)); dbExport->setDatabaseName(task->path()); dbExport->setConnectOptions("QSQLITE_ENABLE_SHARED_CACHE"); if (dbExport->open()) { if(_createDB(dbExport, false)) { + //-- Prepare progress report + quint64 tileCount = 0; + quint64 currentCount = 0; + for(int i = 0; i < task->sets().count(); i++) { + QGCCachedTileSet* set = task->sets()[i]; + //-- Default set has no unique tiles + if(set->defaultSet()) { + tileCount += set->totalTileCount(); + } else { + tileCount += set->uniqueTileCount(); + } + } + if(!tileCount) { + tileCount = 1; + } //-- Iterate sets to save for(int i = 0; i < task->sets().count(); i++) { QGCCachedTileSet* set = task->sets()[i]; //-- Create Tile Exported Set QSqlQuery exportQuery(*dbExport); exportQuery.prepare("INSERT INTO TileSets(" - "name, typeStr, topleftLat, topleftLon, bottomRightLat, bottomRightLon, minZoom, maxZoom, type, numTiles, date" - ") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - QString name = set->name(); - if(set->defaultSet()) { - name = "Exported Default Set"; - } - exportQuery.addBindValue(name); + "name, typeStr, topleftLat, topleftLon, bottomRightLat, bottomRightLon, minZoom, maxZoom, type, numTiles, defaultSet, date" + ") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + exportQuery.addBindValue(set->name()); exportQuery.addBindValue(set->mapTypeStr()); exportQuery.addBindValue(set->topleftLat()); exportQuery.addBindValue(set->topleftLon()); @@ -671,6 +684,7 @@ QGCCacheWorker::_exportSets(QGCMapTask* mtask) exportQuery.addBindValue(set->maxZoom()); exportQuery.addBindValue(set->type()); exportQuery.addBindValue(set->totalTileCount()); + exportQuery.addBindValue(set->defaultSet()); exportQuery.addBindValue(QDateTime::currentDateTime().toTime_t()); if(!exportQuery.exec()) { task->setError("Error adding tile set to exported database"); @@ -682,6 +696,7 @@ QGCCacheWorker::_exportSets(QGCMapTask* mtask) QString s = QString("SELECT * FROM SetTiles WHERE setID = %1").arg(set->id()); QSqlQuery query(*_db); if(query.exec(s)) { + dbExport->transaction(); while(query.next()) { quint64 tileID = query.value("tileID").toULongLong(); //-- Get tile @@ -706,11 +721,14 @@ QGCCacheWorker::_exportSets(QGCMapTask* mtask) QString s = QString("INSERT INTO SetTiles(tileID, setID) VALUES(%1, %2)").arg(exportTileID).arg(exportSetID); exportQuery.prepare(s); exportQuery.exec(); + currentCount++; + task->setProgress((int)((double)currentCount / (double)tileCount * 100.0)); } } } } } + dbExport->commit(); } } } else { @@ -721,9 +739,7 @@ QGCCacheWorker::_exportSets(QGCMapTask* mtask) task->setError("Error opening export database"); } delete dbExport; - if(res) { - task->setExportCompleted(); - } + task->setExportCompleted(); } //----------------------------------------------------------------------------- diff --git a/src/QtLocationPlugin/QMLControl/OfflineMap.qml b/src/QtLocationPlugin/QMLControl/OfflineMap.qml index 7a70d672a425fa3a2bb9858376c1c20e2b515e4f..49100ee87f383fb9f13ff7921b825ca1e917df1b 100644 --- a/src/QtLocationPlugin/QMLControl/OfflineMap.qml +++ b/src/QtLocationPlugin/QMLControl/OfflineMap.qml @@ -39,6 +39,7 @@ QGCView { property bool _defaultSet: offlineMapView && offlineMapView._currentSelection && offlineMapView._currentSelection.defaultSet property real _margins: ScreenTools.defaultFontPixelWidth * 0.5 property real _buttonSize: ScreenTools.defaultFontPixelWidth * 12 + property real _bigButtonSize: ScreenTools.defaultFontPixelWidth * 16 property bool _saveRealEstate: ScreenTools.isTinyScreen || ScreenTools.isShortScreen property real _adjustableFontPointSize: _saveRealEstate ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize @@ -850,8 +851,8 @@ QGCView { visible: _tileSetList.visible spacing: _margins anchors.bottom: parent.bottom - anchors.right: parent.right anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter QGCButton { text: qsTr("Import") width: _buttonSize @@ -907,21 +908,31 @@ QGCView { visible: _exporTiles.visible spacing: _margins anchors.bottom: parent.bottom - anchors.right: parent.right anchors.margins: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter QGCButton { - text: qsTr("All") - width: _buttonSize + text: qsTr("Select All") + width: _bigButtonSize onClicked: QGroundControl.mapEngineManager.selectAll() } QGCButton { - text: qsTr("None") - width: _buttonSize + text: qsTr("Select None") + width: _bigButtonSize onClicked: QGroundControl.mapEngineManager.selectNone() } QGCButton { - text: qsTr("Export") - width: _buttonSize + text: qsTr("Export to Disk") + width: _bigButtonSize + enabled: QGroundControl.mapEngineManager.selectedCount > 0 + onClicked: { + showList(); + QGroundControl.mapEngineManager.exportSets() + rootLoader.sourceComponent = exportToDiskProgress + } + } + QGCButton { + text: qsTr("Export to Device") + width: _bigButtonSize enabled: QGroundControl.mapEngineManager.selectedCount > 0 onClicked: { QGroundControl.mapEngineManager.exportSets() @@ -930,9 +941,64 @@ QGCView { } QGCButton { text: qsTr("Cancel") - width: _buttonSize + width: _bigButtonSize onClicked: showList() } } } // QGCViewPanel + + Component { + id: exportToDiskProgress + Rectangle { + width: mainWindow.width + height: mainWindow.height + color: "black" + anchors.centerIn: parent + Rectangle { + width: parent.width * 0.5 + height: cameraSettingsCol.height * 1.25 + radius: ScreenTools.defaultFontPixelWidth + color: qgcPal.windowShadeDark + border.color: qgcPal.text + anchors.centerIn: parent + Column { + id: cameraSettingsCol + spacing: ScreenTools.defaultFontPixelHeight + width: parent.width + anchors.centerIn: parent + QGCLabel { + text: QGroundControl.mapEngineManager.exporting ? qsTr("Tile Set Export Progress") : qsTr("Tile Set Export Completed") + font.family: ScreenTools.demiboldFontFamily + font.pointSize: ScreenTools.mediumFontPointSize + anchors.horizontalCenter: parent.horizontalCenter + } + ProgressBar { + id: progressBar + width: parent.width * 0.45 + maximumValue: 100 + value: QGroundControl.mapEngineManager.exportProgress + anchors.horizontalCenter: parent.horizontalCenter + } + BusyIndicator { + visible: QGroundControl.mapEngineManager.exporting + running: QGroundControl.mapEngineManager.exporting + width: exportCloseButton.height + height: exportCloseButton.height + anchors.horizontalCenter: parent.horizontalCenter + } + QGCButton { + id: exportCloseButton + text: qsTr("Close") + width: _buttonSize + visible: !QGroundControl.mapEngineManager.exporting + anchors.horizontalCenter: parent.horizontalCenter + onClicked: { + rootLoader.sourceComponent = null + } + } + } + } + } + } + } // QGCView diff --git a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc index c8f9a63a7957a9207812336ce033e614281a155a..05b5b9aaf648748f4c4bc02cc676c183c8cdde7e 100644 --- a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc +++ b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc @@ -11,6 +11,11 @@ /// @file /// @author Gus Grubba +#if !defined(__mobile__) +#include "QGCFileDialog.h" +#include "MainWindow.h" +#endif + #include "QGCMapEngineManager.h" #include "QGCApplication.h" #include "QGCMapTileSet.h" @@ -36,6 +41,8 @@ QGCMapEngineManager::QGCMapEngineManager(QGCApplication* app) , _setID(UINT64_MAX) , _freeDiskSpace(0) , _diskSpace(0) + , _exportProgress(0) + , _exporting(false) { } @@ -389,33 +396,59 @@ QGCMapEngineManager::selectedCount() { } //----------------------------------------------------------------------------- -void +bool QGCMapEngineManager::exportSets(QString path) { QString dir = path; if(dir.isEmpty()) { +#if defined(__mobile__) dir = QDir(QDir::homePath()).filePath(QString("export_%1.db").arg(QDateTime::currentDateTime().toTime_t())); +#else + dir = QGCFileDialog::getSaveFileName( + MainWindow::instance(), + "Export Tile Set", + QDir::homePath(), + "Tile Sets (*.qgctiledb)", + "qgctiledb", + true); +#endif } - QVector sets; - for(int i = 0; i < _tileSets.count(); i++ ) { - QGCCachedTileSet* set = qobject_cast(_tileSets.get(i)); - Q_ASSERT(set); - if(set->selected()) { - sets.append(set); + if(!dir.isEmpty()) { + QVector sets; + for(int i = 0; i < _tileSets.count(); i++ ) { + QGCCachedTileSet* set = qobject_cast(_tileSets.get(i)); + Q_ASSERT(set); + if(set->selected()) { + sets.append(set); + } + } + if(sets.count()) { + _exporting = true; + emit exportingChanged(); + QGCExportTileTask* task = new QGCExportTileTask(sets, dir); + connect(task, &QGCExportTileTask::exportCompleted, this, &QGCMapEngineManager::_exportCompleted); + connect(task, &QGCExportTileTask::exportProgress, this, &QGCMapEngineManager::_exportProgressHandler); + connect(task, &QGCMapTask::error, this, &QGCMapEngineManager::taskError); + getQGCMapEngine()->addTask(task); + return true; } } - if(sets.count()) { - QGCExportTileTask* task = new QGCExportTileTask(sets, dir); - connect(task, &QGCExportTileTask::exportCompleted, this, &QGCMapEngineManager::_exportCompleted); - connect(task, &QGCMapTask::error, this, &QGCMapEngineManager::taskError); - getQGCMapEngine()->addTask(task); - } + return false; } //----------------------------------------------------------------------------- void -QGCMapEngineManager::_exportCompleted() +QGCMapEngineManager::_exportProgressHandler(int percentage) { + _exportProgress = percentage; + emit exportProgressChanged(); +} +//----------------------------------------------------------------------------- +void +QGCMapEngineManager::_exportCompleted() +{ + _exporting = false; + emit exportingChanged(); } //----------------------------------------------------------------------------- diff --git a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h index ce7e34ba13d4c70df68aa22b4cea84d4b1d9e3e6..b23f590d5f0245034bc11819badc26e8c2d22e90 100644 --- a/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h +++ b/src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h @@ -46,7 +46,10 @@ public: //-- Disk Space in MB Q_PROPERTY(quint32 freeDiskSpace READ freeDiskSpace NOTIFY freeDiskSpaceChanged) Q_PROPERTY(quint32 diskSpace READ diskSpace CONSTANT) + //-- Tile set export Q_PROPERTY(int selectedCount READ selectedCount NOTIFY selectedCountChanged) + Q_PROPERTY(int exportProgress READ exportProgress NOTIFY exportProgressChanged) + Q_PROPERTY(bool exporting READ exporting NOTIFY exportingChanged) Q_INVOKABLE void loadTileSets (); Q_INVOKABLE void updateForCurrentView (double lon0, double lat0, double lon1, double lat1, int minZoom, int maxZoom, const QString& mapName); @@ -58,7 +61,7 @@ public: Q_INVOKABLE bool findName (const QString& name); Q_INVOKABLE void selectAll (); Q_INVOKABLE void selectNone (); - Q_INVOKABLE void exportSets (QString path = QString()); + Q_INVOKABLE bool exportSets (QString path = QString()); int tileX0 () { return _totalSet.tileX0; } int tileX1 () { return _totalSet.tileX1; } @@ -77,6 +80,8 @@ public: quint64 freeDiskSpace () { return _freeDiskSpace; } quint64 diskSpace () { return _diskSpace; } int selectedCount (); + int exportProgress () { return _exportProgress; } + bool exporting () { return _exporting; } void setMapboxToken (QString token); void setMaxMemCache (quint32 size); @@ -101,6 +106,8 @@ signals: void errorMessageChanged (); void freeDiskSpaceChanged (); void selectedCountChanged (); + void exportProgressChanged (); + void exportingChanged (); public slots: void taskError (QGCMapTask::TaskType type, QString error); @@ -112,6 +119,7 @@ private slots: void _updateTotals (quint32 totaltiles, quint64 totalsize, quint32 defaulttiles, quint64 defaultsize); void _resetCompleted (); void _exportCompleted (); + void _exportProgressHandler (int percentage); private: void _updateDiskFreeSpace (); @@ -129,6 +137,8 @@ private: quint32 _diskSpace; QmlObjectListModel _tileSets; QString _errorMessage; + int _exportProgress; + bool _exporting; }; #endif