Skip to content

Commit

Permalink
AnalyzeView: Fix GeoTagWorker Threading
Browse files Browse the repository at this point in the history
  • Loading branch information
HTRamsey committed Sep 21, 2024
1 parent b1b1e01 commit e8955cc
Show file tree
Hide file tree
Showing 19 changed files with 461 additions and 245 deletions.
2 changes: 1 addition & 1 deletion src/AnalyzeView/ExifParser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ double readTime2(const QByteArray &buf)
}
}

bool write(QByteArray &buf, const GeoTagWorker::cameraFeedbackPacket &geotag)
bool write(QByteArray &buf, const GeoTagWorker::CameraFeedbackPacket &geotag)
{
try {
// Convert QByteArray to std::string for Exiv2
Expand Down
2 changes: 1 addition & 1 deletion src/AnalyzeView/ExifParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ Q_DECLARE_LOGGING_CATEGORY(ExifParserLog)
namespace ExifParser {
double readTime(const QByteArray &buf);
double readTime2(const QByteArray &buf);
bool write(QByteArray &buf, const GeoTagWorker::cameraFeedbackPacket &geotag);
bool write(QByteArray &buf, const GeoTagWorker::CameraFeedbackPacket &geotag);
} // namespace ExifParser
190 changes: 118 additions & 72 deletions src/AnalyzeView/GeoTagController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,120 +8,166 @@
****************************************************************************/

#include "GeoTagController.h"
#include "GeoTagWorker.h"
#include "QGCLoggingCategory.h"

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QThread>
#include <QtCore/QUrl>

QGC_LOGGING_CATEGORY(GeoTagControllerLog, "qgc.analyzeview.geotagcontroller")

GeoTagController::GeoTagController()
: _progress(0)
, _inProgress(false)
GeoTagController::GeoTagController(QObject *parent)
: QObject(parent)
, _worker(new GeoTagWorker())
, _workerThread(new QThread(this))
{
connect(&_worker, &GeoTagWorker::progressChanged, this, &GeoTagController::_workerProgressChanged);
connect(&_worker, &GeoTagWorker::error, this, &GeoTagController::_workerError);
connect(&_worker, &GeoTagWorker::started, this, &GeoTagController::inProgressChanged);
connect(&_worker, &GeoTagWorker::finished, this, &GeoTagController::inProgressChanged);
// qCDebug(GeoTagControllerLog) << Q_FUNC_INFO << this;

_worker->moveToThread(_workerThread);

(void) connect(_worker, &GeoTagWorker::progressChanged, this, &GeoTagController::_workerProgressChanged);
(void) connect(_worker, &GeoTagWorker::error, this, &GeoTagController::_workerError);
(void) connect(_workerThread, &QThread::started, _worker, &GeoTagWorker::process);
(void) connect(_workerThread, &QThread::started, this, &GeoTagController::inProgressChanged);
(void) connect(_workerThread, &QThread::finished, this, &GeoTagController::inProgressChanged);
}

GeoTagController::~GeoTagController()
{
// qCDebug(GeoTagControllerLog) << Q_FUNC_INFO << this;
}

void GeoTagController::cancelTagging()
{
(void) QMetaObject::invokeMethod(_worker, "cancelTagging", Qt::AutoConnection);
(void) QMetaObject::invokeMethod(_workerThread, "quit", Qt::AutoConnection);
_workerThread->wait();
}

void GeoTagController::setLogFile(QString filename)
QString GeoTagController::logFile() const
{
filename = QUrl(filename).toLocalFile();
if (!filename.isEmpty()) {
_worker.setLogFile(filename);
emit logFileChanged(filename);
}
return _worker->logFile();
}

void GeoTagController::setImageDirectory(QString dir)
QString GeoTagController::imageDirectory() const
{
dir = QUrl(dir).toLocalFile();
if (!dir.isEmpty()) {
_worker.setImageDirectory(dir);
emit imageDirectoryChanged(dir);
if(_worker.saveDirectory() == "") {
QDir saveDirectory = QDir(_worker.imageDirectory() + kTagged);
if(saveDirectory.exists()) {
_setErrorMessage(tr("Images have alreay been tagged. Existing images will be removed."));
return;
}
}
return _worker->imageDirectory();
}

QString GeoTagController::saveDirectory() const
{
return _worker->saveDirectory();
}

bool GeoTagController::inProgress() const
{
return _workerThread->isRunning();
}

void GeoTagController::setLogFile(const QString &filename)
{
if (filename.isEmpty()) {
_setErrorMessage(tr("Empty Filename."));
return;
}

const QFileInfo logFileInfo = QFileInfo(filename);
if (!logFileInfo.exists() || !logFileInfo.isFile()) {
_setErrorMessage(tr("Invalid Filename."));
return;
}
_errorMessage.clear();
emit errorMessageChanged(_errorMessage);

_worker->setLogFile(filename);
emit logFileChanged(filename);

_setErrorMessage(QString());
}

void GeoTagController::setSaveDirectory(QString dir)
void GeoTagController::setImageDirectory(const QString &dir)
{
dir = QUrl(dir).toLocalFile();
if (!dir.isEmpty()) {
_worker.setSaveDirectory(dir);
emit saveDirectoryChanged(dir);
//-- Check and see if there are images already there
QDir saveDirectory = QDir(_worker.saveDirectory());
saveDirectory.setFilter(QDir::Files | QDir::Readable | QDir::NoSymLinks | QDir::Writable);
QStringList nameFilters;
nameFilters << "*.jpg" << "*.JPG";
saveDirectory.setNameFilters(nameFilters);
QStringList imageList = saveDirectory.entryList();
if(!imageList.isEmpty()) {
_setErrorMessage(tr("The save folder already contains images."));
if (dir.isEmpty()) {
_setErrorMessage(tr("Invalid Directory."));
return;
}

const QFileInfo imageDirectoryInfo = QFileInfo(dir);
if (!imageDirectoryInfo.exists() || !imageDirectoryInfo.isDir()) {
_setErrorMessage(tr("Invalid Directory."));
return;
}

_worker->setImageDirectory(dir);
emit imageDirectoryChanged(dir);

if (_worker->saveDirectory().isEmpty()) {
const QDir saveDirectory = QDir(_worker->imageDirectory() + kTagged);
if (saveDirectory.exists()) {
_setErrorMessage(tr("Images have already been tagged. Existing images will be removed."));
return;
}
}
_errorMessage.clear();
emit errorMessageChanged(_errorMessage);

_setErrorMessage(QString());
}

void GeoTagController::setSaveDirectory(const QString &dir)
{
if (dir.isEmpty()) {
_setErrorMessage(tr("Invalid Directory."));
return;
}

const QFileInfo saveDirectoryInfo = QFileInfo(dir);
if (!saveDirectoryInfo.exists() || !saveDirectoryInfo.isDir()) {
_setErrorMessage(tr("Invalid Directory."));
return;
}

_worker->setSaveDirectory(dir);
emit saveDirectoryChanged(dir);

QDir saveDirectory = QDir(_worker->saveDirectory());
saveDirectory.setFilter(QDir::Files | QDir::Readable | QDir::NoSymLinks | QDir::Writable);
QStringList nameFilters;
nameFilters << "*.jpg" << "*.JPG";
saveDirectory.setNameFilters(nameFilters);
const QStringList imageList = saveDirectory.entryList();
if (!imageList.isEmpty()) {
_setErrorMessage(tr("The save folder already contains images."));
return;
}

_setErrorMessage(QString());
}

void GeoTagController::startTagging()
{
_errorMessage.clear();
emit errorMessageChanged(_errorMessage);
QDir imageDirectory = QDir(_worker.imageDirectory());
if(!imageDirectory.exists()) {
_setErrorMessage(QString());

const QDir imageDirectory = QDir(_worker->imageDirectory());
if (!imageDirectory.exists()) {
_setErrorMessage(tr("Cannot find the image directory."));
return;
}
if(_worker.saveDirectory() == "") {
QDir oldTaggedFolder = QDir(_worker.imageDirectory() + kTagged);
if(oldTaggedFolder.exists()) {

if (_worker->saveDirectory().isEmpty()) {
QDir oldTaggedFolder = QDir(_worker->imageDirectory() + kTagged);
if (oldTaggedFolder.exists()) {
oldTaggedFolder.removeRecursively();
if(!imageDirectory.mkdir(_worker.imageDirectory() + kTagged)) {
if (!imageDirectory.mkdir(_worker->imageDirectory() + kTagged)) {
_setErrorMessage(tr("Couldn't replace the previously tagged images"));
return;
}
}
} else {
QDir saveDirectory = QDir(_worker.saveDirectory());
if(!saveDirectory.exists()) {
const QDir saveDirectory = QDir(_worker->saveDirectory());
if (!saveDirectory.exists()) {
_setErrorMessage(tr("Cannot find the save directory."));
return;
}
}
_worker.start();
}

void GeoTagController::_workerProgressChanged(double progress)
{
_progress = progress;
emit progressChanged(progress);
}

void GeoTagController::_workerError(QString errorMessage)
{
_errorMessage = errorMessage;
emit errorMessageChanged(errorMessage);
}


void GeoTagController::_setErrorMessage(const QString& error)
{
_errorMessage = error;
emit errorMessageChanged(error);
(void) QMetaObject::invokeMethod(_workerThread, "start", Qt::AutoConnection);
}
76 changes: 37 additions & 39 deletions src/AnalyzeView/GeoTagController.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@

#pragma once

#include <QtCore/QLoggingCategory>
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QLoggingCategory>
#include <QtQmlIntegration/QtQmlIntegration>

#include "GeoTagWorker.h"
class GeoTagWorker;
class QThread;

Q_DECLARE_LOGGING_CATEGORY(GeoTagControllerLog)

Expand All @@ -24,56 +25,53 @@ class GeoTagController : public QObject
Q_OBJECT
QML_ELEMENT

public:
GeoTagController();
~GeoTagController();

Q_PROPERTY(QString logFile READ logFile WRITE setLogFile NOTIFY logFileChanged)
Q_PROPERTY(QString imageDirectory READ imageDirectory WRITE setImageDirectory NOTIFY imageDirectoryChanged)
Q_PROPERTY(QString saveDirectory READ saveDirectory WRITE setSaveDirectory NOTIFY saveDirectoryChanged)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
Q_PROPERTY(double progress READ progress NOTIFY progressChanged)
Q_PROPERTY(bool inProgress READ inProgress NOTIFY inProgressChanged)

/// Set to an error message is geotagging fails
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)

/// Progress indicator: 0-100
Q_PROPERTY(double progress READ progress NOTIFY progressChanged)

/// true: Currently in the process of tagging
Q_PROPERTY(bool inProgress READ inProgress NOTIFY inProgressChanged)
public:
GeoTagController(QObject *parent = nullptr);
~GeoTagController();

Q_INVOKABLE void startTagging();
Q_INVOKABLE void cancelTagging() { _worker.cancelTagging(); }
Q_INVOKABLE void cancelTagging();

QString logFile () const { return _worker.logFile(); }
QString imageDirectory () const { return _worker.imageDirectory(); }
QString saveDirectory () const { return _worker.saveDirectory(); }
double progress () const { return _progress; }
bool inProgress () const { return _worker.isRunning(); }
QString errorMessage () const { return _errorMessage; }
QString logFile() const;
QString imageDirectory() const;
QString saveDirectory() const;
/// Progress indicator: 0-100
double progress() const { return _progress; }
/// true: Currently in the process of tagging
bool inProgress() const;
/// Set to an error message if geotagging fails
QString errorMessage() const { return _errorMessage; }

void setLogFile (QString file);
void setImageDirectory (QString dir);
void setSaveDirectory (QString dir);
void setLogFile(const QString &file);
void setImageDirectory(const QString &dir);
void setSaveDirectory(const QString &dir);

signals:
void logFileChanged (QString logFile);
void imageDirectoryChanged (QString imageDirectory);
void saveDirectoryChanged (QString saveDirectory);
void progressChanged (double progress);
void inProgressChanged ();
void errorMessageChanged (QString errorMessage);
void logFileChanged(const QString &logFile);
void imageDirectoryChanged(const QString &imageDirectory);
void saveDirectoryChanged(const QString &saveDirectory);
void progressChanged(double progress);
void inProgressChanged();
void errorMessageChanged(const QString &errorMessage);

private slots:
void _workerProgressChanged (double progress);
void _workerError (QString errorMsg);
void _setErrorMessage (const QString& error);
void _workerProgressChanged(double progress) { if (progress != _progress) { _progress = progress; emit progressChanged(_progress); } }
void _setErrorMessage(const QString &errorMsg) { if (errorMsg != _errorMessage) { _errorMessage = errorMsg; emit errorMessageChanged(_errorMessage); } }
void _workerError(const QString &errorMsg) { _setErrorMessage(errorMsg); }

private:
QString _errorMessage;
double _progress;
bool _inProgress;

GeoTagWorker _worker;
QString _errorMessage;
double _progress = 0.;
bool _inProgress = false;
GeoTagWorker *_worker = nullptr;
QThread *_workerThread = nullptr;

static constexpr const char* kTagged = "/TAGGED";
static constexpr const char *kTagged = "/TAGGED";
};
6 changes: 3 additions & 3 deletions src/AnalyzeView/GeoTagPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ AnalyzePage {
nameFilters: [qsTr("ULog file (*.ulg)"), qsTr("PX4 log file (*.px4log)"), qsTr("All Files (*)")]
defaultSuffix: "ulg"
onAcceptedForLoad: (file) => {
geoController.logFile = openLogFile.file
geoController.logFile = file
close()
}
}
Expand All @@ -101,7 +101,7 @@ AnalyzePage {
title: qsTr("Select image directory")
selectFolder: true
onAcceptedForLoad: (file) => {
geoController.imageDirectory = selectImageDir.file
geoController.imageDirectory = file
close()
}
}
Expand All @@ -126,7 +126,7 @@ AnalyzePage {
title: qsTr("Select save directory")
selectFolder: true
onAcceptedForLoad: (file) => {
geoController.saveDirectory = selectDestDir.file
geoController.saveDirectory = file
close()
}
}
Expand Down
Loading

0 comments on commit e8955cc

Please sign in to comment.