Commit 84cd97ca authored by Don Gagne's avatar Don Gagne

Changed FTP to tree view

Also added selection from tree view for downloading
parent 2b88c6e9
...@@ -99,11 +99,6 @@ quint32 QGCUASFileManager::crc32(Request* request, unsigned state) ...@@ -99,11 +99,6 @@ quint32 QGCUASFileManager::crc32(Request* request, unsigned state)
return state; return state;
} }
void QGCUASFileManager::nothingMessage()
{
// FIXME: Connect ui correctly
}
/// @brief Respond to the Ack associated with the Open command with the next Read command. /// @brief Respond to the Ack associated with the Open command with the next Read command.
void QGCUASFileManager::_openAckResponse(Request* openAck) void QGCUASFileManager::_openAckResponse(Request* openAck)
{ {
...@@ -220,17 +215,11 @@ void QGCUASFileManager::_listAckResponse(Request* listAck) ...@@ -220,17 +215,11 @@ void QGCUASFileManager::_listAckResponse(Request* listAck)
_emitErrorMessage(tr("Missing NULL termination in list entry")); _emitErrorMessage(tr("Missing NULL termination in list entry"));
return; return;
} }
// Returned names are prepended with D for directory, F for file, U for unknown
QString s(ptr + 1); // Returned names are prepended with D for directory, F for file, U for unknown
if (*ptr == 'D') {
s.append('/');
}
if (*ptr == 'F' || *ptr == 'D') { if (*ptr == 'F' || *ptr == 'D') {
// put it in the view // put it in the view
_emitStatusMessage(s); _emitStatusMessage(ptr);
} }
// account for the name + NUL // account for the name + NUL
...@@ -243,6 +232,7 @@ void QGCUASFileManager::_listAckResponse(Request* listAck) ...@@ -243,6 +232,7 @@ void QGCUASFileManager::_listAckResponse(Request* listAck)
// Directory is empty, we're done // Directory is empty, we're done
Q_ASSERT(listAck->hdr.opcode == kRspAck); Q_ASSERT(listAck->hdr.opcode == kRspAck);
_currentOperation = kCOIdle; _currentOperation = kCOIdle;
emit listComplete();
} else { } else {
// Possibly more entries to come, need to keep trying till we get EOF // Possibly more entries to come, need to keep trying till we get EOF
_currentOperation = kCOList; _currentOperation = kCOList;
...@@ -307,6 +297,7 @@ void QGCUASFileManager::receiveMessage(LinkInterface* link, mavlink_message_t me ...@@ -307,6 +297,7 @@ void QGCUASFileManager::receiveMessage(LinkInterface* link, mavlink_message_t me
if (previousOperation == kCOList && errorCode == kErrEOF) { if (previousOperation == kCOList && errorCode == kErrEOF) {
// This is not an error, just the end of the read loop // This is not an error, just the end of the read loop
emit listComplete();
return; return;
} else if (previousOperation == kCORead && errorCode == kErrEOF) { } else if (previousOperation == kCORead && errorCode == kErrEOF) {
// This is not an error, just the end of the read loop // This is not an error, just the end of the read loop
......
...@@ -43,11 +43,11 @@ public: ...@@ -43,11 +43,11 @@ public:
signals: signals:
void statusMessage(const QString& msg); void statusMessage(const QString& msg);
void resetStatusMessages(); void resetStatusMessages();
void errorMessage(const QString& ms); void errorMessage(const QString& msg);
void listComplete(void);
public slots: public slots:
void receiveMessage(LinkInterface* link, mavlink_message_t message); void receiveMessage(LinkInterface* link, mavlink_message_t message);
void nothingMessage();
void listDirectory(const QString& dirPath); void listDirectory(const QString& dirPath);
void downloadPath(const QString& from, const QDir& downloadDir); void downloadPath(const QString& from, const QDir& downloadDir);
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "QGCUASFileView.h" #include "QGCUASFileView.h"
#include "uas/QGCUASFileManager.h" #include "uas/QGCUASFileManager.h"
#include "ui_QGCUASFileView.h"
#include <QFileDialog> #include <QFileDialog>
#include <QDir> #include <QDir>
#include <QMessageBox>
QGCUASFileView::QGCUASFileView(QWidget *parent, QGCUASFileManager *manager) : QGCUASFileView::QGCUASFileView(QWidget *parent, QGCUASFileManager *manager) :
QWidget(parent), QWidget(parent),
_manager(manager), _manager(manager)
ui(new Ui::QGCUASFileView)
{ {
ui->setupUi(this); _ui.setupUi(this);
connect(ui->testButton, SIGNAL(clicked()), _manager, SLOT(nothingMessage())); bool success = connect(_ui.listFilesButton, SIGNAL(clicked()), this, SLOT(_refreshTree()));
connect(ui->listFilesButton, SIGNAL(clicked()), this, SLOT(listFiles())); Q_ASSERT(success);
connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(downloadFiles())); success = connect(_ui.downloadButton, SIGNAL(clicked()), this, SLOT(_downloadFiles()));
Q_ASSERT(success);
success = connect(_ui.treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(_currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
Q_ASSERT(success);
Q_UNUSED(success);
}
connect(_manager, SIGNAL(statusMessage(QString)), ui->messageArea, SLOT(appendPlainText(QString))); void QGCUASFileView::_downloadFiles(void)
connect(_manager, SIGNAL(errorMessage(QString)), ui->messageArea, SLOT(appendPlainText(QString))); {
connect(_manager, SIGNAL(resetStatusMessages()), ui->messageArea, SLOT(clear())); QString dir = QFileDialog::getExistingDirectory(this, tr("Download Directory"),
QDir::homePath(),
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);
// And now download to this location
QString path;
QTreeWidgetItem* item = _ui.treeWidget->currentItem();
if (item && item->type() == _typeFile) {
do {
path.prepend("/" + item->text(0));
item = item->parent();
} while (item);
qDebug() << "Download: " << path;
bool success = connect(_manager, SIGNAL(statusMessage(QString)), this, SLOT(_downloadStatusMessage(QString)));
Q_ASSERT(success);
success = connect(_manager, SIGNAL(errorMessage(QString)), this, SLOT(_downloadStatusMessage(QString)));
Q_ASSERT(success);
Q_UNUSED(success);
_manager->downloadPath(path, QDir(dir));
}
} }
QGCUASFileView::~QGCUASFileView() void QGCUASFileView::_refreshTree(void)
{ {
delete ui; QTreeWidgetItem* item;
for (int i=_ui.treeWidget->invisibleRootItem()->childCount(); i>=0; i--) {
item = _ui.treeWidget->takeTopLevelItem(i);
delete item;
}
_walkIndexStack.clear();
_walkItemStack.clear();
_walkIndexStack.append(0);
_walkItemStack.append(_ui.treeWidget->invisibleRootItem());
bool success = connect(_manager, SIGNAL(statusMessage(QString)), this, SLOT(_treeStatusMessage(QString)));
Q_ASSERT(success);
success = connect(_manager, SIGNAL(errorMessage(QString)), this, SLOT(_treeErrorMessage(QString)));
Q_ASSERT(success);
success = connect(_manager, SIGNAL(listComplete(void)), this, SLOT(_listComplete(void)));
Q_ASSERT(success);
Q_UNUSED(success);
qDebug() << "List: /";
_manager->listDirectory("/");
} }
void QGCUASFileView::listFiles() void QGCUASFileView::_treeStatusMessage(const QString& msg)
{ {
_manager->listDirectory(ui->pathLineEdit->text()); int type;
if (msg.startsWith("F")) {
type = _typeFile;
} else if (msg.startsWith("D")) {
type = _typeDir;
if (msg == "D." || msg == "D..") {
return;
}
} else {
Q_ASSERT(false);
}
QTreeWidgetItem* item;
if (_walkItemStack.count() == 0) {
item = new QTreeWidgetItem(_ui.treeWidget, type);
} else {
item = new QTreeWidgetItem(_walkItemStack.last(), type);
}
Q_CHECK_PTR(item);
item->setText(0, msg.right(msg.size() - 1));
} }
void QGCUASFileView::downloadFiles() void QGCUASFileView::_treeErrorMessage(const QString& msg)
{ {
QString dir = QFileDialog::getExistingDirectory(this, tr("Download Directory"), QTreeWidgetItem* item;
QDir::homePath(), if (_walkItemStack.count() == 0) {
QFileDialog::ShowDirsOnly item = new QTreeWidgetItem(_ui.treeWidget, _typeError);
| QFileDialog::DontResolveSymlinks); } else {
// And now download to this location item = new QTreeWidgetItem(_walkItemStack.last(), _typeError);
_manager->downloadPath(ui->pathLineEdit->text(), QDir(dir)); }
Q_CHECK_PTR(item);
item->setText(0, tr("Error: ") + msg);
}
void QGCUASFileView::_listComplete(void)
{
// Walk the current items, traversing down into directories
Again:
int walkIndex = _walkIndexStack.last();
QTreeWidgetItem* parentItem = _walkItemStack.last();
QTreeWidgetItem* childItem = parentItem->child(walkIndex);
// Loop until we hit a directory
while (childItem && childItem->type() != _typeDir) {
// Move to next index at current level
_walkIndexStack.last() = ++walkIndex;
childItem = parentItem->child(walkIndex);
}
if (childItem) {
// Process this item
QString text = childItem->text(0);
// Move to the next item for processing at this level
_walkIndexStack.last() = ++walkIndex;
// Push this new directory on the stack
_walkItemStack.append(childItem);
_walkIndexStack.append(0);
// Ask for the directory list
QString dir;
for (int i=1; i<_walkItemStack.count(); i++) {
QTreeWidgetItem* item = _walkItemStack[i];
dir.append("/" + item->text(0));
}
qDebug() << "List:" << dir;
_manager->listDirectory(dir);
} else {
// We have run out of items at the this level, pop the stack and keep going at that level
_walkIndexStack.removeLast();
_walkItemStack.removeLast();
if (_walkIndexStack.count() != 0) {
goto Again;
} else {
disconnect(_manager, SIGNAL(statusMessage(QString)), this, SLOT(_treeStatusMessage(QString)));
disconnect(_manager, SIGNAL(errorMessage(QString)), this, SLOT(_treeErrorMessage(QString)));
disconnect(_manager, SIGNAL(listComplete(void)), this, SLOT(_listComplete(void)));
}
}
}
void QGCUASFileView::_downloadStatusMessage(const QString& msg)
{
disconnect(_manager, SIGNAL(statusMessage(QString)), this, SLOT(_downloadStatusMessage(QString)));
disconnect(_manager, SIGNAL(errorMessage(QString)), this, SLOT(_downloadStatusMessage(QString)));
QMessageBox msgBox;
msgBox.setWindowModality(Qt::ApplicationModal);
msgBox.setText(msg);
msgBox.exec();
}
void QGCUASFileView::_currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
{
Q_UNUSED(previous);
_ui.downloadButton->setEnabled(current->type() == _typeFile);
} }
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef QGCUASFILEVIEW_H #ifndef QGCUASFILEVIEW_H
#define QGCUASFILEVIEW_H #define QGCUASFILEVIEW_H
#include <QWidget> #include <QWidget>
#include "uas/QGCUASFileManager.h" #include <QTreeWidgetItem>
namespace Ui { #include "uas/QGCUASFileManager.h"
class QGCUASFileView; #include "ui_QGCUASFileView.h"
}
class QGCUASFileView : public QWidget class QGCUASFileView : public QWidget
{ {
...@@ -14,17 +36,27 @@ class QGCUASFileView : public QWidget ...@@ -14,17 +36,27 @@ class QGCUASFileView : public QWidget
public: public:
explicit QGCUASFileView(QWidget *parent, QGCUASFileManager *manager); explicit QGCUASFileView(QWidget *parent, QGCUASFileManager *manager);
~QGCUASFileView();
public slots:
void listFiles();
void downloadFiles();
protected: protected:
QGCUASFileManager* _manager; QGCUASFileManager* _manager;
private slots:
void _refreshTree(void);
void _downloadFiles(void);
void _treeStatusMessage(const QString& msg);
void _treeErrorMessage(const QString& msg);
void _listComplete(void);
void _downloadStatusMessage(const QString& msg);
void _currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
private: private:
Ui::QGCUASFileView *ui; static const int _typeFile = QTreeWidgetItem::UserType + 1;
static const int _typeDir = QTreeWidgetItem::UserType + 2;
static const int _typeError = QTreeWidgetItem::UserType + 3;
QList<int> _walkIndexStack;
QList<QTreeWidgetItem*> _walkItemStack;
Ui::QGCUASFileView _ui;
}; };
#endif // QGCUASFILEVIEW_H #endif // QGCUASFILEVIEW_H
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="3" column="1"> <item row="1" column="1">
<widget class="QPushButton" name="listFilesButton"> <widget class="QPushButton" name="listFilesButton">
<property name="text"> <property name="text">
<string>List Files</string> <string>List Files</string>
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
</widget> </widget>
</item> </item>
<item row="0" column="0" colspan="3"> <item row="0" column="0" colspan="3">
<widget class="QPlainTextEdit" name="messageArea"/>
</item>
<item row="1" column="0" colspan="3">
<widget class="QTreeWidget" name="treeWidget"> <widget class="QTreeWidget" name="treeWidget">
<property name="headerHidden">
<bool>true</bool>
</property>
<column> <column>
<property name="text"> <property name="text">
<string notr="true">1</string> <string notr="true">1</string>
...@@ -33,30 +33,16 @@ ...@@ -33,30 +33,16 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="1" column="2">
<widget class="QPushButton" name="testButton">
<property name="text">
<string>Null Message</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="downloadButton"> <widget class="QPushButton" name="downloadButton">
<property name="text"> <property name="enabled">
<string>Download File</string> <bool>false</bool>
</property> </property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Path:</string> <string>Download File</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="pathLineEdit"/>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment