SSH: Add download capability to SftpFileSystemModel.

Change-Id: I156fa2ecc179f7f9a75ea0c1357b7e6881f5740f
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Christian Kandeler
2012-02-06 12:03:08 +01:00
committed by hjk
parent 051569b998
commit 05aa2b01fe
5 changed files with 142 additions and 31 deletions

View File

@@ -94,6 +94,7 @@ public:
SftpFileNode *rootNode; SftpFileNode *rootNode;
SftpJobId statJobId; SftpJobId statJobId;
DirNodeHash lsOps; DirNodeHash lsOps;
QList<SftpJobId> externalJobs;
}; };
} // namespace Internal } // namespace Internal
@@ -143,6 +144,19 @@ QString SftpFileSystemModel::rootDirectory() const
return d->rootDirectory; return d->rootDirectory;
} }
SftpJobId SftpFileSystemModel::downloadFile(const QModelIndex &index, const QString &targetFilePath)
{
QTC_ASSERT(d->rootNode, return SftpInvalidJob);
const SftpFileNode * const fileNode = indexToFileNode(index);
QTC_ASSERT(fileNode, return SftpInvalidJob);
QTC_ASSERT(fileNode->fileInfo.type == FileTypeRegular, return SftpInvalidJob);
const SftpJobId jobId = d->sftpChannel->downloadFile(fileNode->path, targetFilePath,
SftpOverwriteExisting);
if (jobId != SftpInvalidJob)
d->externalJobs << jobId;
return jobId;
}
int SftpFileSystemModel::columnCount(const QModelIndex &parent) const int SftpFileSystemModel::columnCount(const QModelIndex &parent) const
{ {
Q_UNUSED(parent); Q_UNUSED(parent);
@@ -344,21 +358,29 @@ void SftpFileSystemModel::handleFileInfo(SftpJobId jobId, const QList<SftpFileIn
void SftpFileSystemModel::handleSftpJobFinished(SftpJobId jobId, const QString &errorMessage) void SftpFileSystemModel::handleSftpJobFinished(SftpJobId jobId, const QString &errorMessage)
{ {
QString path;
if (jobId == d->statJobId) { if (jobId == d->statJobId) {
d->statJobId = SftpInvalidJob; d->statJobId = SftpInvalidJob;
path = rootDirectory(); if (!errorMessage.isEmpty())
} else { emit sftpOperationFailed(tr("Error getting 'stat' info about '%1': %2")
DirNodeHash::Iterator it = d->lsOps.find(jobId); .arg(rootDirectory(), errorMessage));
QTC_ASSERT(it != d->lsOps.end(), return); return;
QTC_CHECK(it.value()->lsState == SftpDirNode::LsRunning);
it.value()->lsState = SftpDirNode::LsFinished;
path = it.value()->path;
d->lsOps.erase(it);
} }
if (!errorMessage.isEmpty()) DirNodeHash::Iterator it = d->lsOps.find(jobId);
emit sftpOperationFailed(tr("Error reading '%1': %2").arg(path, errorMessage)); if (it != d->lsOps.end()) {
QTC_CHECK(it.value()->lsState == SftpDirNode::LsRunning);
it.value()->lsState = SftpDirNode::LsFinished;
if (!errorMessage.isEmpty())
emit sftpOperationFailed(tr("Error listing contents of directory '%1': %2")
.arg(it.value()->path, errorMessage));
d->lsOps.erase(it);
return;
}
const int jobIndex = d->externalJobs.indexOf(jobId);
QTC_ASSERT(jobIndex != -1, return);
d->externalJobs.removeAt(jobIndex);
emit sftpOperationFinished(jobId, errorMessage);
} }
} // namespace Utils } // namespace Utils

View File

@@ -63,6 +63,8 @@ public:
void setRootDirectory(const QString &path); // Default is "/". void setRootDirectory(const QString &path); // Default is "/".
QString rootDirectory() const; QString rootDirectory() const;
SftpJobId downloadFile(const QModelIndex &index, const QString &targetFilePath);
signals: signals:
/* /*
* E.g. "Permission denied". Note that this can happen without direct user intervention, * E.g. "Permission denied". Note that this can happen without direct user intervention,
@@ -77,6 +79,9 @@ signals:
*/ */
void connectionError(const QString &errorMessage); void connectionError(const QString &errorMessage);
// Success <=> error.isEmpty().
void sftpOperationFinished(Utils::SftpJobId, const QString &error);
private slots: private slots:
void handleSshConnectionEstablished(); void handleSshConnectionEstablished();
void handleSshConnectionFailure(); void handleSshConnectionFailure();

View File

@@ -38,7 +38,11 @@
#include <utils/ssh/sshconnection.h> #include <utils/ssh/sshconnection.h>
#include <QApplication> #include <QApplication>
#include <QDir>
#include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QModelIndexList>
#include <QItemSelectionModel>
#include <QString> #include <QString>
using namespace Utils; using namespace Utils;
@@ -47,6 +51,7 @@ SftpFsWindow::SftpFsWindow(QWidget *parent) : QDialog(parent), m_ui(new Ui::Wind
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->connectButton, SIGNAL(clicked()), SLOT(connectToHost())); connect(m_ui->connectButton, SIGNAL(clicked()), SLOT(connectToHost()));
connect(m_ui->downloadButton, SIGNAL(clicked()), SLOT(downloadFile()));
} }
SftpFsWindow::~SftpFsWindow() SftpFsWindow::~SftpFsWindow()
@@ -64,19 +69,49 @@ void SftpFsWindow::connectToHost()
sshParams.password = m_ui->passwordLineEdit->text(); sshParams.password = m_ui->passwordLineEdit->text();
sshParams.port = m_ui->portSpinBox->value(); sshParams.port = m_ui->portSpinBox->value();
sshParams.timeout = 10; sshParams.timeout = 10;
SftpFileSystemModel * const fsModel = new SftpFileSystemModel(this); m_fsModel = new SftpFileSystemModel(this);
if (m_ui->useModelTesterCheckBox->isChecked()) if (m_ui->useModelTesterCheckBox->isChecked())
new ModelTest(fsModel, this); new ModelTest(m_fsModel, this);
connect(fsModel, SIGNAL(sftpOperationFailed(QString)), connect(m_fsModel, SIGNAL(sftpOperationFailed(QString)),
SLOT(handleSftpOperationFailed(QString))); SLOT(handleSftpOperationFailed(QString)));
connect(fsModel, SIGNAL(connectionError(QString)), SLOT(handleConnectionError(QString))); connect(m_fsModel, SIGNAL(connectionError(QString)), SLOT(handleConnectionError(QString)));
fsModel->setSshConnection(sshParams); connect(m_fsModel, SIGNAL(sftpOperationFinished(Utils::SftpJobId,QString)),
m_ui->fsView->setModel(fsModel); SLOT(handleSftpOperationFinished(Utils::SftpJobId,QString)));
m_fsModel->setSshConnection(sshParams);
m_ui->fsView->setModel(m_fsModel);
}
void SftpFsWindow::downloadFile()
{
const QModelIndexList selectedIndexes = m_ui->fsView->selectionModel()->selectedIndexes();
if (selectedIndexes.count() != 2)
return;
const QString targetFilePath = QFileDialog::getSaveFileName(this, tr("Choose target file"),
QDir::tempPath());
if (targetFilePath.isEmpty())
return;
const SftpJobId jobId = m_fsModel->downloadFile(selectedIndexes.at(1), targetFilePath);
QString message;
if (jobId == SftpInvalidJob)
message = tr("Download failed.");
else
message = tr("Queuing download operation %1.").arg(jobId);
m_ui->outputTextEdit->appendPlainText(message);
} }
void SftpFsWindow::handleSftpOperationFailed(const QString &errorMessage) void SftpFsWindow::handleSftpOperationFailed(const QString &errorMessage)
{ {
qDebug("%s: %s", Q_FUNC_INFO, qPrintable(errorMessage)); m_ui->outputTextEdit->appendPlainText(errorMessage);
}
void SftpFsWindow::handleSftpOperationFinished(SftpJobId jobId, const QString &error)
{
QString message;
if (error.isEmpty())
message = tr("Operation %1 finished successfully.").arg(jobId);
else
message = tr("Operation %1 failed: %2.").arg(jobId).arg(error);
m_ui->outputTextEdit->appendPlainText(message);
} }
void SftpFsWindow::handleConnectionError(const QString &errorMessage) void SftpFsWindow::handleConnectionError(const QString &errorMessage)

View File

@@ -29,6 +29,8 @@
** Nokia at qt-info@nokia.com. ** Nokia at qt-info@nokia.com.
** **
**************************************************************************/ **************************************************************************/
#include <utils/ssh/sftpdefs.h>
#include <QDialog> #include <QDialog>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -46,9 +48,12 @@ public:
private slots: private slots:
void connectToHost(); void connectToHost();
void downloadFile();
void handleConnectionError(const QString &errorMessage); void handleConnectionError(const QString &errorMessage);
void handleSftpOperationFailed(const QString &errorMessage); void handleSftpOperationFailed(const QString &errorMessage);
void handleSftpOperationFinished(Utils::SftpJobId jobId, const QString &error);
private: private:
Utils::SftpFileSystemModel *m_fsModel;
Ui::Window *m_ui; Ui::Window *m_ui;
}; };

View File

@@ -13,16 +13,13 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Dialog</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string>Connection Parameters</string> <string>Connection Parameters</string>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
@@ -103,9 +100,63 @@
<property name="title"> <property name="title">
<string>Remote File System</string> <string>Remote File System</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QTreeView" name="fsView"/> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTreeView" name="fsView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="connectButton">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="downloadButton">
<property name="text">
<string>Download...</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Debug output</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="outputTextEdit"/>
</item> </item>
</layout> </layout>
</widget> </widget>
@@ -122,13 +173,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="connectButton">
<property name="text">
<string>Connect</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>