diff --git a/src/libs/utils/ssh/sftpfilesystemmodel.cpp b/src/libs/utils/ssh/sftpfilesystemmodel.cpp index 37fbb83701d..3c534707427 100644 --- a/src/libs/utils/ssh/sftpfilesystemmodel.cpp +++ b/src/libs/utils/ssh/sftpfilesystemmodel.cpp @@ -94,6 +94,7 @@ public: SftpFileNode *rootNode; SftpJobId statJobId; DirNodeHash lsOps; + QList externalJobs; }; } // namespace Internal @@ -143,6 +144,19 @@ QString SftpFileSystemModel::rootDirectory() const 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 { Q_UNUSED(parent); @@ -344,21 +358,29 @@ void SftpFileSystemModel::handleFileInfo(SftpJobId jobId, const QListstatJobId) { d->statJobId = SftpInvalidJob; - path = rootDirectory(); - } else { - DirNodeHash::Iterator it = d->lsOps.find(jobId); - QTC_ASSERT(it != d->lsOps.end(), return); - QTC_CHECK(it.value()->lsState == SftpDirNode::LsRunning); - it.value()->lsState = SftpDirNode::LsFinished; - path = it.value()->path; - d->lsOps.erase(it); + if (!errorMessage.isEmpty()) + emit sftpOperationFailed(tr("Error getting 'stat' info about '%1': %2") + .arg(rootDirectory(), errorMessage)); + return; } - if (!errorMessage.isEmpty()) - emit sftpOperationFailed(tr("Error reading '%1': %2").arg(path, errorMessage)); + DirNodeHash::Iterator it = d->lsOps.find(jobId); + 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 diff --git a/src/libs/utils/ssh/sftpfilesystemmodel.h b/src/libs/utils/ssh/sftpfilesystemmodel.h index 1d9be4feead..f4b83799cd0 100644 --- a/src/libs/utils/ssh/sftpfilesystemmodel.h +++ b/src/libs/utils/ssh/sftpfilesystemmodel.h @@ -63,6 +63,8 @@ public: void setRootDirectory(const QString &path); // Default is "/". QString rootDirectory() const; + SftpJobId downloadFile(const QModelIndex &index, const QString &targetFilePath); + signals: /* * E.g. "Permission denied". Note that this can happen without direct user intervention, @@ -77,6 +79,9 @@ signals: */ void connectionError(const QString &errorMessage); + // Success <=> error.isEmpty(). + void sftpOperationFinished(Utils::SftpJobId, const QString &error); + private slots: void handleSshConnectionEstablished(); void handleSshConnectionFailure(); diff --git a/tests/manual/ssh/sftpfsmodel/window.cpp b/tests/manual/ssh/sftpfsmodel/window.cpp index 3b87c069203..bb8bb7816da 100644 --- a/tests/manual/ssh/sftpfsmodel/window.cpp +++ b/tests/manual/ssh/sftpfsmodel/window.cpp @@ -38,7 +38,11 @@ #include #include +#include +#include #include +#include +#include #include using namespace Utils; @@ -47,6 +51,7 @@ SftpFsWindow::SftpFsWindow(QWidget *parent) : QDialog(parent), m_ui(new Ui::Wind { m_ui->setupUi(this); connect(m_ui->connectButton, SIGNAL(clicked()), SLOT(connectToHost())); + connect(m_ui->downloadButton, SIGNAL(clicked()), SLOT(downloadFile())); } SftpFsWindow::~SftpFsWindow() @@ -64,19 +69,49 @@ void SftpFsWindow::connectToHost() sshParams.password = m_ui->passwordLineEdit->text(); sshParams.port = m_ui->portSpinBox->value(); sshParams.timeout = 10; - SftpFileSystemModel * const fsModel = new SftpFileSystemModel(this); + m_fsModel = new SftpFileSystemModel(this); if (m_ui->useModelTesterCheckBox->isChecked()) - new ModelTest(fsModel, this); - connect(fsModel, SIGNAL(sftpOperationFailed(QString)), + new ModelTest(m_fsModel, this); + connect(m_fsModel, SIGNAL(sftpOperationFailed(QString)), SLOT(handleSftpOperationFailed(QString))); - connect(fsModel, SIGNAL(connectionError(QString)), SLOT(handleConnectionError(QString))); - fsModel->setSshConnection(sshParams); - m_ui->fsView->setModel(fsModel); + connect(m_fsModel, SIGNAL(connectionError(QString)), SLOT(handleConnectionError(QString))); + connect(m_fsModel, SIGNAL(sftpOperationFinished(Utils::SftpJobId,QString)), + 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) { - 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) diff --git a/tests/manual/ssh/sftpfsmodel/window.h b/tests/manual/ssh/sftpfsmodel/window.h index 05e7c17730b..b403df0582f 100644 --- a/tests/manual/ssh/sftpfsmodel/window.h +++ b/tests/manual/ssh/sftpfsmodel/window.h @@ -29,6 +29,8 @@ ** Nokia at qt-info@nokia.com. ** **************************************************************************/ +#include + #include QT_BEGIN_NAMESPACE @@ -46,9 +48,12 @@ public: private slots: void connectToHost(); + void downloadFile(); void handleConnectionError(const QString &errorMessage); void handleSftpOperationFailed(const QString &errorMessage); + void handleSftpOperationFinished(Utils::SftpJobId jobId, const QString &error); private: + Utils::SftpFileSystemModel *m_fsModel; Ui::Window *m_ui; }; diff --git a/tests/manual/ssh/sftpfsmodel/window.ui b/tests/manual/ssh/sftpfsmodel/window.ui index fa5bd77e214..cf31e2bce6f 100644 --- a/tests/manual/ssh/sftpfsmodel/window.ui +++ b/tests/manual/ssh/sftpfsmodel/window.ui @@ -13,16 +13,13 @@ Dialog - + Connection Parameters - - QFormLayout::AllNonFixedFieldsGrow - @@ -103,9 +100,63 @@ Remote File System - + - + + + + + + 1 + 1 + + + + + + + + + + Connect + + + + + + + Download... + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + Debug output + + + + @@ -122,13 +173,6 @@ - - - - Connect - - -