|
|
|
@ -22,7 +22,7 @@
@@ -22,7 +22,7 @@
|
|
|
|
|
======================================================================*/ |
|
|
|
|
|
|
|
|
|
#include "QGCUASFileView.h" |
|
|
|
|
#include "uas/FileManager.h" |
|
|
|
|
#include "FileManager.h" |
|
|
|
|
#include "QGCFileDialog.h" |
|
|
|
|
|
|
|
|
|
#include <QFileDialog> |
|
|
|
@ -32,62 +32,64 @@
@@ -32,62 +32,64 @@
|
|
|
|
|
QGCUASFileView::QGCUASFileView(QWidget *parent, FileManager *manager) : |
|
|
|
|
QWidget(parent), |
|
|
|
|
_manager(manager), |
|
|
|
|
_listInProgress(false), |
|
|
|
|
_downloadInProgress(false), |
|
|
|
|
_uploadInProgress(false) |
|
|
|
|
_currentCommand(commandNone) |
|
|
|
|
{ |
|
|
|
|
_ui.setupUi(this); |
|
|
|
|
|
|
|
|
|
// Progress bar is only visible while a download is in progress
|
|
|
|
|
_ui.progressBar->setVisible(false); |
|
|
|
|
|
|
|
|
|
bool success; |
|
|
|
|
Q_UNUSED(success); // Silence retail unused variable error
|
|
|
|
|
_ui.progressBar->reset(); |
|
|
|
|
|
|
|
|
|
// Connect UI signals
|
|
|
|
|
success = connect(_ui.listFilesButton, SIGNAL(clicked()), this, SLOT(_refreshTree())); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_ui.downloadButton, SIGNAL(clicked()), this, SLOT(_downloadFile())); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_ui.uploadButton, SIGNAL(clicked()), this, SLOT(_uploadFile())); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_ui.treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(_currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
connect(_ui.listFilesButton, &QPushButton::clicked, this, &QGCUASFileView::_refreshTree); |
|
|
|
|
connect(_ui.downloadButton, &QPushButton::clicked, this, &QGCUASFileView::_downloadFile); |
|
|
|
|
connect(_ui.uploadButton, &QPushButton::clicked, this, &QGCUASFileView::_uploadFile); |
|
|
|
|
connect(_ui.treeWidget, &QTreeWidget::currentItemChanged, this, &QGCUASFileView::_currentItemChanged); |
|
|
|
|
|
|
|
|
|
// Connect signals from FileManager
|
|
|
|
|
connect(_manager, &FileManager::commandProgress, this, &QGCUASFileView::_commandProgress); |
|
|
|
|
connect(_manager, &FileManager::commandComplete, this, &QGCUASFileView::_commandComplete); |
|
|
|
|
connect(_manager, &FileManager::commandError, this, &QGCUASFileView::_commandError); |
|
|
|
|
connect(_manager, &FileManager::listEntry, this, &QGCUASFileView::_listEntryReceived); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Downloads the file currently selected in the tree view
|
|
|
|
|
void QGCUASFileView::_downloadFile(void) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(!_downloadInProgress); |
|
|
|
|
if (_currentCommand != commandNone) { |
|
|
|
|
qWarning() << QString("Download attempted while another command was in progress: _currentCommand(%1)").arg(_currentCommand); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ui.statusText->clear(); |
|
|
|
|
|
|
|
|
|
QString downloadToHere = QGCFileDialog::getExistingDirectory(this, tr("Download Directory"), |
|
|
|
|
QDir::homePath(), |
|
|
|
|
QGCFileDialog::ShowDirsOnly |
|
|
|
|
| QGCFileDialog::DontResolveSymlinks); |
|
|
|
|
QString downloadToHere = QGCFileDialog::getExistingDirectory(this, |
|
|
|
|
"Download Directory", |
|
|
|
|
QDir::homePath(), |
|
|
|
|
QGCFileDialog::ShowDirsOnly | QGCFileDialog::DontResolveSymlinks); |
|
|
|
|
|
|
|
|
|
// And now download to this location
|
|
|
|
|
|
|
|
|
|
QString path; |
|
|
|
|
QString downloadFilename; |
|
|
|
|
|
|
|
|
|
QTreeWidgetItem* item = _ui.treeWidget->currentItem(); |
|
|
|
|
if (item && item->type() == _typeFile) { |
|
|
|
|
_downloadFilename.clear(); |
|
|
|
|
do { |
|
|
|
|
QString name = item->text(0).split("\t")[0]; // Strip off file sizes
|
|
|
|
|
|
|
|
|
|
// If this is the file name and not a directory keep track of the download file name
|
|
|
|
|
if (_downloadFilename.isEmpty()) { |
|
|
|
|
_downloadFilename = name; |
|
|
|
|
if (downloadFilename.isEmpty()) { |
|
|
|
|
downloadFilename = name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
path.prepend("/" + name); |
|
|
|
|
item = item->parent(); |
|
|
|
|
} while (item); |
|
|
|
|
|
|
|
|
|
_ui.downloadButton->setEnabled(false); |
|
|
|
|
_downloadInProgress = true; |
|
|
|
|
_connectDownloadSignals(); |
|
|
|
|
_setAllButtonsEnabled(false); |
|
|
|
|
_currentCommand = commandDownload; |
|
|
|
|
|
|
|
|
|
_ui.statusText->setText(QString("Downloading: %1").arg(downloadFilename)); |
|
|
|
|
|
|
|
|
|
_manager->streamPath(path, QDir(downloadToHere)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -95,7 +97,10 @@ void QGCUASFileView::_downloadFile(void)
@@ -95,7 +97,10 @@ void QGCUASFileView::_downloadFile(void)
|
|
|
|
|
/// @brief uploads a file into the currently selected directory the tree view
|
|
|
|
|
void QGCUASFileView::_uploadFile(void) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(!_uploadInProgress); |
|
|
|
|
if (_currentCommand != commandNone) { |
|
|
|
|
qWarning() << QString("Upload attempted while another command was in progress: _currentCommand(%1)").arg(_currentCommand); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ui.statusText->clear(); |
|
|
|
|
|
|
|
|
@ -113,83 +118,41 @@ void QGCUASFileView::_uploadFile(void)
@@ -113,83 +118,41 @@ void QGCUASFileView::_uploadFile(void)
|
|
|
|
|
item = item->parent(); |
|
|
|
|
} while (item); |
|
|
|
|
|
|
|
|
|
QString uploadFromHere = QGCFileDialog::getOpenFileName(this, tr("Upload File"), |
|
|
|
|
QDir::homePath()); |
|
|
|
|
QString uploadFromHere = QGCFileDialog::getOpenFileName(this, "Upload File", QDir::homePath()); |
|
|
|
|
|
|
|
|
|
_ui.statusText->setText(QString("Uploading: %1").arg(uploadFromHere)); |
|
|
|
|
|
|
|
|
|
qDebug() << "Upload: " << uploadFromHere << "to path" << path; |
|
|
|
|
|
|
|
|
|
_setAllButtonsEnabled(false); |
|
|
|
|
_currentCommand = commandUpload; |
|
|
|
|
|
|
|
|
|
_manager->uploadPath(path, uploadFromHere); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// @brief Called when length of file being downloaded is known.
|
|
|
|
|
void QGCUASFileView::_downloadLength(unsigned int length) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(_downloadInProgress); |
|
|
|
|
|
|
|
|
|
// Setup the progress bar
|
|
|
|
|
QProgressBar* bar = _ui.progressBar; |
|
|
|
|
bar->setMinimum(0); |
|
|
|
|
bar->setMaximum(length); |
|
|
|
|
bar->setValue(0); |
|
|
|
|
bar->setVisible(true); |
|
|
|
|
|
|
|
|
|
_ui.downloadButton->setEnabled(true); |
|
|
|
|
_downloadStartTime.start(); |
|
|
|
|
|
|
|
|
|
_ui.statusText->setText(tr("Downloading: %1").arg(_downloadFilename)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Called to update the progress of the download.
|
|
|
|
|
/// @param bytesReceived Current count of bytes received for current download
|
|
|
|
|
void QGCUASFileView::_downloadProgress(unsigned int bytesReceived) |
|
|
|
|
{ |
|
|
|
|
static uint lastSecsReported = 0; |
|
|
|
|
|
|
|
|
|
Q_ASSERT(_downloadInProgress); |
|
|
|
|
|
|
|
|
|
_ui.progressBar->setValue(bytesReceived); |
|
|
|
|
|
|
|
|
|
// Calculate and display download rate. Only update once per second.
|
|
|
|
|
uint kbReceived = bytesReceived / 1024; |
|
|
|
|
uint secs = _downloadStartTime.elapsed() / 1000; |
|
|
|
|
if (secs != 0) { |
|
|
|
|
uint kbPerSec = kbReceived / secs; |
|
|
|
|
if (kbPerSec != 0 && secs != lastSecsReported) { |
|
|
|
|
lastSecsReported = secs; |
|
|
|
|
_ui.statusText->setText(tr("Downloading: %1 %2 KB/sec").arg(_downloadFilename).arg(kbPerSec)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Called when the download associated with the FileManager::downloadPath command completes.
|
|
|
|
|
void QGCUASFileView::_downloadComplete(void) |
|
|
|
|
/// @param value Progress bar value
|
|
|
|
|
void QGCUASFileView::_commandProgress(int value) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(_downloadInProgress); |
|
|
|
|
_ui.downloadButton->setEnabled(true); |
|
|
|
|
_ui.progressBar->setVisible(false); |
|
|
|
|
_downloadInProgress = false; |
|
|
|
|
_disconnectDownloadSignals(); |
|
|
|
|
_ui.statusText->setText(tr("Download complete: %1").arg(_downloadFilename)); |
|
|
|
|
_ui.progressBar->setValue(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Called when an error occurs during a download.
|
|
|
|
|
/// @param msg Error message
|
|
|
|
|
void QGCUASFileView::_downloadErrorMessage(const QString& msg) |
|
|
|
|
void QGCUASFileView::_commandError(const QString& msg) |
|
|
|
|
{ |
|
|
|
|
if (_downloadInProgress) { |
|
|
|
|
_ui.downloadButton->setEnabled(true); |
|
|
|
|
_ui.progressBar->setVisible(false); |
|
|
|
|
_downloadInProgress = false; |
|
|
|
|
_disconnectDownloadSignals(); |
|
|
|
|
_ui.statusText->setText(tr("Error: ") + msg); |
|
|
|
|
} |
|
|
|
|
_setAllButtonsEnabled(true); |
|
|
|
|
_currentCommand = commandNone; |
|
|
|
|
_ui.statusText->setText(QString("Error: %1").arg(msg)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Refreshes the directory list tree.
|
|
|
|
|
void QGCUASFileView::_refreshTree(void) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(!_listInProgress); |
|
|
|
|
if (_currentCommand != commandNone) { |
|
|
|
|
qWarning() << QString("List attempted while another command was in progress: _currentCommand(%1)").arg(_currentCommand); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ui.treeWidget->clear(); |
|
|
|
|
_ui.statusText->clear(); |
|
|
|
@ -199,10 +162,8 @@ void QGCUASFileView::_refreshTree(void)
@@ -199,10 +162,8 @@ void QGCUASFileView::_refreshTree(void)
|
|
|
|
|
_walkIndexStack.append(0); |
|
|
|
|
_walkItemStack.append(_ui.treeWidget->invisibleRootItem()); |
|
|
|
|
|
|
|
|
|
// Don't queue up more than once
|
|
|
|
|
_ui.listFilesButton->setEnabled(false); |
|
|
|
|
_listInProgress = true; |
|
|
|
|
_connectListSignals(); |
|
|
|
|
_setAllButtonsEnabled(false); |
|
|
|
|
_currentCommand = commandList; |
|
|
|
|
|
|
|
|
|
_requestDirectoryList("/"); |
|
|
|
|
} |
|
|
|
@ -210,7 +171,10 @@ void QGCUASFileView::_refreshTree(void)
@@ -210,7 +171,10 @@ void QGCUASFileView::_refreshTree(void)
|
|
|
|
|
/// @brief Adds the specified directory entry to the tree view.
|
|
|
|
|
void QGCUASFileView::_listEntryReceived(const QString& entry) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(_listInProgress); |
|
|
|
|
if (_currentCommand != commandList) { |
|
|
|
|
qWarning() << QString("List entry received while no list command in progress: _currentCommand(%1)").arg(_currentCommand); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int type; |
|
|
|
|
if (entry.startsWith("F")) { |
|
|
|
@ -232,22 +196,29 @@ void QGCUASFileView::_listEntryReceived(const QString& entry)
@@ -232,22 +196,29 @@ void QGCUASFileView::_listEntryReceived(const QString& entry)
|
|
|
|
|
item->setText(0, entry.right(entry.size() - 1)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Called when an error occurs during a directory listing.
|
|
|
|
|
/// @param msg Error message
|
|
|
|
|
void QGCUASFileView::_listErrorMessage(const QString& msg) |
|
|
|
|
/// @brief Called when a command completes successfully
|
|
|
|
|
void QGCUASFileView::_commandComplete(void) |
|
|
|
|
{ |
|
|
|
|
if (_listInProgress) { |
|
|
|
|
_ui.listFilesButton->setEnabled(true); |
|
|
|
|
_listInProgress = false; |
|
|
|
|
_disconnectListSignals(); |
|
|
|
|
_ui.statusText->setText(tr("Error: ") + msg); |
|
|
|
|
QString statusText; |
|
|
|
|
|
|
|
|
|
if (_currentCommand == commandDownload) { |
|
|
|
|
_currentCommand = commandNone; |
|
|
|
|
_setAllButtonsEnabled(true); |
|
|
|
|
statusText = "Download complete"; |
|
|
|
|
} else if (_currentCommand == commandDownload) { |
|
|
|
|
_currentCommand = commandNone; |
|
|
|
|
_setAllButtonsEnabled(true); |
|
|
|
|
statusText = "Upload complete"; |
|
|
|
|
} else if (_currentCommand == commandList) { |
|
|
|
|
_listComplete(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ui.statusText->setText(statusText); |
|
|
|
|
_ui.progressBar->reset(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void QGCUASFileView::_listComplete(void) |
|
|
|
|
{ |
|
|
|
|
Q_ASSERT(_listInProgress); |
|
|
|
|
|
|
|
|
|
// Walk the current items, traversing down into directories
|
|
|
|
|
|
|
|
|
|
Again: |
|
|
|
@ -287,9 +258,8 @@ Again:
@@ -287,9 +258,8 @@ Again:
|
|
|
|
|
if (_walkIndexStack.count() != 0) { |
|
|
|
|
goto Again; |
|
|
|
|
} else { |
|
|
|
|
_ui.listFilesButton->setEnabled(true); |
|
|
|
|
_listInProgress = false; |
|
|
|
|
_disconnectListSignals(); |
|
|
|
|
_setAllButtonsEnabled(true); |
|
|
|
|
_currentCommand = commandNone; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -297,7 +267,7 @@ Again:
@@ -297,7 +267,7 @@ Again:
|
|
|
|
|
void QGCUASFileView::_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) |
|
|
|
|
{ |
|
|
|
|
Q_UNUSED(previous); |
|
|
|
|
// FIXME: Should not enable when downloading
|
|
|
|
|
|
|
|
|
|
_ui.downloadButton->setEnabled(current ? (current->type() == _typeFile) : false); |
|
|
|
|
_ui.uploadButton->setEnabled(current ? (current->type() == _typeDir) : false); |
|
|
|
|
} |
|
|
|
@ -307,51 +277,14 @@ void QGCUASFileView::_requestDirectoryList(const QString& dir)
@@ -307,51 +277,14 @@ void QGCUASFileView::_requestDirectoryList(const QString& dir)
|
|
|
|
|
_manager->listDirectory(dir); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Connects to the signals associated with the FileManager::downloadPath method. We only leave these signals connected
|
|
|
|
|
/// while a download because there may be multiple UAS, which in turn means multiple QGCUASFileView instances. We only want the signals
|
|
|
|
|
/// connected to the active FileView which is doing the current download.
|
|
|
|
|
void QGCUASFileView::_connectDownloadSignals(void) |
|
|
|
|
void QGCUASFileView::_setAllButtonsEnabled(bool enabled) |
|
|
|
|
{ |
|
|
|
|
bool success; |
|
|
|
|
Q_UNUSED(success); // Silence retail unused variable error
|
|
|
|
|
|
|
|
|
|
success = connect(_manager, SIGNAL(downloadFileLength(unsigned int)), this, SLOT(_downloadLength(unsigned int))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_manager, SIGNAL(downloadFileProgress(unsigned int)), this, SLOT(_downloadProgress(unsigned int))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_manager, SIGNAL(downloadFileComplete(void)), this, SLOT(_downloadComplete(void))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_manager, SIGNAL(errorMessage(const QString&)), this, SLOT(_downloadErrorMessage(const QString&))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void QGCUASFileView::_disconnectDownloadSignals(void) |
|
|
|
|
{ |
|
|
|
|
disconnect(_manager, SIGNAL(downloadFileLength(unsigned int)), this, SLOT(_downloadLength(unsigned int))); |
|
|
|
|
disconnect(_manager, SIGNAL(downloadFileProgress(unsigned int)), this, SLOT(_downloadProgress(unsigned int))); |
|
|
|
|
disconnect(_manager, SIGNAL(downloadFileComplete(void)), this, SLOT(_downloadComplete(void))); |
|
|
|
|
disconnect(_manager, SIGNAL(errorMessage(const QString&)), this, SLOT(_downloadErrorMessage(const QString&))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// @brief Connects to the signals associated with the FileManager::listDirectory method. We only leave these signals connected
|
|
|
|
|
/// while a download because there may be multiple UAS, which in turn means multiple QGCUASFileView instances. We only want the signals
|
|
|
|
|
/// connected to the active FileView which is doing the current download.
|
|
|
|
|
void QGCUASFileView::_connectListSignals(void) |
|
|
|
|
{ |
|
|
|
|
bool success; |
|
|
|
|
Q_UNUSED(success); // Silence retail unused variable error
|
|
|
|
|
_ui.treeWidget->setEnabled(enabled); |
|
|
|
|
_ui.downloadButton->setEnabled(enabled); |
|
|
|
|
_ui.listFilesButton->setEnabled(enabled); |
|
|
|
|
_ui.uploadButton->setEnabled(enabled); |
|
|
|
|
|
|
|
|
|
success = connect(_manager, SIGNAL(listEntry(const QString&)), this, SLOT(_listEntryReceived(const QString&))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_manager, SIGNAL(listComplete(void)), this, SLOT(_listComplete(void))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
success = connect(_manager, SIGNAL(errorMessage(const QString&)), this, SLOT(_listErrorMessage(const QString&))); |
|
|
|
|
Q_ASSERT(success); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void QGCUASFileView::_disconnectListSignals(void) |
|
|
|
|
{ |
|
|
|
|
disconnect(_manager, SIGNAL(listEntry(const QString&)), this, SLOT(_listEntryReceived(const QString&))); |
|
|
|
|
disconnect(_manager, SIGNAL(listComplete(void)), this, SLOT(_listComplete(void))); |
|
|
|
|
disconnect(_manager, SIGNAL(errorMessage(const QString&)), this, SLOT(_listErrorMessage(const QString&))); |
|
|
|
|
if (enabled) { |
|
|
|
|
_currentItemChanged(_ui.treeWidget->currentItem(), NULL); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|