Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ V1.XX.X
[QMS-990] Fix: Toolbar menu item(s) too small, "View" menu item missing (macOS)
[QMS-992] Fix: Changing items does not update the map view
[QMS-994] Fix: QMapTool not callable from QMapShack (macOS)
[QMS-998] Add progress bar to GPS devices while loading records

V1.20.1
[QMS-945] Redesign icons for focus, autosave, sync, and DB buttons
Expand Down
2 changes: 2 additions & 0 deletions src/qmapshack/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ set( SRCS
helpers/CProgressDialog.cpp
helpers/CSelectCopyAction.cpp
helpers/CSelectProjectDialog.cpp
helpers/CThread.cpp
helpers/CTimeDialog.cpp
helpers/CToolBarConfig.cpp
helpers/CToolBarSetupDialog.cpp
Expand Down Expand Up @@ -563,6 +564,7 @@ set( HDRS
helpers/CSelectCopyAction.h
helpers/CSelectProjectDialog.h
helpers/CSettings.h
helpers/CThread.h
helpers/CTryMutexLocker.h
helpers/CTimeDialog.h
helpers/CToolBarConfig.h
Expand Down
2 changes: 1 addition & 1 deletion src/qmapshack/device/CDeviceAccessKMtp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ QStringList CDeviceAccessKMtp::listDirsOnStorage(const QString& path) {
int CDeviceAccessKMtp::waitForCopyOperation(const org::kde::kmtp::Storage* storage, fn_operation operation) {
QEventLoop loop;
connect(storage, &org::kde::kmtp::Storage::copyProgress, &loop,
[](qulonglong sent, qulonglong total) { qDebug() << "processed size:" << sent << "of" << total; });
[](qulonglong sent, qulonglong total) { /*qDebug() << "processed size:" << sent << "of" << total;*/ });
connect(storage, &org::kde::kmtp::Storage::copyFinished, &loop, &QEventLoop::exit);

if (operation() == 0) {
Expand Down
105 changes: 75 additions & 30 deletions src/qmapshack/device/CDeviceGarmin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@
#include "gis/gpx/CGpxProject.h"
#include "gis/tcx/CTcxProject.h"
#include "gis/wpt/CGisItemWpt.h"
#include "helpers/CThread.h"

CDeviceGarmin::CDeviceGarmin(const QString& path, const QString& key, const QString& model,
const QString& garminDeviceXml, QTreeWidget* parent)
: IDevice(path, eTypeGarmin, key, parent), model(model), cntImages(0) {
: QObject(parent), IDevice(path, eTypeGarmin, key, parent), model(model), cntImages(0) {
name = "Garmin";

QFile file(QDir(path).absoluteFilePath(garminDeviceXml));
Expand Down Expand Up @@ -118,51 +119,95 @@ CDeviceGarmin::CDeviceGarmin(const QString& path, const QString& key, const QStr
dir.mkpath(pathTcx);
}

createProjectsFromFiles(pathGpx, "gpx");
createProjectsFromFiles(pathGpx + "/Current", "gpx");
threadLoadData = new CThread([this]() {
CDeviceMountLock mountLock(*this);
quint32 total = 0;
total += QDir(dir.absoluteFilePath(pathGpx)).entryList(QStringList("*.gpx")).count();
total += QDir(dir.absoluteFilePath(pathGpx + "/Current")).entryList(QStringList("*.gpx")).count();
total += QDir(dir.absoluteFilePath(pathActivities)).entryList(QStringList("*.fit")).count();
total += QDir(dir.absoluteFilePath(pathCourses)).entryList(QStringList("*.fit")).count();
total += QDir(dir.absoluteFilePath(pathLocations)).entryList(QStringList("*.fit")).count();
if (!pathTcx.isEmpty()) {
total += QDir(dir.absoluteFilePath(pathTcx)).entryList(QStringList("*.tcx")).count();
}
quint32 count = 0;

createProjectsFromFiles(pathGpx, "gpx", count, total);
createProjectsFromFiles(pathGpx + "/Current", "gpx", count, total);
createProjectsFromFiles(pathActivities, "fit", count, total);
createProjectsFromFiles(pathCourses, "fit", count, total);
createProjectsFromFiles(pathLocations, "fit", count, total);
if (!pathTcx.isEmpty()) {
createProjectsFromFiles(pathTcx, "tcx", count, total);
}

QDir dirArchive(dir.absoluteFilePath(pathGpx + "/Archive"));
if (dirArchive.exists() && (dirArchive.entryList(QStringList("*.gpx")).count() != 0)) {
new CDeviceGarminArchive(dir.absoluteFilePath(pathGpx + "/Archive"), this);
}
QMetaObject::invokeMethod(
this,
[this]() {
QMutexLocker lock(&IGisItem::mutexItems);
QDir dirArchive(dir.absoluteFilePath(pathGpx + "/Archive"));
if (dirArchive.exists() && (dirArchive.entryList(QStringList("*.gpx")).count() != 0)) {
new CDeviceGarminArchive(dir.absoluteFilePath(pathGpx + "/Archive"), this);
}
},
Qt::BlockingQueuedConnection);

setProgress(total, total);
});

threadLoadData->start();
}

createProjectsFromFiles(pathActivities, "fit");
createProjectsFromFiles(pathCourses, "fit");
createProjectsFromFiles(pathLocations, "fit");
if (!pathTcx.isEmpty()) {
createProjectsFromFiles(pathTcx, "tcx");
CDeviceGarmin::~CDeviceGarmin() {
if (threadLoadData != nullptr) {
threadLoadData->cancel();
}
}

QString CDeviceGarmin::getInfo(quint32) const { return QString("%1 (%2, %3)").arg(description, partno, model); }

void CDeviceGarmin::createProjectsFromFiles(QString subdirecoty, QString fileEnding) {
void CDeviceGarmin::createProjectsFromFiles(QString subdirecoty, QString fileEnding, quint32& count,
const quint32 total) {
QDir dirLoop(dir.absoluteFilePath(subdirecoty));
qDebug() << "reading files from device: " << dirLoop.path();
const QStringList& entries = dirLoop.entryList(QStringList("*." + fileEnding));
for (const QString& entry : entries) {
const QString filename = dirLoop.absoluteFilePath(entry);
IGisProject* project = nullptr;
if (fileEnding == "fit") {
project = new CFit2Project(filename, this);
} else if (fileEnding == "gpx") {
project = new CGpxProject(filename, this);
} else if (fileEnding == "tcx") {
project = new CTcxProject(filename, this);
if (threadLoadData->isInterruptionRequested()) {
break;
}

if (project) {
if (!project->isValid()) {
delete project;
} else {
project->setVisibility(isVisible());
}
}
setProgress(++count, total);
const QString filename = dirLoop.absoluteFilePath(entry);

QMetaObject::invokeMethod(
this,
[this, filename, fileEnding]() {
QMutexLocker lock(&IGisItem::mutexItems);
IGisProject* project = nullptr;
try {
if (fileEnding == "fit") {
project = new CFit2Project(filename, this);
} else if (fileEnding == "gpx") {
project = new CGpxProject(filename, this);
} else if (fileEnding == "tcx") {
project = new CTcxProject(filename, this);
}

if (project) {
if (!project->isValid()) {
delete project;
} else {
project->setVisibility(isVisible());
}
}
} catch (const QString& msg) {
qWarning() << msg;
}
},
Qt::BlockingQueuedConnection);
}
}

CDeviceGarmin::~CDeviceGarmin() {}

void CDeviceGarmin::insertCopyOfProject(IGisProject* project) {
if (description.startsWith("EDGE 5", Qt::CaseInsensitive)) {
insertCopyOfProjectAsTcx(project);
Expand Down
11 changes: 8 additions & 3 deletions src/qmapshack/device/CDeviceGarmin.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@
#ifndef CDEVICEGARMIN_H
#define CDEVICEGARMIN_H

#include <QPointer>

#include "device/IDevice.h"

class CDeviceGarminArchive;
class CThread;

class CDeviceGarmin : public IDevice {
Q_DECLARE_TR_FUNCTIONS(CDeviceGarmin)
class CDeviceGarmin : public QObject, public IDevice {
Q_OBJECT
public:
CDeviceGarmin(const QString& path, const QString& key, const QString& model, const QString& garminDeviceXml,
QTreeWidget* parent);
Expand All @@ -38,7 +41,7 @@ class CDeviceGarmin : public IDevice {
QString getInfo(quint32) const override;

private:
void createProjectsFromFiles(QString subdirecoty, QString fileEnding);
void createProjectsFromFiles(QString subdirecoty, QString fileEnding, quint32& count, const quint32 total);
void createAdventureFromProject(IGisProject* project, const QString& gpxFilename);
void insertCopyOfProjectAsGpx(IGisProject* project);
void insertCopyOfProjectAsTcx(IGisProject* project);
Expand All @@ -61,6 +64,8 @@ class CDeviceGarmin : public IDevice {
QString pathTcx; // no default

int cntImages = 0;

QPointer<CThread> threadLoadData;
};

#endif // CDEVICEGARMIN_H
70 changes: 50 additions & 20 deletions src/qmapshack/device/CDeviceGarminArchive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,84 @@

#include <QtWidgets>

#include "canvas/CCanvas.h"
#include "device/CDeviceGarmin.h"
#include "gis/CGisListWks.h"
#include "gis/CGisWorkspace.h"
#include "gis/gpx/CGpxProject.h"
#include "helpers/CThread.h"

CDeviceGarminArchive::CDeviceGarminArchive(const QString& path, CDeviceGarmin* parent)
: IDevice(path, parent->getKey(), parent) {
: QObject(parent), IDevice(path, parent->getKey(), parent) {
name = tr("Archive - expand to load");
setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
connect(treeWidget(), &QTreeWidget::itemExpanded, this, &CDeviceGarminArchive::slotExpanded);
connect(treeWidget(), &QTreeWidget::itemCollapsed, this, &CDeviceGarminArchive::slotCollapsed);
}

CDeviceGarminArchive::~CDeviceGarminArchive() {
if (threadLoadData != nullptr) {
threadLoadData->cancel();
}
};

void CDeviceGarminArchive::slotExpanded(QTreeWidgetItem* item) {
if ((item != this) || (childCount() != 0)) {
return;
}

name = tr("Archive - loaded");

QMutexLocker lock(&IGisItem::mutexItems);
CDeviceMountLock mountLock(*this);
CCanvasCursorLock cursorLock(Qt::WaitCursor, __func__);
name = tr("Archive - loading");
qDebug() << "reading files from device: " << dir.path();
const QStringList& entries = dir.entryList(QStringList("*.gpx"));
for (const QString& entry : entries) {
const QString& filename = dir.absoluteFilePath(entry);
IGisProject* project = new CGpxProject(filename, this);
if (project) {
if (!project->isValid()) {
delete project;
} else {
project->setVisibility(isVisible());

threadLoadData = new CThread([this]() {
CDeviceMountLock mountLock(*this);
const QStringList& entries = dir.entryList(QStringList("*.gpx"));

quint32 total = entries.count();
quint32 count = 0;

for (const QString& entry : entries) {
if (threadLoadData->isInterruptionRequested()) {
break;
}
setProgress(++count, total);
const QString& filename = dir.absoluteFilePath(entry);
QMetaObject::invokeMethod(
this,
[this, filename]() {
QMutexLocker lock(&IGisItem::mutexItems);
try {
IGisProject* project = new CGpxProject(filename, this);
if (project) {
if (!project->isValid()) {
delete project;
} else {
project->setVisibility(isVisible());
}
}
} catch (const QString& msg) {
qWarning() << msg;
}
},
Qt::BlockingQueuedConnection);
}
}

name = tr("Archive - loaded");
setProgress(total, total);
});

threadLoadData->start();
}

void CDeviceGarminArchive::slotCollapsed(QTreeWidgetItem* item) {
if ((item != this) || (childCount() == 0)) {
return;
}

QMutexLocker lock(&IGisItem::mutexItems);
CDeviceMountLock mountLock(*this);
CCanvasCursorLock cursorLock(Qt::WaitCursor, __func__);
if (threadLoadData != nullptr) {
threadLoadData->cancel();
}

QMutexLocker lock(&IGisItem::mutexItems);
qDeleteAll(takeChildren());

name = tr("Archive - expand to load");
Expand Down
7 changes: 6 additions & 1 deletion src/qmapshack/device/CDeviceGarminArchive.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@
#include <QCoreApplication>
#include <QDir>
#include <QObject>
#include <QPointer>

#include "device/IDevice.h"

class CDeviceGarmin;
class CThread;

class CDeviceGarminArchive : public QObject, public IDevice {
Q_OBJECT
public:
CDeviceGarminArchive(const QString& path, CDeviceGarmin* parent);
virtual ~CDeviceGarminArchive() = default;
virtual ~CDeviceGarminArchive();

QString getInfo(quint32) const override { return ""; }

Expand All @@ -41,6 +43,9 @@ class CDeviceGarminArchive : public QObject, public IDevice {
private slots:
void slotExpanded(QTreeWidgetItem* item);
void slotCollapsed(QTreeWidgetItem* item);

private:
QPointer<CThread> threadLoadData;
};

#endif // CDEVICEGARMINARCHIVE_H
Loading