12#include <QtCore/QFileInfo>
22 , _ftpManager(_vehicle->ftpManager())
35bool FTPController::listDirectory(
const QString &uri,
int componentId)
37 if (_operation != Operation::None) {
38 _setErrorString(tr(
"Another FTP operation is in progress"));
42 const QString previousPath = _currentPath;
44 _resetDirectoryState();
47 _setErrorString(QString());
50 _setOperation(Operation::List);
54 const uint8_t compId = _componentIdForRequest(componentId);
56 qCWarning(FTPControllerLog) <<
"Failed to start list operation for" << uri;
57 _setErrorString(tr(
"Failed to list %1").arg(uri));
58 _currentPath = previousPath;
68bool FTPController::downloadFile(
const QString &uri,
const QString &localDir,
const QString &fileName,
int componentId)
70 if (_operation != Operation::None) {
71 const QString
error = tr(
"Another FTP operation is in progress");
72 _setErrorString(
error);
78 const QString
error = tr(
"Could not create directory %1").arg(localDir);
79 _setErrorString(
error);
84 const QString absoluteLocalDir = QDir(localDir).absolutePath();
86 _lastDownloadFile.clear();
88 _setErrorString(QString());
91 _setOperation(Operation::Download);
95 const uint8_t compId = _componentIdForRequest(componentId);
96 if (!_ftpManager->
download(compId, uri, absoluteLocalDir, fileName)) {
97 qCWarning(FTPControllerLog) <<
"Failed to start download" << uri << absoluteLocalDir;
98 const QString
error = tr(
"Failed to download %1").arg(uri);
99 _setErrorString(
error);
109bool FTPController::uploadFile(
const QString &localFile,
const QString &uri,
int componentId)
111 if (_operation != Operation::None) {
112 const QString
error = tr(
"Another FTP operation is in progress");
113 _setErrorString(
error);
118 QFileInfo sourceInfo(localFile);
119 if (!sourceInfo.exists() || !sourceInfo.isFile()) {
120 const QString
error = tr(
"File %1 does not exist").arg(localFile);
121 _setErrorString(
error);
126 _lastUploadTarget.clear();
128 _setErrorString(QString());
131 _setOperation(Operation::Upload);
135 const uint8_t compId = _componentIdForRequest(componentId);
136 if (!_ftpManager->
upload(compId, uri, sourceInfo.absoluteFilePath())) {
137 qCWarning(FTPControllerLog) <<
"Failed to start upload" << sourceInfo.absoluteFilePath() << uri;
138 const QString
error = tr(
"Failed to upload %1").arg(sourceInfo.fileName());
139 _setErrorString(
error);
149bool FTPController::deleteFile(
const QString &uri,
int componentId)
151 if (_operation != Operation::None) {
152 const QString
error = tr(
"Another FTP operation is in progress");
153 _setErrorString(
error);
158 _setErrorString(QString());
160 _setOperation(Operation::Delete);
162 const uint8_t compId = _componentIdForRequest(componentId);
164 qCWarning(FTPControllerLog) <<
"Failed to start delete" << uri;
165 const QString
error = tr(
"Failed to delete %1").arg(uri);
166 _setErrorString(
error);
176void FTPController::cancelActiveOperation()
178 switch (_operation) {
179 case Operation::Download:
182 case Operation::Upload:
185 case Operation::List:
188 case Operation::Delete:
191 case Operation::None:
196void FTPController::_handleDownloadComplete(
const QString &filePath,
const QString &
error)
198 if (_operation != Operation::Download) {
204 if (
error.isEmpty()) {
205 if (!filePath.isEmpty()) {
206 _lastDownloadFile = filePath;
210 _setErrorString(QString());
212 _setErrorString(
error);
213 _lastDownloadFile.clear();
214 _lastDownloadIsArchive =
false;
221void FTPController::_handleUploadComplete(
const QString &remotePath,
const QString &
error)
223 if (_operation != Operation::Upload) {
229 if (
error.isEmpty()) {
230 _lastUploadTarget = remotePath;
232 _setErrorString(QString());
234 _setErrorString(
error);
235 _lastUploadTarget.clear();
242void FTPController::_handleDirectoryComplete(
const QStringList &entries,
const QString &
error)
244 if (_operation != Operation::List) {
250 if (
error.isEmpty()) {
251 if (_directoryEntries != entries) {
252 _directoryEntries = entries;
255 _setErrorString(QString());
257 _setErrorString(
error);
258 _resetDirectoryState();
264void FTPController::_handleDeleteComplete(
const QString &remotePath,
const QString &
error)
268 if (_operation != Operation::Delete) {
274 if (
error.isEmpty()) {
275 _setErrorString(QString());
277 _setErrorString(
error);
283void FTPController::_handleCommandProgress(
float value)
285 if (_operation == Operation::Download || _operation == Operation::Upload) {
286 if (std::fabs(_progress - value) > std::numeric_limits<float>::epsilon()) {
293void FTPController::_setBusy(
bool busy)
303void FTPController::_setOperation(Operation operation)
305 if (_operation == operation) {
309 _operation = operation;
313void FTPController::_clearOperation()
315 _setOperation(Operation::None);
316 if (std::fabs(_progress) > std::numeric_limits<float>::epsilon()) {
322void FTPController::_setErrorString(
const QString &
error)
324 if (_errorString ==
error) {
328 _errorString =
error;
332void FTPController::_resetDirectoryState()
334 if (!_directoryEntries.isEmpty()) {
335 _directoryEntries.clear();
340uint8_t FTPController::_componentIdForRequest(
int componentId)
const
342 if (componentId <= 0 || componentId > std::numeric_limits<uint8_t>::max()) {
343 return MAV_COMP_ID_AUTOPILOT1;
346 return static_cast<uint8_t
>(componentId);
349bool FTPController::browseArchive(
const QString &archivePath)
351 if (archivePath.isEmpty()) {
352 _setErrorString(tr(
"No archive path specified"));
356 if (!QFile::exists(archivePath)) {
357 _setErrorString(tr(
"Archive file not found: %1").arg(archivePath));
362 _setErrorString(tr(
"Not a supported archive format: %1").arg(archivePath));
366 _archiveModel->setArchivePath(archivePath);
367 _setErrorString(QString());
371bool FTPController::extractArchive(
const QString &archivePath,
const QString &outputDir)
374 _setErrorString(tr(
"Extraction already in progress"));
378 if (archivePath.isEmpty()) {
379 _setErrorString(tr(
"No archive path specified"));
383 if (!QFile::exists(archivePath)) {
384 _setErrorString(tr(
"Archive file not found: %1").arg(archivePath));
388 QString targetDir = outputDir;
389 if (targetDir.isEmpty()) {
390 targetDir = QFileInfo(archivePath).absolutePath();
394 _setErrorString(tr(
"Could not create output directory: %1").arg(targetDir));
398 _extractionOutputDir = targetDir;
400 if (_extractionJob ==
nullptr) {
403 this, &FTPController::_handleExtractionProgress);
405 this, &FTPController::_handleExtractionFinished);
409 _extractionProgress = 0.0F;
417void FTPController::cancelExtraction()
419 if (_extractionJob !=
nullptr && _extracting) {
424void FTPController::_handleExtractionProgress(qreal progress)
426 const auto newProgress =
static_cast<float>(progress);
427 if (std::fabs(_extractionProgress - newProgress) > std::numeric_limits<float>::epsilon()) {
428 _extractionProgress = newProgress;
433void FTPController::_handleExtractionFinished(
bool success)
439 _setErrorString(QString());
442 const QString
error = _extractionJob !=
nullptr ? _extractionJob->errorString() : tr(
"Extraction failed");
443 _setErrorString(
error);
447 _extractionProgress = 0.0F;
QObject wrapper for async compression operations using QtConcurrent/QPromise.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QML-facing controller for MAVLink FTP operations.
void uploadComplete(const QString &remotePath, const QString &error)
void directoryEntriesChanged()
void downloadComplete(const QString &filePath, const QString &error)
void extractionComplete(const QString &outputDir, const QString &error)
void currentPathChanged()
void errorStringChanged()
void deleteComplete(const QString &remotePath, const QString &error)
void extractionProgressChanged()
void activeOperationChanged()
void lastDownloadFileChanged()
void lastUploadTargetChanged()
bool listDirectory(uint8_t fromCompId, const QString &fromURI)
bool deleteFile(uint8_t fromCompId, const QString &fromURI)
bool upload(uint8_t toCompId, const QString &toURI, const QString &fromFile)
void uploadComplete(const QString &file, const QString &errorMsg)
void commandProgress(float value)
void downloadComplete(const QString &file, const QString &errorMsg)
void cancelListDirectory()
void deleteComplete(const QString &file, const QString &errorMsg)
bool download(uint8_t fromCompId, const QString &fromURI, const QString &toDir, const QString &fileName="", bool checksize=true)
void listDirectoryComplete(const QStringList &dirList, const QString &errorMsg)
void progressChanged(qreal progress)
Emitted when progress changes (0.0 to 1.0)
void cancel()
Cancel current operation.
void finished(bool success)
void extractArchive(const QString &archivePath, const QString &outputDirectoryPath, qint64 maxBytes=0)
bool isArchiveFile(const QString &filePath)
Check if file path indicates an archive file (.zip, .tar, .tar.gz, etc.)
bool ensureDirectoryExists(const QString &path)