#include "FtpDownloader.hpp"
#include <bb/cascades/Button>
#include <bb/cascades/Label>
#include <bb/cascades/ListView>
#include <bb/cascades/QmlDocument>
#include <bb/cascades/TextField>
#include <QtCore/QFile>
using namespace bb::cascades;
FtpDownloader::FtpDownloader(QObject *parent)
: QObject(parent)
, m_url(QLatin1String("ftp://ftp.kde.org"))
, m_ftp(0)
, m_file(0)
, m_parentDirectoryAvailable(false)
, m_downloadPossible(false)
, m_connectPossible(true)
, m_connectLabel(tr("Connect"))
, m_selectionPossible(false)
, m_networkSession(0)
{
m_statusText = tr("Please enter the name of an FTP server.");
emit statusTextChanged();
m_selectionPossible = false;
emit selectionPossibleChanged();
m_parentDirectoryAvailable = false;
emit parentDirectoryAvailableChanged();
m_downloadPossible = false;
emit downloadPossibleChanged();
connect(&m_progressDialogController, SIGNAL(canceled()), this, SLOT(cancelDownload()));
}
FtpDownloader::~FtpDownloader()
{
delete m_file;
m_file = 0;
}
void FtpDownloader::connectOrDisconnect()
{
if (m_ftp) {
m_ftp->abort();
m_ftp->deleteLater();
m_ftp = 0;
m_selectionPossible = false;
emit selectionPossibleChanged();
m_parentDirectoryAvailable = false;
emit parentDirectoryAvailableChanged();
m_downloadPossible = false;
emit downloadPossibleChanged();
m_connectPossible = true;
emit connectPossibleChanged();
m_connectLabel = tr("Connect");
emit connectLabelChanged();
m_statusText = tr("Please enter the name of an FTP server.");
emit statusTextChanged();
return;
}
if (!m_networkSession || !m_networkSession->isOpen()) {
if (m_manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired) {
if (!m_networkSession) {
QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
settings.beginGroup(QLatin1String("QtNetwork"));
const QString id = settings.value(QLatin1String("DefaultNetworkConfiguration")).toString();
settings.endGroup();
QNetworkConfiguration config = m_manager.configurationFromIdentifier(id);
if ((config.state() & QNetworkConfiguration::Discovered) != QNetworkConfiguration::Discovered) {
config = m_manager.defaultConfiguration();
}
m_networkSession = new QNetworkSession(config, this);
connect(m_networkSession, SIGNAL(opened()), this, SLOT(connectToFtp()));
connect(m_networkSession, SIGNAL(error(QNetworkSession::SessionError)),
this, SLOT(enableConnectButton()));
}
m_connectPossible = false;
emit connectPossibleChanged();
m_statusText = tr("Opening network session.");
emit statusTextChanged();
m_networkSession->open();
return;
}
}
connectToFtp();
}
void FtpDownloader::setUrl(const QString &url)
{
if (m_url != url) {
m_url = url;
emit urlChanged();
}
}
QString FtpDownloader::url() const
{
return m_url;
}
QString FtpDownloader::statusText() const
{
return m_statusText;
}
bool FtpDownloader::parentDirectoryAvailable() const
{
return m_parentDirectoryAvailable;
}
bool FtpDownloader::downloadPossible() const
{
return m_downloadPossible;
}
bool FtpDownloader::connectPossible() const
{
return m_connectPossible;
}
QString FtpDownloader::connectLabel() const
{
return m_connectLabel;
}
bool FtpDownloader::selectionPossible() const
{
return m_selectionPossible;
}
void FtpDownloader::connectToFtp()
{
m_ftp = new QFtp(this);
connect(m_ftp, SIGNAL(commandFinished(int,bool)),
this, SLOT(ftpCommandFinished(int,bool)));
connect(m_ftp, SIGNAL(listInfo(QUrlInfo)),
this, SLOT(addToList(QUrlInfo)));
connect(m_ftp, SIGNAL(dataTransferProgress(qint64,qint64)),
this, SLOT(updateDataTransferProgress(qint64,qint64)));
m_model.clear();
m_currentPath.clear();
const QUrl url(m_url);
if (!url.isValid() || url.scheme().toLower() != QLatin1String("ftp")) {
m_ftp->connectToHost(m_url, 21);
m_ftp->login();
} else {
m_ftp->connectToHost(url.host(), url.port(21));
if (!url.userName().isEmpty())
m_ftp->login(QUrl::fromPercentEncoding(url.userName().toLatin1()), url.password());
else
m_ftp->login();
if (!url.path().isEmpty()) {
m_currentPath = url.path();
if (m_currentPath.endsWith('/'))
m_currentPath.chop(1);
m_ftp->cd(m_currentPath);
}
}
m_selectionPossible = true;
emit selectionPossibleChanged();
m_connectPossible = false;
emit connectPossibleChanged();
m_connectLabel = tr("Disconnect");
emit connectLabelChanged();
m_statusText = tr("Connecting to FTP server %1...").arg(m_url);
emit statusTextChanged();
}
void FtpDownloader::downloadFile()
{
const QVariant data = m_model.data(m_currentIndexPath);
if (!data.isValid()) {
enableDownloadButton();
return;
}
const FtpItem currentItem = data.value<FtpItem>();
m_downloadFileName = currentItem.fileName;
const QString diskFileName = "tmp/" + m_downloadFileName;
if (QFile::exists(diskFileName)) {
m_messageBoxController.exec(tr("FTP"),
tr("There already exists a file called %1 in %2.").arg(diskFileName).arg("tmp/"),
tr("Ok"), QString());
return;
}
m_file = new QFile(diskFileName);
if (!m_file->open(QIODevice::WriteOnly)) {
m_messageBoxController.exec(tr("FTP"),
tr("Unable to save the file %1: %2.").arg(diskFileName).arg(m_file->errorString()),
tr("Ok"), QString());
delete m_file;
m_file = 0;
return;
}
m_ftp->get(m_downloadFileName, m_file);
m_progressDialogController.setLabelText(tr("Downloading %1...").arg(m_downloadFileName));
m_downloadPossible = false;
emit downloadPossibleChanged();
m_progressDialogController.show();
}
void FtpDownloader::cancelDownload()
{
m_ftp->abort();
if (m_file->exists()) {
m_file->close();
m_file->remove();
}
delete m_file;
m_file = 0;
}
void FtpDownloader::ftpCommandFinished(int, bool error)
{
if (m_ftp->currentCommand() == QFtp::ConnectToHost) {
if (error) {
m_messageBoxController.exec(tr("FTP"), tr("Unable to connect to the FTP server "
"at %1. Please check that the host "
"name is correct.").arg(m_url),
tr("Ok"), QString());
connectOrDisconnect();
return;
}
m_statusText = tr("Logged onto %1.").arg(m_url);
emit statusTextChanged();
m_connectPossible = true;
emit connectPossibleChanged();
return;
}
if (m_ftp->currentCommand() == QFtp::Login)
m_ftp->list();
if (m_ftp->currentCommand() == QFtp::Get) {
if (error) {
m_statusText = tr("Canceled download of %1.").arg(m_downloadFileName);
emit statusTextChanged();
if (m_file) {
m_file->close();
m_file->remove();
}
} else {
if (m_file) {
const QFileInfo actualDir(*m_file);
m_statusText = tr("Downloaded %1 to %2.").arg(m_downloadFileName).arg(actualDir.absolutePath());
emit statusTextChanged();
m_file->close();
} else {
m_statusText = tr("Canceled download of %1.").arg(m_downloadFileName);
emit statusTextChanged();
}
}
delete m_file;
m_file = 0;
enableDownloadButton();
m_progressDialogController.hide();
} else if (m_ftp->currentCommand() == QFtp::List) {
if (m_model.isEmpty()) {
FtpItem item;
item.fileName = tr("<empty>");
m_model.append(item);
m_selectionPossible = false;
emit selectionPossibleChanged();
}
if (!m_currentPath.isEmpty()) {
m_parentDirectoryAvailable = true;
emit parentDirectoryAvailableChanged();
}
}
}
void FtpDownloader::addToList(const QUrlInfo &urlInfo)
{
FtpItem item;
item.fileName = urlInfo.name();
item.fileSize = urlInfo.size();
item.owner = urlInfo.owner();
item.group = urlInfo.group();
item.time = urlInfo.lastModified();
item.isDirectory = urlInfo.isDir();
const bool wasEmpty = m_model.isEmpty();
m_model.append(item);
if (wasEmpty) {
m_selectionPossible = true;
emit selectionPossibleChanged();
}
}
void FtpDownloader::processItem(const QVariantList &indexPath)
{
if (!m_selectionPossible)
return;
m_currentIndexPath = indexPath;
enableDownloadButton();
if (!indexPath.isEmpty()) {
const FtpItem item = m_model.data(indexPath).value<FtpItem>();
if (item.isDirectory) {
m_model.clear();
m_currentPath += '/';
m_currentPath += item.fileName;
m_ftp->cd(item.fileName);
m_ftp->list();
m_parentDirectoryAvailable = true;
emit parentDirectoryAvailableChanged();
return;
}
}
}
void FtpDownloader::cdToParent()
{
m_model.clear();
m_currentIndexPath.clear();
enableDownloadButton();
m_currentPath = m_currentPath.left(m_currentPath.lastIndexOf('/'));
if (m_currentPath.isEmpty()) {
m_parentDirectoryAvailable = false;
emit parentDirectoryAvailableChanged();
m_ftp->cd("/");
} else {
m_ftp->cd(m_currentPath);
}
m_ftp->list();
}
void FtpDownloader::updateDataTransferProgress(qint64 readBytes, qint64 totalBytes)
{
const float progress = readBytes / (float) totalBytes * 100.0f;
m_progressDialogController.setProgress(progress);
}
void FtpDownloader::enableDownloadButton()
{
const QVariant itemData = m_model.data(m_currentIndexPath);
if (itemData.isValid()) {
const FtpItem item = itemData.value<FtpItem>();
m_downloadPossible = !item.isDirectory;
} else {
m_downloadPossible = false;
}
emit downloadPossibleChanged();
}
void FtpDownloader::enableConnectButton()
{
QNetworkConfiguration config = m_networkSession->configuration();
QString id;
if (config.type() == QNetworkConfiguration::UserChoice)
id = m_networkSession->sessionProperty(QLatin1String("UserChoiceConfiguration")).toString();
else
id = config.identifier();
QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
settings.beginGroup(QLatin1String("QtNetwork"));
settings.setValue(QLatin1String("DefaultNetworkConfiguration"), id);
settings.endGroup();
m_connectPossible = true;
emit connectPossibleChanged();
m_statusText = tr("Please enter the name of an FTP server.");
emit statusTextChanged();
}
bb::cascades::QListDataModel<FtpItem> *FtpDownloader::model()
{
return &m_model;
}
MessageBoxController *FtpDownloader::messageBoxController()
{
return &m_messageBoxController;
}
ProgressDialogController *FtpDownloader::progressDialogController()
{
return &m_progressDialogController;
}